Incantory
Sign in

CLI

The incantory command-line client: device login, pull, push, diff, labels, forks, render, installs, export and import, codegen, eval reports and webhooks.

The CLI needs Node 20.19 or later. Run it with npx or install it globally.

bash
npx incantory login
npx incantory add alice/code-review@production --to claude

Every command accepts -h / --help for its usage. incantory --help lists them all.

Global options

OptionMeaning
--jsonPrint exactly one JSON document on stdout; progress goes to stderr
--url <url>API base URL (default $INCANTORY_URL or https://incantory.ai)
--offlineUse only the local cache (pull, render)
-q, --quietLess output
--no-colorDisable colour (also NO_COLOR=1)
-h, --helpHelp for a command
--versionPrint the version

Environment

VariableMeaning
INCANTORY_TOKENAPI token; overrides the stored login. Use this in CI
INCANTORY_URLAPI base URL
INCANTORY_CACHE_DIRCache directory (default $XDG_CACHE_HOME/incantory or ~/.cache/incantory)
INCANTORY_NO_TELEMETRY1 to skip recording install events
NO_COLORDisable colour
INCANTORY_DEBUGPrint stack traces on unexpected errors

Account

incantory login

incantory login [--scopes read,write] [--device-name name] [--no-browser]

Logs in with the device flow: the CLI mints a token, registers only its hash, prints a code and opens the approval page. After you approve, the token is saved to ~/.config/incantory/credentials.json (mode 0600, one entry per API URL).

incantory logout

incantory logout

Forgets the stored token for this server. Revoke it on the server at Settings → Security.

incantory whoami

incantory whoami

Shows the account behind your token.

Working with prompts

incantory pull

incantory pull <owner/slug[@label|@vN]> [dir] [--force]

Downloads a prompt into a working directory (default: the slug), with the entry file's frontmatter restored, and records the version in .incantory/state.json. Refuses to overwrite local changes unless you pass --force.

incantory push

incantory push [dir] -m <message> [--force]

Commits the directory as a new version, sending the version you pulled as baseVersion. If someone else committed first you get stale_base and exit code 5; --force commits on top anyway. If nothing changed it says so and exits 0.

incantory diff

incantory diff <owner/slug> <a>..<b>

Unified diff between two versions, including frontmatter (1..3 or v1..v3).

incantory log

incantory log <owner/slug> [--limit N] [--all]

Versions, newest first, with labels, yanked marks, author and hash.

incantory label

incantory label set <owner/slug> <name> <vN> [--reason text] [--protected] [--require-passing-eval]
incantory label ls <owner/slug>
incantory label rm <owner/slug> <name>
incantory label history <owner/slug> <name>

Moves, lists and deletes labels, and shows a label's move history. A move onto a version without a passing eval fails with eval_required when the label requires one.

incantory fork

incantory fork <owner/slug[@label|@vN]> [--slug new-slug] [--license SPDX]

Forks into your namespace, at the ref's version if it names one.

incantory render

incantory render <owner/slug[@label|@vN]> [--var name=value]... [--var name=@file] [--vars-file vars.json] [--on-missing error|keep|empty]

Renders the prompt with the shared template engine. --var name=@file reads the value from a file. Chat prompts print as ## role sections, or as messages with --json. No model is called.

incantory export

incantory export <owner/slug[@label|@vN]> [dir] [--force]

Writes a git-friendly directory: the package files plus incantory.json metadata.

incantory import

incantory import [dir] [--slug s] [--title t] [--visibility public|unlisted] [--draft] [-m message]

Creates a new prompt from a directory: an export, or any folder with a recognisable entry file such as prompt.md, SKILL.md or *.mdc. The directory then becomes a working copy you can push.

incantory codegen

incantory codegen <owner/slug[@label|@vN]>... [-o prompts.d.ts]

Writes TypeScript types for the prompts' variables. They plug into @incantory/sdk, so render() is type-checked.

Installing into coding tools

See Install into tools for where each tool's files go.

incantory add

incantory add <owner/slug[@label|@vN]> --to claude|cursor|copilot|agents|codex|windsurf|gemini [--project|--global] [--yes-i-read-it] [--var name=value]... [--no-record]

Installs a prompt into a coding tool and records it in incantory.lock. A prompt the scanner rates high risk needs --yes-i-read-it. --no-record skips the install-count event.

incantory update

incantory update [owner/slug...] [--global] [--force] [--yes-i-read-it]

Re-resolves label and latest refs in incantory.lock and rewrites the installs. @vN pins never change.

incantory remove

incantory remove <owner/slug> [--to claude|cursor|copilot|agents|codex|windsurf|gemini] [--global]

Deletes the installed files and cuts out managed sections. Your own content in shared files is left alone.

incantory verify

incantory verify [--lock path]

Checks every pin in incantory.lock against the registry (exit code 7 on a mismatch) and reports labels that have moved.

CI

incantory eval

incantory eval report <results.jsonl> (--run <id> | --ref <owner/slug@vN> [--model m] [--dataset id]) [--chunk-size N]

Uploads eval results from a JSONL file (one result object per line) to an existing run or a new one. Exits 9 when the server does not offer the evals API. See Evals and the CI gate.

incantory webhook

incantory webhook ls
incantory webhook add <url> --events a,b [--prompt owner/slug]... [--description text] [--inactive]
incantory webhook rm <id>
incantory webhook test <id>
incantory webhook deliveries <id> [--limit N] [--cursor c]
incantory webhook redeliver <id> <deliveryId>

Manages your webhooks. add prints the signing secret once, alone on stdout (so it can be piped into a secret store; with --json it is the secret field); store it where your receiver can read it. test sends a ping delivery, deliveries shows the delivery log, and redeliver sends a past delivery again.

Output

Plain text by default, with colour only when stdout is a terminal and NO_COLOR / --no-color are not set. Rendered prompts go to stdout; progress, the device code and warnings go to stderr. With --json, a failure prints:

json
{ "error": { "message": "Not found", "code": "not_found", "exitCode": 4 } }

Exit codes

CodeMeaning
0Success (including "nothing to push" and "already up to date")
1Unexpected error (INCANTORY_DEBUG=1 prints the stack)
2Usage or invalid input: a bad flag or ref, a missing or invalid variable, invalid JSONL, a 400/413/422
3Authentication: not logged in, 401/403, or login denied or expired
4Not found (404/410, unknown label)
5Conflict: stale_base, local changes would be overwritten, a directory is not empty, slug_taken
6The risk gate refused a high-risk prompt (re-run with --yes-i-read-it)
7Integrity: a content hash mismatch, lock_mismatch, or a failed verify
8Network, rate limit or server unavailable (after retries), or an offline cache miss
9This server does not support the operation yet