Install¶
Leopold has two tiers. The in-session engine (skills + hooks) is all you need to start and runs in plain Claude Code or plain Codex CLI. The SDK driver is optional and adds unattended, background runs.
Prerequisites¶
- At least one harness, logged in: Claude Code and/or Codex CLI (0.146.0 is the reference). Both is fine — the installer wires each one it finds.
jqon yourPATH(the hooks use it to parse state safely).python3(the prompt enhancer engine and theleopold watchdashboard).- For the SDK driver only: Node.js 18+ .
- Optional but recommended: gstack, so Leopold can conduct the full skill toolchain.
Install the in-session engine¶
The npm package is the fastest path — it bundles the whole harness and sets the project up in one command:
Or the one-line installer:
Or clone it (more transparent):
Choosing harnesses¶
The installer detects what is on the machine, and asks only when the choice is a real one. If it finds both Claude Code and Codex — or neither — it prompts:
Both Claude Code and Codex CLI are here. Install Leopold into which?
1) both — same brief, same hooks, either seat (recommended)
2) Claude Code — ~/.claude
3) Codex CLI — ~/.codex
Choice [1]:
If exactly one harness is present it just installs there — asking would be friction,
not a choice. The prompt reads from the terminal rather than stdin, so it still works
under curl … | bash; with no terminal at all (CI, a headless box) it takes both and
says so instead of hanging.
Skip the prompt entirely by naming the harness:
./install.sh # auto — detect, and ask if the choice is real
./install.sh --harness claude # Claude Code only
./install.sh --harness codex # Codex only
./install.sh --harness all # both, installed or not
LEOPOLD_NONINTERACTIVE=1 ./install.sh # never prompt, take the defaults
What the installer does:
flowchart LR
Run["./install.sh"] --> S["copy skills →<br/>each harness's skills/"]
Run --> H["copy hooks/templates/docs →<br/>the asset home"]
Run --> M["wire hooks into<br/>settings.json / config.toml"]
Run --> E["vendor the prompt enhancer →<br/><home>/enhance/ (off)"]
M --> Idem{{"idempotent +<br/>backup"}}
Skills go into each harness's own skills directory (~/.claude/skills/,
~/.codex/skills/ — the same SKILL.md format). Everything harness-neutral —
hooks, templates, docs, scripts, extensions — goes into one shared asset home:
~/.claude/leopold whenever Claude Code is in play, so existing installs need no
migration, otherwise ~/.codex/leopold. LEOPOLD_HOME overrides both. See
Asset Home.
Four hooks are wired into your harness config: the three engine hooks are inert
unless a Leopold run is active, and the prompt enhancer
is off until you toggle it on (leopold menu → enhance) — so none of them
interfere with normal sessions.
It is safe to re-run
install.sh is idempotent, on both formats. It backs up settings.json to
settings.json.leopold.bak and never duplicates hook entries; on Codex it backs
up config.toml, replaces its marker-delimited block and nothing else, and
validates the result — a merge that would not parse is rolled back and printed
for you to paste instead. Three installs leave a byte-identical file.
One extra step on Codex
Codex will not execute a hook declared in config.toml until you have trusted
it once — until then it is silently inert. Open Codex once and approve the
Leopold hooks, or install Leopold as a Codex plugin, which arms them through the
plugin install. leopold doctor tells you which state you are in. Headless
workers started by leopold run --provider codex arm their own git lock, so a
driver-conducted run is locked from its first turn either way. Full detail:
Claude Code and Codex.
Install the SDK driver (optional)¶
The driver uses your existing harness login for both the worker and the conductor,
so there is no separate API key — the Agent SDK on your Claude Code auth, or
codex exec on your Codex login (leopold run --provider codex). See
Driver Config.
Verify¶
leopold doctor # every harness present: skills, hooks, wiring, extensions
leopold harness # what each harness here can do, and which one a run would use
Then, in any session:
If Leopold is installed, this reports "No Leopold run in this project." (which is the correct answer before you start one).
Install as a plugin (one command, auto-wires hooks)¶
The plugin is the most native install — it wires the skills and hooks
automatically, with no config merge. Leopold ships both manifests
(.claude-plugin/ and .codex-plugin/):
On Codex the plugin has a second benefit: plugin-provided hooks are trusted through the install, so there is no separate approval step.
Use the plugin or install.sh, not both, to avoid double-wired hooks.
The extensions¶
leopold menu installs and manages the bundled extensions — serena, gstack, ovmem,
the prompt enhancer and decisions (typed, calibrated
judgements; optional, and every consumer keeps a deterministic path without it). Each one installs, reports status and runs its doctor
per harness, so a two-harness machine gets both wired and a Codex-only machine
gets nothing pointing at a Claude path. See
Toolchain Manager.
The SDK driver from npm¶
For the background-driver tier:
Updating¶
The toolchain has two version surfaces: the assets (hooks, skills, scripts —
carrying VERSION) and the leopold-driver binary on PATH. They are installed by
different mechanisms, so they can drift, and a drift is invisible from either one
alone. One update moves both.
- Engine (curl /
install.sh):make update, or/leopold-updatefrom inside Claude Code. This pulls the source, re-runs the installer, and brings the npm driver to the same version — or says out loud which half it could not move. Opt into automatic updates withtouch ~/.leopold/auto-update— the brief then checks and updates on its own (notify-only otherwise). - Plugin:
claude plugin update leopold. - npm driver on its own:
npm i -g leopold-driver@latest.
leopold doctor prints the pair on one line — toolchain: driver X · assets X — both
surfaces agree — and fails loudly when they diverge.
A newer driver can be shadowed by an older one
npm i -g installs into its prefix. If an older leopold-driver sits earlier in
your PATH (a second npm prefix, say), it keeps winning: npm reports success and you
keep running the old binary. leopold-driver update cannot escape this either —
that command is executed by the stale binary.
The update and leopold doctor both look at the whole PATH and list every install,
the one that actually runs first. Remove the stale one (and the tree it points
into), then re-check with leopold-driver --version.