diffmode 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "diffmode",
3
+ "version": "0.1.0",
4
+ "description": "Agent-drivable CLI for the Diffmode growth pipeline",
5
+ "license": "Apache-2.0",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/agentic-builders/diffmode-cli.git"
9
+ },
10
+ "homepage": "https://github.com/agentic-builders/diffmode-cli#readme",
11
+ "bugs": "https://github.com/agentic-builders/diffmode-cli/issues",
12
+ "engines": {
13
+ "node": ">=20"
14
+ },
15
+ "bin": {
16
+ "diffmode": "dist/bin.js"
17
+ },
18
+ "files": [
19
+ "dist/",
20
+ "skills/",
21
+ "NOTICE",
22
+ "LICENSE"
23
+ ],
24
+ "scripts": {
25
+ "build": "esbuild src/bin.ts --bundle --platform=node --target=node20 --format=cjs --external:keytar --outfile=dist/bin.js --banner:js='#!/usr/bin/env node' && chmod +x dist/bin.js",
26
+ "dev": "tsx src/bin.ts",
27
+ "test": "vitest run",
28
+ "test:watch": "vitest",
29
+ "lint": "eslint src --ext .ts",
30
+ "typecheck": "tsc --noEmit",
31
+ "sync:companions": "tsx scripts/sync-companions.ts",
32
+ "prepublishOnly": "npm run lint && npm run typecheck && npm test && npm run build"
33
+ },
34
+ "dependencies": {
35
+ "commander": "^14.0.0"
36
+ },
37
+ "optionalDependencies": {
38
+ "keytar": "^7.9.0"
39
+ },
40
+ "devDependencies": {
41
+ "@types/node": "^22.0.0",
42
+ "@typescript-eslint/eslint-plugin": "^8.0.0",
43
+ "@typescript-eslint/parser": "^8.0.0",
44
+ "esbuild": "^0.28.0",
45
+ "eslint": "^9.0.0",
46
+ "msw": "^2.14.0",
47
+ "tsx": "^4.22.0",
48
+ "typescript": "^6.0.0",
49
+ "vitest": "^4.1.0"
50
+ }
51
+ }
@@ -0,0 +1,32 @@
1
+ ---
2
+ description: Operate the diffmode CLI to generate growth plans, personas, and focus-group simulations against the hosted Diffmode API.
3
+ alwaysApply: false
4
+ ---
5
+ # diffmode CLI
6
+
7
+ <!-- DO NOT EDIT — generated by scripts/sync-companions.ts from SKILL.md -->
8
+
9
+ Use the `diffmode` CLI to operate the hosted growth-strategy API.
10
+
11
+ ## When to invoke
12
+ - User asks for a growth plan, personas, focus group, or names diffmode.
13
+ - Confirm: `diffmode --version` and `diffmode whoami --json`.
14
+
15
+ ## Default flow
16
+ 1. `diffmode limits --json` — credits.
17
+ 2. `diffmode run <product> --input founder.json --idempotency-key <uuid> --json`
18
+ 3. `diffmode jobs watch <job_id> --json --wait 4h`
19
+ 4. `diffmode results <product> --json` then `--summary --json`.
20
+ 5. `diffmode unlock <product>` (optional, 15 cr).
21
+
22
+ ## Contract
23
+ - Always pass `--json`. Stdout = data; stderr = progress/errors.
24
+ - Generate your own UUIDv4 for `--idempotency-key` (CLI never auto-generates).
25
+ - `--input founder.json` required for `run`/`workflow`/`smoke-test`.
26
+ - On exit 8, redirect user to https://diffmode.app/app/billing. No CLI top-up command exists.
27
+ - Exit codes: `4` auth · `5` conflict (job_id in stderr) · `7` rate-limited ·
28
+ `8` insufficient-credits · `10` interrupted-resumable.
29
+
30
+ ## Reference
31
+ - https://github.com/agentic-builders/diffmode-cli
32
+ - https://diffmode.app
@@ -0,0 +1,35 @@
1
+ # diffmode — agent contract
2
+
3
+ <!-- DO NOT EDIT — generated by scripts/sync-companions.ts from SKILL.md -->
4
+
5
+ Agent-drivable CLI for the Diffmode growth pipeline.
6
+
7
+ ## When to use
8
+ - User asks for a growth plan, personas, focus group, or any task using `diffmode`.
9
+ - Verify: `diffmode --version` and `diffmode whoami --json` (exit 4 → `diffmode login`).
10
+
11
+ ## Default flow
12
+ 1. `diffmode limits --json` — confirm credits (1 run / 5 idea-eval / 15 unlock).
13
+ 2. `diffmode run <product> --input founder.json --idempotency-key <uuid> --json`
14
+ 3. `diffmode jobs watch <job_id> --json --wait 4h` (stderr = progress).
15
+ 4. `diffmode results <product> --json` — manifest first; never dump full bundle.
16
+ 5. `diffmode results <product> --summary --json` — keyFinding sections (~3 k tok).
17
+ 6. `diffmode unlock <product> --idempotency-key <uuid> --json` (optional, 15 cr).
18
+
19
+ ## Contract
20
+ - `--json` on every call. Stdout = data; stderr = progress/errors.
21
+ - **Idempotency is yours.** Generate a UUIDv4 per submit; CLI does NOT auto-generate.
22
+ - **Founder input** is required for `run`, `workflow`, `smoke-test`. Use `--input` or
23
+ `--from-url`. `unlock` reuses the prior free-tier's input.
24
+ - `idea-eval` takes a JSON array (not strings) — see `references/idea-input-schema.md`.
25
+ - **Billing is browser-only.** On exit 8, redirect user to https://diffmode.app/app/billing.
26
+
27
+ ## Exit codes (spec §8)
28
+ `0` ok · `1` generic · `2` usage · `3` network · `4` auth ·
29
+ `5` conflict · `6` not-found · `7` rate-limited · `8` insufficient-credits ·
30
+ `9` server · `10` interrupted-resumable · `130` SIGINT.
31
+ Full recovery: `references/error-codes.md`.
32
+
33
+ ## See also
34
+ - https://github.com/agentic-builders/diffmode-cli
35
+ - https://diffmode.app
@@ -0,0 +1,136 @@
1
+ ---
2
+ name: diffmode
3
+ description: Use this skill whenever the user asks to generate, run, retrieve, or apply a growth plan, marketing strategy, persona research, or focus group simulation with the Diffmode CLI. Triggers on phrases like "growth plan", "diffmode run", "personas", "focus group", "growth strategy", and any instruction to operate the `diffmode` CLI. The skill orchestrates the `diffmode` CLI end-to-end against the hosted growth-pipeline API — authenticate, pre-flight credits, submit a run, watch the job, retrieve manifest-shaped results, and apply tactics. Use this any time the user mentions Diffmode or asks for a bootstrapped-SaaS growth plan, even if they don't explicitly name the CLI.
4
+ ---
5
+
6
+ # Diffmode
7
+
8
+ You are operating the `diffmode` CLI on behalf of the user. It is a thin HTTP
9
+ client to a hosted growth-strategy API. A full plan run can take 10 minutes to
10
+ several hours and produces dozens of markdown files. **Never dump full outputs
11
+ into your context** — always work through the manifest emitted by
12
+ `diffmode results`.
13
+
14
+ ## When to use this skill
15
+
16
+ - User says "use diffmode", "generate a growth plan", "run diffmode for
17
+ <product>", "show the personas", or asks to apply a plan produced by
18
+ Diffmode.
19
+ - User has installed the CLI (verify with `diffmode --version`) and
20
+ authenticated (verify with `diffmode whoami --json`).
21
+
22
+ ## When NOT to use this skill
23
+
24
+ - For generic marketing advice not tied to a Diffmode product.
25
+ - If the user wants to top up credits — Diffmode billing is **browser-only**.
26
+ On exit 8, redirect them to `https://diffmode.app/app/billing` (or the
27
+ resolver URL in the error payload). There is no `diffmode billing topup`
28
+ command.
29
+ - If `diffmode` is not installed — instruct the user to run
30
+ `npx diffmode@latest login` once, then resume.
31
+
32
+ ## Operating contract
33
+
34
+ - The CLI is **non-interactive** when stdout is not a TTY. Always pass
35
+ `--json` and parse the schema-versioned envelope.
36
+ - **Stdout is data; stderr is progress/errors.** Both carry valid JSON when
37
+ `--json` is set.
38
+ - **Exit codes** are part of the public contract:
39
+ - `0` ok · `1` generic · `2` usage · `3` network · `4` auth ·
40
+ `5` conflict (409) · `6` not-found · `7` rate-limited ·
41
+ `8` insufficient-credits (402) · `9` server ·
42
+ `10` interrupted-resumable · `130` SIGINT
43
+ - Full recovery guidance: `references/error-codes.md`.
44
+ - **Idempotency is the agent's responsibility.** The CLI does NOT
45
+ auto-generate an `Idempotency-Key` header. Generate a UUIDv4 yourself and
46
+ pass `--idempotency-key <uuid>` on every submit (`run`, `unlock`,
47
+ `workflow`, `idea-eval`, `smoke-test`). Same key + same user → same
48
+ `job_id` (no double-charge). Matches `gh`/`stripe` UX.
49
+ - **Founder input is required** for `run`, `workflow`, and `smoke-test`. Use
50
+ `--input founder.json` (canonical) or `--from-url <url>` (CLI calls
51
+ `/public/v1/analyze-website` to pre-fill). Schema:
52
+ `references/founder-input-schema.md`. `unlock` reuses the prior
53
+ free-tier's stored input — do not re-supply.
54
+ - **Idea-eval** takes a structured JSON array, not strings — see
55
+ `references/idea-input-schema.md`.
56
+
57
+ ## Default workflow
58
+
59
+ 1. **Authenticate (one-time per machine).**
60
+ `diffmode whoami --json` → on exit 4, stop and tell the user
61
+ `npx diffmode@latest login` (or `diffmode login --token dm_pat_…`) in
62
+ their terminal, then resume.
63
+ 2. **Pre-flight credits.**
64
+ `diffmode limits --json` → if `credits_available < N` (1 for `run`/
65
+ `smoke-test`, 5 for `idea-eval`, 15 for `unlock`/`workflow`), echo the
66
+ `billing_url` and stop. The CLI's submit also does this pre-flight by
67
+ default; `--no-preflight` skips it.
68
+ 3. **Submit a run (default = free-tier, 1 credit).**
69
+ Generate a UUIDv4 and run
70
+ `diffmode run <product> --input founder.json --idempotency-key <uuid> --json`.
71
+ On exit 5 (CONFLICT), parse `error.job_id` from stderr and resume at
72
+ step 4 with that id.
73
+ 4. **Watch.**
74
+ `diffmode jobs watch <job_id> --json --wait 4h`. This blocks; the CLI
75
+ handles `next_poll_ms` backoff and prints progress to stderr.
76
+ - exit 10 (RESUMABLE) → run `diffmode jobs resume <job_id>` once, then
77
+ re-watch.
78
+ - exit 7 (rate-limited) → respect `error.retry_after`; sleep then retry.
79
+ - exit 9 twice in a row → stop, surface to the user.
80
+ - Ctrl-C never cancels the server job — print "resume with
81
+ `diffmode jobs watch <job_id>`" and exit 130.
82
+ 5. **Retrieve results (manifest-first; never read the full bundle).**
83
+ `diffmode results <product> --json` → read the manifest only. Then read
84
+ `report.json` keyFinding sections via
85
+ `diffmode results <product> --summary --json` (~3 k tokens).
86
+ 6. **Drill down deliberately.**
87
+ - Buyer personas (free-tier report sections are: `landscape`,
88
+ `advantages`, `buyers`, `blockers`, `growthPlan`):
89
+ `diffmode results <product> --stage buyers --summary --json`, then
90
+ `--pull` once and `--show <relative-path>.md` for any persona file
91
+ listed in the manifest.
92
+ - A tactic: `diffmode results <product> --tactic <id-or-name>` (look up
93
+ valid tactic ids/names via `--stage growthPlan --summary --json`).
94
+ - Always page large files with `--max-tokens 4000` unless the user asks
95
+ for the full file.
96
+ 7. **Optional unlock (15 credits).**
97
+ `diffmode unlock <product> --idempotency-key <uuid> --json`. Requires a
98
+ completed `diffmode run` for the same product first — on 422, prompt the
99
+ user to run free-tier first.
100
+ 8. **Apply the plan.** Present the executive summary and proposed actions.
101
+ **Stop and confirm** before making any code/copy/config changes. Treat
102
+ each tactic as its own edit-review-commit loop.
103
+
104
+ ## Human-checkpoint policy
105
+
106
+ - Submit a run only after confirming product name AND that the user
107
+ understands it costs credits.
108
+ - Apply changes to files only after presenting a diff and getting explicit
109
+ user approval.
110
+ - Never re-run the pipeline against the same product within 30 minutes
111
+ without asking.
112
+
113
+ ## Failure recovery (cheat sheet)
114
+
115
+ | Exit | Meaning | Action |
116
+ | --- | --- | --- |
117
+ | 4 | Auth | Ask the user to `diffmode login`. |
118
+ | 5 | Conflict (in-flight job) | Parse `error.job_id`; jump to step 4 (watch). |
119
+ | 7 | Rate limited | Sleep `error.retry_after` (or surface if > 5 min). |
120
+ | 8 | Insufficient credits | Print `billing_url` from the error; stop. |
121
+ | 10 | Interrupted (resumable) | `diffmode jobs resume <id>` once, re-watch. |
122
+ | 130 | SIGINT | Confirm whether to re-watch — do NOT auto-cancel. |
123
+
124
+ See `references/error-codes.md` for every code + per-command coverage.
125
+
126
+ ## See also
127
+
128
+ - `references/commands.md` — full command catalog with endpoints, credit
129
+ costs, flags, and example invocations.
130
+ - `references/error-codes.md` — exit codes + per-code recovery script.
131
+ - `references/founder-input-schema.md` — `FounderDiagnostics` shape for
132
+ `--input`.
133
+ - `references/idea-input-schema.md` — `IdeaInput` array shape for
134
+ `--ideas-file`.
135
+ - `https://github.com/agentic-builders/diffmode-cli` — repo + issue tracker.
136
+ - `https://diffmode.app` — top-up + dashboard (browser-only billing).
@@ -0,0 +1,20 @@
1
+ # diffmode
2
+
3
+ <!-- DO NOT EDIT — generated by scripts/sync-companions.ts from SKILL.md -->
4
+
5
+ > Agent-drivable CLI for the Diffmode growth pipeline. Generate growth plans,
6
+ > personas, and focus-group simulations against the hosted Diffmode API. PAT
7
+ > auth, JSON-on-non-TTY, durable jobs, browser-only billing.
8
+
9
+ ## Docs
10
+
11
+ - [Repository](https://github.com/agentic-builders/diffmode-cli): source, README, exit codes, CHANGELOG.
12
+ - [SKILL.md](https://github.com/agentic-builders/diffmode-cli/blob/main/skills/diffmode/SKILL.md): canonical agent skill.
13
+ - [Commands reference](https://github.com/agentic-builders/diffmode-cli/blob/main/skills/diffmode/references/commands.md): endpoint, credit cost, flags, examples per command.
14
+ - [Exit codes](https://github.com/agentic-builders/diffmode-cli/blob/main/skills/diffmode/references/error-codes.md): exit-code contract + per-code recovery scripts.
15
+ - [Founder input schema](https://github.com/agentic-builders/diffmode-cli/blob/main/skills/diffmode/references/founder-input-schema.md): `FounderDiagnostics` shape for `--input`.
16
+ - [Idea-eval input schema](https://github.com/agentic-builders/diffmode-cli/blob/main/skills/diffmode/references/idea-input-schema.md): `IdeaInput` array for `--ideas-file`.
17
+
18
+ ## Optional
19
+
20
+ - [Dashboard](https://diffmode.app): mint PATs at `/app/tokens`, top up credits at `/app/billing`.
@@ -0,0 +1,295 @@
1
+ # Commands reference
2
+
3
+ Complete catalog of `diffmode` commands. Each entry lists: the backend
4
+ endpoint it calls, credit cost (where applicable), required + optional
5
+ flags, exit codes, and example invocations (TTY + `--json` forms). For a
6
+ machine-readable version of this table, run `diffmode commands --json`.
7
+
8
+ > **Drift policy.** The CLI emits its commander tree as a manifest; the
9
+ > test `test/commands-reference-drift.test.ts` asserts every command listed
10
+ > here also appears in `diffmode commands --json`. Don't add a new command
11
+ > without updating this file.
12
+
13
+ ## Globals (apply to every command)
14
+
15
+ | Flag | Description |
16
+ | --- | --- |
17
+ | `--json` | Emit machine-readable JSON (forces JSON even on a TTY). |
18
+ | `--no-color` | Disable ANSI colors. |
19
+ | `--quiet` | Suppress stderr progress. |
20
+ | `--verbose` | Verbose stderr output. |
21
+ | `--yes` | Auto-confirm interactive prompts. |
22
+ | `--token <pat>` | PAT override (precedence: `--token` > `DIFFMODE_TOKEN` env > stored). |
23
+ | `--profile <name>` | Configuration profile (default `default`). |
24
+ | `--timeout <s>` | Per-HTTP-request timeout in seconds (default 60). |
25
+
26
+ `--idempotency-key <uuid>` is **subcommand-scoped** (on submit commands
27
+ only) and **not** a global flag.
28
+
29
+ ## Auth
30
+
31
+ ### `diffmode login`
32
+
33
+ - **Endpoint:** `GET /public/v1/access-tokens` (validates PAT)
34
+ - Reads a PAT from stdin or `--token`. Stores it via OS keyring (or 0600
35
+ file fallback with a one-time stderr warning).
36
+ - **Exits:** 0, 1, 2, 3, 4, 9
37
+ - Examples:
38
+ ```bash
39
+ diffmode login --token dm_pat_…
40
+ echo "$DIFFMODE_TOKEN" | diffmode login
41
+ ```
42
+
43
+ ### `diffmode logout`
44
+
45
+ - Clears stored credentials for the active profile. Idempotent.
46
+ - **Exits:** 0
47
+
48
+ ### `diffmode whoami`
49
+
50
+ - **Endpoint:** `GET /public/v1/access-tokens`
51
+ - Verifies the active token; prints identity metadata.
52
+ - **Exits:** 0, 1, 3, 4, 9
53
+ - Example: `diffmode whoami --json`
54
+
55
+ ## Submit (job-creating)
56
+
57
+ All submit commands accept `--idempotency-key <uuid>` (optional, no
58
+ auto-generation). The CLI does a pre-flight `GET /billing/balance` before
59
+ posting unless `--no-preflight` is set.
60
+
61
+ ### `diffmode run <product>` (default, **1 credit**)
62
+
63
+ - **Endpoint:** `POST /public/v1/free-tier`
64
+ - **Required input:** `--input <file|->` or `--from-url <url>` (founder
65
+ diagnostics; see `founder-input-schema.md`).
66
+ - **Flags:** `--input`, `--from-url`, `--save-input`, `--idempotency-key`,
67
+ `--no-preflight`
68
+ - **Exits:** 0, 1, 2, 3, 4, 5, 7, 8, 9
69
+ - Examples:
70
+ ```bash
71
+ diffmode run myproduct --input founder.json --idempotency-key "$(uuidgen)"
72
+ diffmode run myproduct --from-url https://example.com --json
73
+ ```
74
+
75
+ ### `diffmode workflow <product>` (**15 credits**)
76
+
77
+ - **Endpoint:** `POST /public/v1/workflow`
78
+ - Cold-start full plan. Power-user verb.
79
+ - **Flags:** identical surface to `run`.
80
+ - **Exits:** 0, 1, 2, 3, 4, 5, 7, 8, 9
81
+
82
+ ### `diffmode unlock <product>` (**15 credits**)
83
+
84
+ - **Endpoint:** `POST /public/v1/products/{id}/unlock`
85
+ - Server reuses the founder input from the prior completed free-tier run;
86
+ no `--input` accepted here. On 422 → CLI exits 2 with
87
+ `Run \`diffmode run <p>\` first.`
88
+ - **Flags:** `--idempotency-key`, `--no-preflight`
89
+ - **Exits:** 0, 1, 2, 3, 4, 5, 7, 8, 9
90
+
91
+ ### `diffmode idea-eval <product>` (**5 credits**)
92
+
93
+ - **Endpoint:** `POST /public/v1/idea-eval`
94
+ - **Required input:** `--ideas-file <path>` — JSON array of `IdeaInput`
95
+ objects (see `idea-input-schema.md`). Not resumable.
96
+ - **Flags:** `--ideas-file`, `--intuition`, `--target-idea`,
97
+ `--idempotency-key`, `--no-preflight`
98
+ - **Exits:** 0, 1, 2, 3, 4, 5, 7, 8, 9
99
+ - Example:
100
+ ```bash
101
+ diffmode idea-eval myproduct --ideas-file ideas.json \
102
+ --intuition "founder-mode onboarding is the highest-leverage" \
103
+ --json
104
+ ```
105
+
106
+ ### `diffmode smoke-test <product>` (**1 credit**)
107
+
108
+ - **Endpoint:** `POST /public/v1/smoke-test`
109
+ - Always pass `--input` (CLI does NOT rely on the server-side disk
110
+ fallback used by local-CLI mode). Not resumable.
111
+ - **Flags:** `--input`, `--from-url`, `--save-input`, `--idempotency-key`,
112
+ `--no-preflight`
113
+ - **Exits:** 0, 1, 2, 3, 4, 5, 7, 8, 9
114
+
115
+ ## Jobs
116
+
117
+ ### `diffmode jobs list`
118
+
119
+ - **Endpoint:** `GET /public/v1/jobs?limit=&cursor=&product_id=&status=`
120
+ - Keyset pagination (max `--limit 200`).
121
+ - **Flags:** `--product`, `--status`, `--limit`, `--cursor`
122
+ - **Exits:** 0, 1, 3, 4, 9
123
+ - Examples:
124
+ ```bash
125
+ diffmode jobs list --product myproduct --json
126
+ diffmode jobs list --cursor "$NEXT_CURSOR"
127
+ ```
128
+
129
+ ### `diffmode jobs status <job_id>`
130
+
131
+ - **Endpoint:** `GET /public/v1/jobs/{job_id}`
132
+ - **Exits:** 0, 1, 3, 4, 6, 9
133
+
134
+ ### `diffmode jobs watch <job_id>`
135
+
136
+ - Repeated `GET /public/v1/jobs/{job_id}`; honors `next_poll_ms` with
137
+ ±20 % jitter clamped to `[3 s, 30 s]`.
138
+ - **Flags:** `--wait <duration>` (e.g. `4h`, `30m`, `300s`; this is the
139
+ **total polling wait**, distinct from the global per-request
140
+ `--timeout`). The deadline is enforced at the start of every poll
141
+ iteration AND retry sleeps (429 `Retry-After`, transient backoff) are
142
+ clamped to the remaining budget, so a single long `Retry-After` cannot
143
+ push the watch past `--wait`.
144
+ - **Exits:** 0, 1, 3, 4, 6, 7, 9, 10, 130
145
+ - Persistent `429` responses (≥5 in a row) surface as exit 7 with code
146
+ `rate_limited` and the server's `Retry-After` echoed in the envelope.
147
+ - `--wait` deadline exhaustion exits **1** with `code: "generic"` (the
148
+ server-side job keeps running; re-watch to resume). This is distinct
149
+ from exit 7 — the CLI has no `retry_after` to promise on a client-side
150
+ timeout, so it deliberately does NOT pose as back-pressure.
151
+ - Ctrl-C: prints `Resume with: diffmode jobs watch <id>` to stderr; never
152
+ calls `DELETE /jobs/{id}`.
153
+
154
+ ### `diffmode jobs resume <job_id>`
155
+
156
+ - Two-step:
157
+ 1. `GET /public/v1/jobs/{job_id}` to fetch `module_type` + `product_id`.
158
+ 2. Branch:
159
+ - `free-tier` → `POST /public/v1/free-tier/{product_id}/retry`
160
+ - `workflow` → `POST /public/v1/workflow/resume`
161
+ - other modules → exit 2 with "module is not resumable" hint.
162
+ - **Flags:** `--idempotency-key`
163
+ - **Exits:** 0, 1, 2, 3, 4, 6, 9
164
+
165
+ ### `diffmode jobs cancel <job_id>`
166
+
167
+ - **Endpoint:** `DELETE /public/v1/jobs/{job_id}`
168
+ - Idempotent; on TTY prompts unless global `--yes` is set.
169
+ - **Exits:** 0, 1, 2, 3, 4, 6, 9
170
+ - Declining the interactive `y/N` confirmation exits 2 with code `usage`
171
+ (no `DELETE` issued) — same envelope agents already handle for malformed
172
+ flags, so the path is predictable from `diffmode commands --json`.
173
+
174
+ ## Results
175
+
176
+ ### `diffmode results <product>`
177
+
178
+ - Resolves the latest completed job (or `--job-id <id>`), downloads
179
+ `/products/{id}/outputs`, and emits a manifest:
180
+ ```json
181
+ {
182
+ "schema_version": "1",
183
+ "product": "<p>",
184
+ "job_id": "<id>",
185
+ "module_type": "free-tier",
186
+ "out_dir": ".diffmode/<p>/<id>/",
187
+ "total_files": 14,
188
+ "total_bytes_est": 184323,
189
+ "report_sections": ["meta", "landscape", "advantages", "growthPlan", ...]
190
+ }
191
+ ```
192
+ - **Flags:** `--job-id`, `--out`, `--summary`, `--show <path>`,
193
+ `--max-tokens <n>`, `--pull`, `--stage <s>`, `--tactic <t>`
194
+ - **Exits:** 0, 1, 2, 3, 4, 6, 9
195
+ - `--summary` returns `report.json` keyFinding sections for free-tier
196
+ jobs; for workflow/unlock it prints a Phase-2 stub.
197
+ - **Phase-1 `--job-id` caveat:** `/products/{id}/outputs` returns the
198
+ current product workspace; the API does not yet serve per-job artifact
199
+ snapshots. `--job-id` pins the manifest's `job_id` field, but downloaded
200
+ files always reflect the latest run. If the pinned job is not the latest
201
+ completed run, the manifest JSON carries `latest_completed_job_id`
202
+ (always emitted, not silenced by `--quiet`), the CLI redirects the local
203
+ snapshot dir to `<latest-job>/` so any prior `<pinned>/` snapshot stays
204
+ intact, and a stderr note describes the redirect for humans. If the
205
+ advisory drift lookup itself fails (transient 429/5xx/network), the
206
+ manifest sets `drift_lookup_failed: true` and the CLI warns on stderr
207
+ that drift status could not be verified. Per-job snapshots ship with the
208
+ Phase-2 manifest endpoint.
209
+
210
+ ## Billing (read-only)
211
+
212
+ ### `diffmode account`
213
+
214
+ - **Endpoint:** `GET /public/v1/billing/balance`
215
+ - Pretty table on TTY; full `CreditBalance` JSON on `--json`.
216
+ - **Exits:** 0, 1, 3, 4, 9
217
+
218
+ ### `diffmode billing balance`
219
+
220
+ - Terse `{balance, has_purchased}` (or pretty on TTY).
221
+ - **Exits:** 0, 1, 3, 4, 9
222
+
223
+ ### `diffmode billing history`
224
+
225
+ - **Endpoint:** `GET /public/v1/billing/history?limit=&offset=`
226
+ - **Offset-based** pagination (not B5 keyset). NDJSON output on non-TTY.
227
+ - **Flags:** `--limit`, `--offset`
228
+ - **Exits:** 0, 1, 3, 4, 9
229
+
230
+ ### `diffmode limits`
231
+
232
+ - Derives credit availability from `/billing/balance` plus the documented
233
+ rate-limit policy (3 submissions / 24 h for non-paying).
234
+ - **Exits:** 0, 1, 3, 4, 9
235
+ - Does NOT estimate `free_submits_remaining` — the backend doesn't expose
236
+ remaining slots and a CLI-local guess would lie across devices.
237
+
238
+ ### NO `diffmode billing topup`
239
+
240
+ Top-up is **browser-only by design**. On exit 8 from any submit, the CLI
241
+ prints `Insufficient credits. Top up at <DIFFMODE_BILLING_URL or default>`
242
+ and exits. Override the redirect with `DIFFMODE_BILLING_URL`.
243
+
244
+ ## Diagnostics helpers
245
+
246
+ ### `diffmode diagnostics from-url <url>`
247
+
248
+ - **Endpoint:** `POST /public/v1/analyze-website`
249
+ - Prints a draft `FounderDiagnostics` JSON; `--save <path>` writes to
250
+ disk instead.
251
+ - **Exits:** 0, 1, 2, 3, 4, 9
252
+
253
+ ### `diffmode diagnostics validate <path>`
254
+
255
+ - Validates a founder-input JSON file against the documented schema. Exits
256
+ 0 if valid, 2 with field-level errors otherwise.
257
+ - **Exits:** 0, 1, 2
258
+
259
+ ## Self-describing
260
+
261
+ ### `diffmode commands`
262
+
263
+ - Emits the full commander tree as a manifest. Always JSON (no `--json`
264
+ required). Stable schema; use it for agent discovery.
265
+ - **Exits:** 0
266
+
267
+ ### `diffmode --version --json`
268
+
269
+ - Emits `{schema_version, version, node, platform}`. Plain text without
270
+ `--json`.
271
+
272
+ ## Agent integration
273
+
274
+ ### `diffmode skill show`
275
+
276
+ - Prints the bundled `SKILL.md` to stdout (`{path, contents}` on `--json`).
277
+ Useful for agents that want to inspect the skill without installing it.
278
+ - **Exits:** 0, 1
279
+
280
+ ### `diffmode skill install`
281
+
282
+ - Copies the bundled skill into per-tool agent dirs.
283
+ - **Flags:**
284
+ - `--target <claude|codex|cursor|all>` (default `all`)
285
+ - `--yes` overwrites a divergent existing file (without it, the command
286
+ reports `needs-confirm` and writes nothing)
287
+ - `--dry-run` reports the action without writing
288
+ - `--print-paths` prints the resolved target paths and exits
289
+ - **Default paths** (override with `DIFFMODE_SKILL_{CLAUDE,CODEX,CURSOR}_PATH`):
290
+ - Claude: `~/.claude/skills/diffmode/SKILL.md`
291
+ - Codex: `~/.codex/skills/diffmode/SKILL.md`
292
+ - Cursor: `~/.cursor/rules/diffmode.mdc`
293
+ - Skips a target gracefully when the parent tool's home dir is missing
294
+ (e.g., Claude Code not installed) — non-fatal.
295
+ - **Exits:** 0, 1, 2