PHARN does not scaffold your app. You create your project (e.g. with create-next-app), initialize git, then run PHARN in that directory.
| Requirement | How PHARN checks | When |
|---|---|---|
| Git | A .git directory exists in the project root |
Always — checked up front, before detection |
| Interactive terminal | process.stdin/stdout are TTYs |
Right after the git check, before any fetch |
| Node | engines.node declares >=20.13.0 (CI exercises Node 24; a smoke job starts the CLI on 20.13.0) |
By npm/npx when the package is resolved |
.git is required for every install. So is a real terminal: pharn init exits 1 rather than
rendering a prompt into a dead stream, and there is deliberately no --yes for it — its second prompt
is the destructive overwrite confirmation. (pharn update behaves the same way, and update --yes is
the supported way through in CI.) pharn init then detects your project's archetype(s) from
package.json dependency names plus a bounded file-tree scan — there is no stack-pack selection and no
package prerequisite to satisfy. See Troubleshooting.
PHARN installs into your existing project. Just before writing, pharn init checks which of its
actual install targets (the selected capability dirs, the product commands/hooks, the contracts, core
and floor dirs, all four trusted docs, pharn's LICENSE copy, pharn/features/README.md, and
pharn.config.json) already exist in your project. If any do, it lists them and asks you to confirm
before overwriting — default no; if none do, there is no prompt at all. Your
.claude/settings.json is never overwritten, so it is not part of the check.
The npm package name is @pharn-dev/pharn. It installs a single command, pharn.
npx @pharn-dev/pharn initnpx create-next-app@latest my-app
cd my-app
npx shadcn@latest init
git init && git add -A && git commit -m "init"
npx @pharn-dev/pharn initpharn with no subcommand runs init (same as pharn init).
pharn init is archetype-driven — there is no questionnaire:
- Detect archetypes. The CLI merges your
package.jsondependency names with a bounded, symlink-safe file-tree scan (names only, never file bodies) into an archetype set —ssr,backend,spa,lib(a project may match several, e.g. Next + Express →ssr+backend). It shows what it detected. Detection is JS/TS-shaped: the signals are npm dependency names plusnext.config.*,app/route handlers,.tsx/.jsx,migrations/and.sql. A Python, Go or Rust project produces no signal, resolves tolib, and receives the universal capabilities only — the correct outcome, not a failure. - Fetch + resolve. It downloads
pharn-dev/pharn-ossas a tarball at a pinned SHA and selects the capabilities whoseappliesisuniversalor intersects your detected archetypes — skipping the rest with a reason. If the SHA cannot be resolved (offline, rate-limited) the fetch floatsmaininstead and recordscommit: null. If the fetched version declares aMIN_CLInewer than your CLI, the run stops here with a named error and writes nothing. - Confirm + install. After a summary (selected + skipped), it copies the selected capabilities plus
the fixed product surfaces (commands, hooks, contracts,
pharn-core, floor checkers, the four trusted docs, upstream'sLICENSEcopy, andpharn/features/README.md) into the mirrored layout, then writespharn.records.jsonandpharn.config.json.
To add a capability the detection didn't select — or remove one it did — use
pharn add / pharn remove afterward.
After a successful install, your project contains the selected capabilities plus the fixed product surfaces:
| Artifact | Description |
|---|---|
pharn/pharn-pipeline/grillers/<name>/, pharn/pharn-review/<name>/ |
The installed grillers + lenses, each with its evals/ |
.claude/commands/, .claude/hooks/ |
The pharn-* product slash commands + the deterministic .cjs floor hooks |
pharn/pharn-contracts/, pharn/floor/ |
Inter-layer schemas + the floor checkers the commands invoke (minus the floor's own test files and test-fixtures/) |
pharn/pharn-core/ |
The agnostic mechanism skills the commands cite (the seam resolver + its evals) |
pharn/CONSTITUTION.md, pharn/ARCHITECTURE.md |
Two of the four trusted spec docs, copied verbatim — see the layout note below |
THREAT-MODEL.md, LIMITS.md |
The other two, at the project root — where upstream keeps them and where the installed commands cite them |
pharn/LICENSE (flat: PHARN-LICENSE) |
PHARN's Apache-2.0 license, copied so a repo you publish carries the grant. Your own root LICENSE is never touched |
pharn/features/README.md |
The product-loop boundary contract the installed commands cite by name (project root in both layouts) |
pharn.config.json |
skillsVersion, commit SHA, detected archetypes, installed capabilities, and the layout |
pharn.records.json |
Per-file sha256 — skips unproven present edits, restores missing; --force overwrites all but unreadable |
.claude/* is layout-invariant — commands, hooks and settings.json sit at those paths either
way, and an existing .claude/settings.json is never overwritten. Everything else follows the fetched
version: the CLI mirrors whichever layout pharn-dev/pharn-oss ships and never rewrites a copied
file's contents, so the paths above are the pharn layout it installs today. The legacy flat
layout puts the same surfaces at the project root instead — pharn-pipeline/grillers/,
pharn-review/, pharn-contracts/, .dev/floor/, PHARN-LICENSE — and upstream ships no root
pharn-core/, so that one surface is simply absent there. The four trusted docs are the same set
in both layouts, but their prefix is per-doc, not per-layout: upstream's relocation moved
CONSTITUTION.md and ARCHITECTURE.md under pharn/ and left THREAT-MODEL.md and LIMITS.md at
the repo root, so a pharn install lands them exactly that way and a flat install lands all four at
the root. Each doc is copied only if the fetched version ships it — a clone that predates one simply
does not get it, and init says which docs it wrote and warns about any it did not. Which layout you
got is recorded as layout in pharn.config.json.
See pharn.config.json and pharn.records.json for the exact schemas. Commit both — they are your project's PHARN state.
- Open Claude Code in the project directory.
- Run
/pharn-specto capture your first feature's intent — it pins the scope and feeds/pharn-plan. This is where every run begins:/pharn-plangates on an Approved, un-driftedSPEC.mdand halts without one, so there is no entry point further down the chain.
The pipeline is eight typed stages: /pharn-spec → /pharn-plan → /pharn-grill → /pharn-test → /pharn-build → /pharn-regress → /pharn-verify → /pharn-ship. You rarely run them by hand — /pharn-ship is itself the eighth stage and orchestrates the seven before it in one pass, keeping both human gates: approve the spec before code is written, decide merge/fix/abandon after verification. /pharn-loop runs the same chain unattended — the model approves the spec and iterates build → regress → verify until green, an iteration cap, or a terminal failure — and leaves the merge/fix/abandon decision to you after the run.
Set up a test runner before your first feature. /pharn-test writes each acceptance criterion's test before the build and requires it to fail, so it needs a test script (plus test:e2e or e2e for end-to-end criteria) whose reporter writes per-test JSON, named under testResults in pharn.config.json. Without one, /pharn-test stops and asks, and /pharn-loop ends with blocked: no-test-runner. Set the runner up as its own increment (a SPEC with spec_kind: test-infra); the reporter setup is in upstream's Per-test results.
Two of the eleven installed commands sit outside the pipeline: /pharn-review runs the review lenses in parallel over any code and merges their findings (no stage invokes it), and /pharn-memory-promote promotes one lesson into memory-bank/ through a gated provenance check.
- Review what was written: pharn.config.json
- Add a capability later: add command
- Refresh to the latest skills: update command