Installation In Full
The npm packages, the standalone binary, building from source, and what wins when both are present.
Your First Spec gives you the one-line version. This is everything else.
Requirements
- Node.js 20.11 or newer. The compiler is ESM and targets modern Node.
- npm, which ships with Node.
The standalone binary needs neither.
As a dependency
npm i -D @psy/cliInstall the framework packages too when you want your editor to type-check
psy.config.ts, or to pin versions:
npm i -D @psy/config @psy/morphic @psy/adapter-claude| Repository | Package | Contents |
|---|---|---|
core | @psy/core | lexer, parser, AST, binder, resolver, checker, IR, provenance, formatter, linter |
framework | @psy/framework | the types a framework or adapter may consume |
config | @psy/config | psy.config.ts loading and typing |
morphic | @psy/morphic | the skill / agent / command vocabulary |
adapter-claude | @psy/adapter-claude | Claude Code agents, skills, commands and plugins |
adapter-data | @psy/adapter-data | JSON, YAML and TOML |
cli | @psy/cli | the psy command line |
The standalone binary
psy can be built as a single self-contained executable — no Node, no
node_modules, in the projects it compiles or on the machine it runs on.
npm run compile # from the root; writes cli/dist/psy
npm run compile:install # and copies it to ~/.local/bin/psyFor anywhere else, node compile.mjs --install <dir>. It warns when the
destination is not on your PATH, and when the directory needs root it tells you
what to run rather than failing with a stack trace:
sudo install -m 755 cli/dist/psy /usr/local/bin/psyIt is built with Bun, which is needed only to produce the binary and never to run it. The build rebuilds every package the binary bundles, then runs the CLI test suite under Bun — the runtime the binary actually ships — before producing anything.
Cross-compile with a target triple:
node compile.mjs --target bun-darwin-arm64 # -> cli/dist/psy-darwin-arm64It carries its own packages
Which means a project that has installed nothing at all still works:
mkdir demo && cd demo
psy init --template morphic --yes
psy check && psy build # no npm install anywhereThat covers both halves of a package. psy.config.ts imports @psy/morphic as
JavaScript; a .psy source activates its keywords with use "@psy/morphic". Both
resolve from inside the binary.
What wins
Anything the project installs takes precedence, for both halves. A project that pins a version gets the version it pinned, and the bundled copies are only ever a fallback.
The same applies to a global npm install -g @psy/cli.
From source
Clone the root repository and run its setup script. It clones every other Psy repository into the same directory and builds them in dependency order.
git clone ssh://dev.mdynx.net/psy/dev.git psy
cd psy
./setup.shsetup.sh is one git clone per line, each guarded by a directory check, so it
is safe to re-run. Once everything is cloned, node bootstrap.mjs installs and
builds on its own.
Repository layout
psy/ the root (`dev`): setup.sh, bootstrap, cross-repo checks
core/ the compiler
framework/ the framework boundary
config/ psy.config.ts
morphic/ the skill / agent / command vocabulary
adapter-claude/ Claude Code output
adapter-data/ JSON, YAML, TOML output
cli/ the psy command line
spec/ the language specification, written in Psy
build/ the Morphic definitions that maintain Psy
examples/ runnable example projects
docs/ this documentation site
tree-sitter/ the tree-sitter grammar
zed/ the Zed extensionThe checkouts depend on each other with file:../<dir>, which npm resolves to a
real symlink — a change in one is visible to the next immediately, with no publish
and no version bump. They do have to be built in dependency order, which is
what bootstrap.mjs is for.
The CLI is linked into the node_modules/.bin of every checkout that depends on
it, so those repositories can just call it:
cd spec && npx psy checkVerification
Each repository verifies itself:
cd spec && npm run verify # psy check, lint, format --check, build --check
cd core && npm run verify # typecheck and testsOnly the assertions that need two repositories at once — a fixture naming a rule
in spec, the docs matching the diagnostic table, the generated agents matching
their Psy sources — live at the root:
node verify-all.mjs # every checkout, then the cross-repo checks
node verify-all.mjs core # just one
node verify-all.mjs --root # just the cross-repo checks