Agent-drivable CLI for the Diffmode growth pipeline.
Thin wrapper around the hosted /public/v1/* API: authenticate, submit a
run, watch a job, retrieve manifest-shaped results.
Use the diffmode CLI to generate a growth plan for my product.
Most LLM agents (Claude Code, Codex, Cursor) understand that sentence after
you install the bundled skill (see Agent integration below). For one-off
use, you can also run diffmode directly without an agent — it's a plain
CLI.
# 1. Authenticate (paste a PAT from https://diffmode.app/app/tokens)
npx diffmode@latest login --token dm_pat_…
# 2. Run the free-tier diagnostic (1 credit) for your product
diffmode run my-product --input founder.json
# 3. Watch the job until terminal
diffmode jobs watch <job_id>
# 4. Download outputs + emit a manifest
diffmode results my-product
# 5. Optionally unlock the full plan (2 credits via CLI)
diffmode unlock my-productTop-up is browser-only by design — diffmode never prompts for a card
or invokes Stripe. When you run out of credits, the CLI exits with code 8
and a message pointing to https://diffmode.app/app/billing?channel=cli
(the CLI credit-packs view: Starter $20/10 cr · Builder $40/30 cr · Scale $99/100 cr).
# Primary path — no install, always latest
npx diffmode@latest <command>
# Global install (power users)
npm i -g diffmodeRequires Node ≥ 20.
| Command | What it does | Credits (CLI) |
|---|---|---|
diffmode login / logout / whoami |
PAT-based authentication | — |
diffmode run <product> |
Free-tier diagnostic | 0 |
diffmode unlock <product> |
Full plan (needs prior run) |
2 |
diffmode workflow <product> |
Cold-start full workflow | 2 |
diffmode idea-eval <product> |
Score ideas vs. founder context | 1 |
diffmode smoke-test <product> |
Quick tactic smoke-test | 1 |
diffmode jobs list/status/watch/resume/cancel |
Job lifecycle | — |
diffmode results <product> |
Download + manifest | — |
diffmode account / billing balance / history |
Read-only billing | — |
diffmode limits |
Credits + rate-limit policy | — |
diffmode diagnostics from-url/validate |
Founder-input helpers | — |
diffmode skill show / skill install / skill uninstall |
Agent skill installer | — |
diffmode commands |
Machine-readable manifest | — |
The credit column above is informational. Actual cost is fetched live from the server via GET /billing/balance (the response includes a credit_costs matrix for the caller's channel). CLI callers (PAT-authenticated) pay materially less than web callers — a $199 / 15-credit pack runs ~7 full pipelines from the CLI vs 1 from the browser. The table above shows current CLI prices; web prices are higher (workflow/unlock=15, idea-eval=5).
Full per-command reference: skills/diffmode/references/commands.md.
Submit commands (run, workflow, unlock, idea-eval, smoke-test) do a
pre-flight GET /billing/balance before posting and exit 8 if the wallet
balance is below the module cost. Pass --no-preflight to skip it when the
agent has already verified credits this turn. If the server's pricing table
is unreachable, the CLI exits with code 11 (pricing_unavailable) instead
of falling back to a stale local constant.
| Code | Meaning |
|---|---|
0 |
OK |
1 |
Generic error |
2 |
Usage error (bad flags, missing required input) |
3 |
Network |
4 |
Auth (invalid/revoked token) |
5 |
Conflict (in-flight job for the same product) |
6 |
Not found |
7 |
Rate-limited (Retry-After) |
8 |
Insufficient credits (top up via browser at https://diffmode.app/app/billing?channel=cli) |
9 |
Server (5xx) |
10 |
Interrupted but resumable (diffmode jobs resume) |
11 |
Pricing config unavailable (server's credit_costs table unreachable) |
130 |
SIGINT (Ctrl-C; never cancels the server-side job) |
Full per-code recovery guidance: skills/diffmode/references/error-codes.md.
diffmode ships an Anthropic-format skill (SKILL.md), an AGENTS.md
companion, an llms.txt, and a Cursor MDC rule — all generated from one
source so they don't drift.
Install them into your agent's known location:
# Install into Claude Code, Codex, and Cursor (default)
diffmode skill install
# Or pick a target
diffmode skill install --target claude
diffmode skill install --target cursor
# Inspect what would happen first
diffmode skill install --dry-run
diffmode skill install --print-pathsDefault destinations:
| Target | Path |
|---|---|
| Claude Code | ~/.claude/skills/diffmode/SKILL.md |
| Codex | ~/.codex/skills/diffmode/SKILL.md |
| Cursor | ~/.cursor/rules/diffmode.mdc |
Override with the env vars DIFFMODE_SKILL_CLAUDE_PATH,
DIFFMODE_SKILL_CODEX_PATH, DIFFMODE_SKILL_CURSOR_PATH.
To preview the skill text without installing: diffmode skill show.
To remove the installed skill:
# Uninstall from all three (default)
diffmode skill uninstall
# Or pick a target
diffmode skill uninstall --target claude
# Preview first
diffmode skill uninstall --dry-runIf you've hand-edited the installed file, uninstall reports
needs-confirm and writes nothing. Pass --yes to remove anyway. Empty
skills/diffmode/ parent directories are cleaned up automatically for
Claude and Codex targets; the Cursor ~/.cursor/rules/ directory is
left alone.
diffmode reads configuration in this order:
- Per-command flag (e.g.,
--token,--timeout,--profile) - Environment variable
- Built-in defaults
A ~/.config/diffmode/config.json profile registry is planned for Phase 2;
0.1.0 only reads the env vars below.
| Variable | Purpose | Default |
|---|---|---|
DIFFMODE_TOKEN |
PAT (overrides stored, beaten by --token) |
— |
DIFFMODE_API_BASE |
API base URL | https://ai-cmo-api.onrender.com/public/v1 |
DIFFMODE_BILLING_URL |
Billing redirect base URL (?channel=cli is appended automatically) |
https://diffmode.app/app/billing |
DIFFMODE_PROFILE |
Active profile name (overridden by --profile) |
default |
DIFFMODE_SKILL_CLAUDE_PATH |
Override Claude skill install target | ~/.claude/skills/diffmode/SKILL.md |
DIFFMODE_SKILL_CODEX_PATH |
Override Codex skill install target | ~/.codex/skills/diffmode/SKILL.md |
DIFFMODE_SKILL_CURSOR_PATH |
Override Cursor MDC install target | ~/.cursor/rules/diffmode.mdc |
NO_COLOR=1 |
Disable ANSI colors | — |
The active profile is used as the keyring account name, so different
profiles can hold independent PATs (diffmode --profile staging login …).
Tokens are stored separately in the OS keyring (keytar) — or in a
mode-0600 fallback file with a one-time stderr warning when the keyring
isn't available.
Every command emits JSON when stdout is not a TTY (or when --json is set).
The envelope is schema-versioned:
Cat-style exception:
diffmode results --show <path>anddiffmode skill showstream raw file/markdown contents to stdout by default sodiffmode skill show > SKILL.mdand `diffmode results--show
out.md
work as documented. Pass--jsonexplicitly to get the{path, contents}envelope on these two read-out commands; on--showthe envelope also carriestruncated: truewhen--max-tokens` clipped the body.
{ "schema_version": "1", "job_id": "…", "status": "running" }Errors go to stderr with the same envelope shape:
{ "error": { "code": "auth", "message": "…", "retryable": false } }For agent self-discovery, run diffmode commands — it dumps the full
commander tree as a stable, machine-readable manifest.
Idempotency-Key is the agent's responsibility (matches gh / stripe
conventions). Generate a UUIDv4 and pass --idempotency-key <uuid> on each
submit (run, workflow, unlock, idea-eval, smoke-test). Same key +
same user → same job_id back (no double-charge). The CLI never
auto-generates the key.
- The CLI never logs the
Authorizationheader value, even with--verbose(redacted toBearer ***). loginreads a PAT from stdin or--tokenbut never echoes it back.- The mode-
0600credential file fallback is only used when the OS keyring is unavailable; the CLI prints a one-time stderr warning when it falls back.
Report security issues per SECURITY.md.
See CHANGELOG.md for the per-version history.
See CONTRIBUTING.md.