Reference

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/cli

Install 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
RepositoryPackageContents
core@psy/corelexer, parser, AST, binder, resolver, checker, IR, provenance, formatter, linter
framework@psy/frameworkthe types a framework or adapter may consume
config@psy/configpsy.config.ts loading and typing
morphic@psy/morphicthe skill / agent / command vocabulary
adapter-claude@psy/adapter-claudeClaude Code agents, skills, commands and plugins
adapter-data@psy/adapter-dataJSON, YAML and TOML
cli@psy/clithe 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/psy

For 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/psy

It 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-arm64

It 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 anywhere

That 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.sh

setup.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 extension

The 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 check

Verification

Each repository verifies itself:

cd spec && npm run verify     # psy check, lint, format --check, build --check
cd core && npm run verify     # typecheck and tests

Only 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

On this page