Scaffold an Arkor project in the current directory.
Scaffolds src/arkor/index.ts, src/arkor/trainer.ts, arkor.config.ts, and a starter package.json in the current directory. Use this when you want to add Arkor to an existing repo (the Quickstart scaffolding flow runs the same scaffolder one directory up).
arkor init [options]pnpm arkor initnpm arkor inityarn arkor inityarn run arkor initbun arkor init| Flag | Description |
|---|---|
-y, --yes | Accept defaults instead of prompting (project name from the directory name, template triage). |
--name <name> | Project name. Defaults to the current directory's name (arkor-project if the path has no basename, e.g. /). The value is sanitised before it lands in package.json. |
--template <id> | Starter template. Options: triage, translate, redaction. Unknown ids throw before any filesystem work. |
--skip-install | Skip running the package manager's install step after scaffolding. |
--use-npm | Force npm as the package manager. |
--use-pnpm | Force pnpm as the package manager. |
--use-yarn | Force yarn as the package manager. |
--use-bun | Force bun as the package manager. Known limitation on Windows: arkor init --use-bun populates node_modules but does not produce bun.lock, so the initial commit will not include a lockfile. Running bun install directly and using create-arkor --use-bun are not affected. |
--git | Initialise a git repo and create an initial commit, without asking. |
--skip-git | Skip git init silently. |
--allow-builds | Opt esbuild's postinstall script into running on pnpm install. pnpm-only (yarn / npm / bun ignore the workspace yaml). Default: deny. See Postinstall scripts (pnpm 11+) below. |
--agents-md | Write AGENTS.md and CLAUDE.md to brief AI coding agents that arkor post-dates their training data. Default. |
--no-agents-md | Skip generating AGENTS.md / CLAUDE.md. An existing user-authored AGENTS.md is always preserved; the arkor-managed block (delimited by <!-- BEGIN:arkor-agent-rules --> / <!-- END:arkor-agent-rules -->) is appended on first run and replaced in place on re-scaffold. |
--git and --skip-git are mutually exclusive; passing both throws. The same goes for --agents-md and --no-agents-md.
By default, the command is partly interactive: it prompts for a project name, a starter template, and (when not in a git repo) whether to run git init, and only then starts the package manager's install step (no confirmation prompt) unless --skip-install is set. The git init confirmation is surfaced before install so you can answer every prompt upfront and walk away while install runs unattended; the actual git init + initial commit still execute after install so the generated lockfile lands in the initial commit. If no package manager can be resolved (no --use-* flag and detection from npm_config_user_agent fails), the install step is skipped and the outro prints a manual install hint.
When the chosen package manager is pnpm (explicitly via --use-pnpm, detected as pnpm from npm_config_user_agent such as pnpm arkor init, or implicitly because pm detection didn't resolve and the target is a fresh empty directory), the scaffold writes a small pnpm-workspace.yaml alongside package.json:
packages: []
allowBuilds:
esbuild: falseThe file is not written when:
--use-npm / --use-yarn / --use-bun is set (those toolchains don't read it).--use-* flag is set (we don't drop workspace-level config into someone else's project on a guess).pnpm-workspace.yaml (the parent monorepo workspace governs; creating a nested one here would shadow it and break workspace:* resolution above).If pnpm-workspace.yaml already exists at the target AND pnpm is plausible (the same --use-pnpm / UA-detected pnpm / unresolved-detection conditions that gate fresh creation above; --use-npm / --use-yarn / --use-bun runs leave any existing file untouched), the scaffold patches it: it appends esbuild: false (or esbuild: true if --allow-builds is set) to the existing top-level allowBuilds: block (or creates one) without touching unrelated keys, and bows out as a no-op for the allowBuilds decision when esbuild is already pinned (allow or deny) or when the file uses the global scalar form allowBuilds: false / allowBuilds: true. Note that an allowBuilds-no-op run can still modify the file in one other way: a top-level packages: key is backfilled as packages: [] if missing, since pnpm 9 errors with "packages field missing or empty" against a pnpm-workspace.yaml that has no packages: declaration. The allowBuilds.esbuild decision is what's preserved; the file itself may pick up that one structural key.
pnpm 11 changed the default for postinstall scripts to "deny unless explicitly approved", and exits with ERR_PNPM_IGNORED_BUILDS (code 1) when an unapproved script is encountered. esbuild ships such a script (node install.js, which verifies/downloads the platform-specific binary), so a vanilla pnpm install against a freshly scaffolded project would otherwise fail.
The scaffolded allowBuilds: { esbuild: false } is an explicit deny: pnpm sees a decision and silently skips the script instead of erroring. esbuild itself still works, because pnpm already installs @esbuild/<platform> as an optionalDependency. yarn / npm / bun all ignore pnpm-workspace.yaml, so the file is inert under those package managers.
If you genuinely need esbuild's postinstall to run (rare; usually a broken installer or unusual platform), pass --allow-builds:
pnpm arkor init --yes --use-pnpm --allow-buildsOr flip the entry to true in pnpm-workspace.yaml after the fact. The flag is only consulted on runs that actually emit or patch pnpm-workspace.yaml, so passing it under --use-npm / --use-yarn / --use-bun is a no-op (those runs don't touch the file at all). Re-run arkor init --use-pnpm --allow-builds later if you switch to pnpm.
| Template | Task | Output shape |
|---|---|---|
triage | Support triage | { category, urgency, summary, nextAction } |
translate | 9-language translation | { translation, detectedLanguage } |
redaction | PII redaction | { redactedText, redactedCount, tags } |
All three pair the same small open-weight base (gemma-4-E4B-it) with a curated public dataset on HuggingFace.
When no --use-* flag is passed, the CLI inspects npm_config_user_agent to detect the package manager that invoked it (this is the standard mechanism corepack uses, so pnpm dlx, yarn dlx, bunx, etc. all work).
If detection fails and no flag is passed, the install step is skipped and the outro prints a manual install hint.
arkor init decides whether to run git init + initial commit by walking these rules in order:
--skip-git is passed, skip.--git or -y is passed, run without asking.The interactive confirmation is shown before install (so you don't sit at a prompt after a multi-minute <pm> install), but git init execution still runs after install so the lockfile generated by the package manager is part of the initial commit. If commit signing fails (e.g. GPG agent isn't running), the CLI falls back to an unsigned commit and warns; you can re-sign with git commit --amend -S later.
When process.stdout is not a TTY, or CI is set in the environment, arkor init is non-interactive: prompts skip with their default values and never block waiting for input. To get a deterministic scaffold from CI:
pnpm arkor init --yes --template triage --use-pnpm --skip-gitnpm arkor init --yes --template triage --use-npm --skip-gityarn arkor init --yes --template triage --use-yarn --skip-gityarn run arkor init --yes --template triage --use-yarn --skip-gitbun arkor init --yes --template triage --use-bun --skip-git--yes accepts the project-name and template defaults (the directory's basename and triage), --use-pnpm (or the matching --use-<pm>) short-circuits package-manager detection, and --skip-git opts out of git init. Pass --skip-install as well if your CI image already has node_modules/.
If you forget --yes in a non-interactive shell, the command still completes (prompts use their defaults) but the experience is silent and easy to miss in logs. Prefer the explicit form above.
CLAUDECODE=1) strict modeClaude Code spawns child processes with CLAUDECODE=1, and it cannot answer interactive prompts. To prevent the agent from silently scaffolding with hidden defaults, arkor init flips into a strict mode under this env var: a curated set of flags becomes required (see the list below), and a missing one produces a stderr message listing the suggested re-invocation rather than running. Project name is intentionally not required here in the common case: arkor init derives it from basename(cwd), which is the same value the interactive prompt would have suggested. The strict-mode validator still asks for --name <name> in two narrow cases that would otherwise silently fall back to the generic arkor-project slug, namely (a) when --name was passed but its value has no ASCII letter or digit (e.g. --name "!!!") and (b) when --name was omitted and the current directory's basename has no ASCII letter or digit either (e.g. running arkor init from /tmp/!!!/). The package-manager flag is required even though it isn't strictly a prompt, so the agent picks --use-* vs. --skip-install deliberately rather than relying on npm_config_user_agent detection.
Required flags (or pass -y/--yes to opt back into "accept all defaults"):
--template <triage|translate|redaction>--git (recommended; matches the interactive default) or --skip-git--use-npm / --use-pnpm / --use-yarn / --use-bun, or --skip-install--agents-md (recommended, especially under CLAUDECODE) or --no-agents-mdSample stderr when a flag is missing. Each flag is paired with a one-line description so the agent can pick a value without round-tripping to the docs:
arkor init: CLAUDECODE=1 detected. Interactive prompts are disabled.
Re-run with explicit flags:
--template <triage|translate|redaction>
Starter template: `triage` (support routing), `translate` (9-language translation), or `redaction` (PII removal).
--git (recommended) or --skip-git
`--git` runs `git init` and creates an initial commit (matches the interactive default); `--skip-git` leaves git setup to the user.
--use-pnpm (or --use-npm / --use-yarn / --use-bun, or --skip-install)
Which package manager to run `install` with after scaffolding. `--skip-install` leaves the install step to the user.
--agents-md (recommended) or --no-agents-md
`--agents-md` writes `AGENTS.md` + `CLAUDE.md` to brief AI coding agents that arkor post-dates their training data (recommended, especially under CLAUDECODE); `--no-agents-md` skips them.
Or pass -y/--yes to accept all defaults.The exit code is 1 and no scaffold work happens before the early exit, so the directory stays pristine. The same rule applies to create-arkor (Quickstart documents the create-arkor specifics, including the additional [dir] / --name requirement to make the project name an explicit decision).
| Message | What it means | Fix |
|---|---|---|
Pick one of --git / --skip-git, not both. | Both git flags were passed. | Pass at most one. |
Unknown template "<id>". Available: triage, translate, redaction | --template value did not match any registered template id. | Use one of the listed ids. |
Commit signing failed: created an unsigned commit. | git init succeeded but the initial commit could not be GPG-signed. | Re-sign with git commit --amend -S once your signing setup is fixed. The repo is otherwise fine. |
Interactive:
pnpm arkor initnpm arkor inityarn arkor inityarn run arkor initbun arkor initAccept defaults, skip install, skip git:
pnpm arkor init --yes --skip-install --skip-gitnpm arkor init --yes --skip-install --skip-gityarn arkor init --yes --skip-install --skip-gityarn run arkor init --yes --skip-install --skip-gitbun arkor init --yes --skip-install --skip-gitPin the template and force the package manager:
pnpm arkor init --template translate --use-pnpmnpm arkor init --template translate --use-npmyarn arkor init --template translate --use-yarnyarn run arkor init --template translate --use-yarnbun arkor init --template translate --use-bunThe scaffolder touches up to ten paths: six unconditional plus two AGENTS.md-related plus two conditional package-manager configs. None of them overwrites existing user content:
| Path | Behavior |
|---|---|
src/arkor/index.ts | Created with createArkor({ trainer }) if missing. Kept untouched if the file already exists. |
src/arkor/trainer.ts | Created with the chosen template's createTrainer({...}) if missing. Kept untouched if it exists. |
arkor.config.ts | Created as a placeholder export if missing. Kept untouched if it exists. See Project structure. |
README.md | Created with a starter README if missing. Kept untouched if it exists. |
.gitignore | Created with node_modules/, dist/, .arkor/ if missing. Patched by appending .arkor/ if the file exists but does not already list it. Ok (no change) if .arkor/ is already there. |
package.json | Created with name / private / type: "module" / starter dev+build+start scripts / devDependencies.arkor if missing. Patched to add any of those scripts that are absent and to add arkor under devDependencies if absent; existing values (e.g. a custom dev script) are not overwritten. Ok (no change) if everything is already in place. |
AGENTS.md | Created with the arkor-managed block if missing (default; skip with --no-agents-md). If the file exists, the arkor-managed block (delimited by <!-- BEGIN:arkor-agent-rules --> / <!-- END:arkor-agent-rules -->) is patched in place (appended on first run, replaced inline on re-scaffold), and any user content outside the markers is preserved. Ok (no change) if the canonical block is already present and up-to-date. Kept with a warning, instead of patched, when the file contains more than one canonical managed block: auto-picking either copy is unsafe, so the scaffolder leaves the file alone and asks you to dedupe before the next re-scaffold. |
CLAUDE.md | Created with @AGENTS.md (the Claude Code import directive) if missing (default; skip with --no-agents-md). Kept untouched if the file already exists, so a project-specific CLAUDE.md is never overwritten. Skipped with a warning when AGENTS.md was kept due to duplicate managed blocks: creating the @AGENTS.md shim in that state would auto-import the unresolved duplicate rules into Claude Code's context. The next re-scaffold creates the file once you dedupe AGENTS.md. |
pnpm-workspace.yaml | Conditional. See Postinstall scripts (pnpm 11+) for the full conditions. Created with packages: [] + allowBuilds.esbuild: false (or : true with --allow-builds) when pnpm is plausible AND no ancestor already declares one. Patched when the file already exists AND pnpm is plausible: appends esbuild: <bool> to allowBuilds: only if esbuild isn't already pinned. Skipped for explicit --use-npm / --use-yarn / --use-bun and inside pnpm monorepo subdirs. |
.yarnrc.yml | Conditional. See packages/cli-internal/src/scaffold.ts for the full layered yarn-config policy. Created with nodeLinker: node-modules on fresh scaffolds where yarn is plausible (--use-yarn, UA-detected yarn, or no --use-* flag with UA detection failing). Kept untouched if it exists; non-default nodeLinker: produces a conflict warning, missing nodeLinker: surfaces a yarn-berry caveat. Skipped for explicit non-yarn pms and for --use-yarn against an existing non-empty dir without a positive yarn-berry signal. |
The CLI prints the file list as a "Files" note before installing, with an action (created / kept / patched / ok / skipped) per path so you can see exactly what changed.
The arkor-managed block is identified by the BEGIN / END markers plus a signature first line (# arkor is newer than your training data). The detector requires all three on their own lines, so inline marker mentions inside backticks are safe, but a fenced code block whose body literally contains the markers and that signature heading on their own lines will look identical to a real managed block. To avoid having a re-scaffold misidentify and overwrite a documentation example you wrote yourself, follow these conventions when editing AGENTS.md:
`<!-- BEGIN:arkor-agent-rules -->`, rather than putting them on their own lines outside the real managed block.# arkor is newer than YOUR training data) so the detector does not match it.arkor dev for the next step after init