amicus 1.9.0 → 2.0.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/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +149 -0
- package/README.md +40 -170
- package/bin/amicus.js +14 -20
- package/commands/council.md +3 -1
- package/electron/fold.js +10 -1
- package/electron/ipc-setup.js +10 -15
- package/electron/main.js +21 -16
- package/electron/preload-setup.js +0 -1
- package/electron/setup-ui-council.js +64 -10
- package/electron/setup-ui-styles.js +34 -3
- package/electron/setup-ui.js +44 -12
- package/package.json +2 -5
- package/skills/second-opinion/MODEL-NOTES.md +2 -2
- package/skills/second-opinion/SKILL.md +24 -23
- package/skills/sidecar/SKILL.md +3 -3
- package/src/cli-handlers-council.js +101 -1
- package/src/cli-handlers-doctor.js +7 -0
- package/src/cli-handlers-run.js +4 -4
- package/src/cli-handlers-spend.js +198 -0
- package/src/cli.js +35 -0
- package/src/council/presets-cli.js +141 -0
- package/src/headless.js +146 -38
- package/src/index.js +1 -9
- package/src/mcp-server.js +132 -108
- package/src/mcp-tools.js +27 -3
- package/src/mcp-wait.js +8 -5
- package/src/opencode-client.js +33 -10
- package/src/prompt-builder.js +32 -11
- package/src/session-manager.js +7 -14
- package/src/sidecar/continue.js +12 -5
- package/src/sidecar/conversation-mirror.js +22 -1
- package/src/sidecar/crash-handler.js +2 -1
- package/src/sidecar/fanout-leg.js +12 -3
- package/src/sidecar/fanout.js +27 -10
- package/src/sidecar/interactive-process.js +6 -17
- package/src/sidecar/interactive.js +5 -6
- package/src/sidecar/models.js +33 -4
- package/src/sidecar/progress.js +2 -1
- package/src/sidecar/read.js +4 -6
- package/src/sidecar/resume.js +19 -4
- package/src/sidecar/session-finalize.js +2 -1
- package/src/sidecar/session-utils.js +13 -35
- package/src/sidecar/setup-window.js +2 -3
- package/src/sidecar/start.js +22 -7
- package/src/utils/abort-coordinator.js +57 -7
- package/src/utils/api-key-store.js +2 -13
- package/src/utils/config.js +30 -43
- package/src/utils/council-presets.js +87 -0
- package/src/utils/env-loader.js +1 -2
- package/src/utils/fold-marker.js +79 -0
- package/src/utils/idle-watchdog.js +9 -12
- package/src/utils/lifecycle.js +1 -1
- package/src/utils/mcp-discovery.js +29 -5
- package/src/utils/mcp-self-identity.js +12 -5
- package/src/utils/model-catalog.js +54 -6
- package/src/utils/read-slice.js +73 -0
- package/src/utils/remediation-hints.js +9 -0
- package/src/utils/result-schema.js +8 -2
- package/src/utils/session-abort.js +1 -1
- package/src/utils/session-index-tmp-sweep.js +80 -0
- package/src/utils/session-index.js +4 -5
- package/src/utils/session-path.js +6 -10
- package/src/utils/shared-server.js +7 -5
- package/src/utils/spend-ledger.js +80 -0
- package/src/utils/updater.js +2 -3
- package/src/utils/env-compat.js +0 -38
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "amicus",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Multi-model LLM Council + parallel AI window for Claude Code. Run structured council reviews across Gemini, GPT, DeepSeek and more — or fork a conversation to any model and fold the results back.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Christian Wagner"
|
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,155 @@ All notable changes to Amicus are documented here. Format follows
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [2.0.0] - 2026-07-03
|
|
9
|
+
|
|
10
|
+
Amicus's first major release: the **`sidecar*` shim removal** (#19). v1.x carried a full
|
|
11
|
+
compatibility surface so installs and integrations from before the Amicus rebrand kept working —
|
|
12
|
+
legacy env vars, CLI bin names, config/session directory fallbacks, MCP tool aliases, and deprecated
|
|
13
|
+
public-API exports. v2.0.0 removes all of it in one pass; see **Migration** below for the exact old
|
|
14
|
+
form → new form for every removed shim, including the one that needs a manual one-time step. Most
|
|
15
|
+
installs need zero action (config/session data auto-migrated forward across v1.x; plugin-channel
|
|
16
|
+
installs float to the latest version automatically). Beyond the shim removal, this release rolls up
|
|
17
|
+
five phases of engine and docs work that shipped since 1.9.1: a fully deterministic council CLI
|
|
18
|
+
transport (`validate`/`verdict`/presets/spend ledger), `amicus_read` paging for large content, a
|
|
19
|
+
per-tool-call stall detector, per-run-nonced fold markers, atomic metadata writes throughout, POSIX
|
|
20
|
+
server teardown hardening, and a full documentation overhaul (`docs/council.md`, restructured
|
|
21
|
+
README, "where things live" config-dir reference).
|
|
22
|
+
|
|
23
|
+
### Migration (from any sidecar*-era setup)
|
|
24
|
+
|
|
25
|
+
Full removal record and rationale: [docs/SHIMS.md](docs/SHIMS.md). Per-shim remedy:
|
|
26
|
+
|
|
27
|
+
| Old form (sidecar*-era) | New form / remedy |
|
|
28
|
+
| --- | --- |
|
|
29
|
+
| `SIDECAR_*` env vars (`SIDECAR_ENV_DIR`, `SIDECAR_IDLE_TIMEOUT*`, `SIDECAR_DEBUG_PORT`, `SIDECAR_MOCK_UPDATE`) | Rename to the `AMICUS_*` equivalent (`AMICUS_ENV_DIR`, `AMICUS_IDLE_TIMEOUT*`, `AMICUS_DEBUG_PORT`, `AMICUS_MOCK_UPDATE`). Unrenamed vars are now silently ignored — no warning, no fallback. |
|
|
30
|
+
| `SIDECAR_MAX_SESSIONS` | Rename to `AMICUS_MAX_SESSIONS` — this was the last legacy-prefixed env var read anywhere in the codebase. |
|
|
31
|
+
| `sidecar` / `claude-sidecar` CLI commands | Use `amicus` (or the `am` short alias). An `EEXIST` on `npm install -g amicus` naming an old `claude-sidecar`/`sidecar` file means a *stale* global install of the old upstream package, not this shim — see [docs/troubleshooting.md](docs/troubleshooting.md#install-fails-with-eexist--claude-sidecar). |
|
|
32
|
+
| `~/.config/sidecar` config dir | No action for most users — every v1.x launch auto-copied `~/.config/sidecar/` into `~/.config/amicus/` once, non-destructively. Only if you skipped every v1.x release and jump straight from pre-rebrand to v2.0.0: copy `~/.config/sidecar/` to `~/.config/amicus/` by hand — `getConfigDir()` no longer reads the old location at all. |
|
|
33
|
+
| `.claude/sidecar_sessions/` | Not auto-migrated (per-project). Rename to `.claude/amicus_sessions/` in any project whose history you want `amicus list`/`amicus read` to see again. |
|
|
34
|
+
| `[SIDECAR_CONFIG_UPDATE]` stderr marker / `sidecar-config-hash` HTML-comment | The `sidecar` skill now instructs the canonical forms only: `[AMICUS_CONFIG_UPDATE]` / `<!-- amicus-config-hash: ... -->`. A stale `<!-- sidecar-config-hash: ... -->` comment in an old CLAUDE.md is simply no longer recognized; the next `amicus setup` alias change writes a fresh one, and the stale comment can be deleted by hand. |
|
|
35
|
+
| `sidecar_*` MCP tool names / `AMICUS_LEGACY_ALIASES=1` | The tool surface is `amicus_*` only, unconditionally — `AMICUS_LEGACY_ALIASES=1` is now a no-op (regression-pinned in `tests/mcp-server-legacy-aliases.test.js`). Update any MCP client config or tooling that still calls a `sidecar_*` tool name. |
|
|
36
|
+
| `startSidecar`/`listSidecars`/`resumeSidecar`/`continueSidecar`/`readSidecar` (package-root exports) | These were deprecated aliases present on npm through v1.9.1. Only `startAmicus`/`listAmicus`/`resumeAmicus`/`continueAmicus`/`readAmicus` remain exported from `amicus`'s package root — rename any import. |
|
|
37
|
+
|
|
38
|
+
**Kept, not removed** (not part of this migration): the `[SIDECAR_FOLD]`/`[SIDECAR_FOLD:<nonce>]`
|
|
39
|
+
wire-format token (deliberate transport continuity, unrelated to the compat shims), the `sidecar`
|
|
40
|
+
chat-skill's directory name, and the one-shot legacy-`'sidecar'`-MCP-entry cleanup in
|
|
41
|
+
`src/utils/legacy-mcp-migration.js` (re-scoped as a permanent healing tool for stale pre-1.8.0
|
|
42
|
+
dual-registrations — it only removes a `'sidecar'` MCP entry verified identical-in-effect to the
|
|
43
|
+
`'amicus'` one; a customized entry is left alone). The `mcp-self-identity` recursive-spawn guard also
|
|
44
|
+
continues to recognize the old `sidecar`/`claude-sidecar` bin/server names — a defense against a
|
|
45
|
+
stale PATH or MCP config causing amicus to spawn itself, not a restoration of removed behavior.
|
|
46
|
+
|
|
47
|
+
**Plugin-channel installs float automatically.** If you installed Amicus via the Claude Code plugin
|
|
48
|
+
channel, `.claude-plugin/plugin.json` runs `npx -y amicus@latest mcp` — you adopt v2.0.0 on your
|
|
49
|
+
next MCP server start with no upgrade action required. The only thing that can still break for you:
|
|
50
|
+
if your client config or tooling relies on `sidecar_*` tool names or sets
|
|
51
|
+
`AMICUS_LEGACY_ALIASES=1` expecting it to do something, update it — that opt-in is now a no-op and
|
|
52
|
+
the legacy tool names are gone.
|
|
53
|
+
|
|
54
|
+
### Added
|
|
55
|
+
- **`docs/council.md` — the council pipeline documented end-to-end**: the stage flow, the tally-input and
|
|
56
|
+
tally-record schemas field-by-field (test-locked against the real validators), verdict.json provenance,
|
|
57
|
+
presets, and a complete worked example whose every command and output was executed against the binary.
|
|
58
|
+
- **"Where things live"** (docs/configuration.md): the full config-dir tree (config.json shape, catalog
|
|
59
|
+
cache + refresh-outcome fields, both ledgers, tmp files and the doctor sweep), per-client session
|
|
60
|
+
storage, log reality (stderr-only — `LOG_LEVEL` never writes a file), and honest uninstall instructions
|
|
61
|
+
covering what `npm uninstall -g` does NOT clean.
|
|
62
|
+
- README now leads with the **two install channels** (npm global vs Claude Code plugin, with the
|
|
63
|
+
`npx -y amicus@latest` translation note) and surfaces **`/amicus:council`** in the quick start and
|
|
64
|
+
council sections.
|
|
65
|
+
- **`amicus council validate <file>` and `amicus council verdict <tally.json>`** — thin CLI wrappers over the
|
|
66
|
+
existing findings-validation and verdict-builder internals, making the second-opinion skill's council
|
|
67
|
+
transport fully deterministic. `validate` exits 0 (ok) / 2 (validation failed) / 1 (bad args); `verdict`
|
|
68
|
+
writes atomically to `-o` (default `./verdict.json`), `--decisions` optional. The skill's Stage-1 and
|
|
69
|
+
Stage-5 instructions now invoke these commands, and the Stage-2 recipe persists the tally record to
|
|
70
|
+
`<run-folder>/tally.json` (previously it existed only on stdout — the verdict step had nothing to read).
|
|
71
|
+
- **Council presets: `amicus council save/list/show <name>` + built-in `free`/`budget`/`frontier` benches.**
|
|
72
|
+
Built-ins resolve only when the name isn't in your config (your saved councils shadow them; `list` marks
|
|
73
|
+
shadowing). `free` resolves dynamically against the catalog (pinned offline fallback); `budget` and
|
|
74
|
+
`frontier` are alias-based (cheapest / most premium distinct-vendor picks) so alias drift tooling covers
|
|
75
|
+
them. `show` resolves against the cached catalog, including the dynamic free pick.
|
|
76
|
+
- **Per-run cost ledger + `amicus spend`.** Every completed run (headless, interactive, fanout legs)
|
|
77
|
+
appends a best-effort JSONL row (`spend-ledger.jsonl` in the config dir); `amicus spend` rolls up total
|
|
78
|
+
and per-model cost/tokens/source-mix with `--since <N>d` windowing and `--json`, plus an OpenRouter
|
|
79
|
+
remaining-credit footer when a key is configured. Ledger appends can never fail a run.
|
|
80
|
+
- **`amicus_read` paging and size caps.** Responses are capped at ~50KB (default: the TAIL of the content,
|
|
81
|
+
with a truncation notice reporting true byte counts at the start of the body); new optional `offset`,
|
|
82
|
+
`limit`, and `tail` params page through large content. Under-cap reads are byte-identical to before;
|
|
83
|
+
slicing happens before the untrusted-output fence is applied; `metadata` mode is param-exempt but
|
|
84
|
+
defensively capped.
|
|
85
|
+
- **Per-tool-call stall detector in headless runs.** A wedged tool call (pending `tool_use`, no result, no
|
|
86
|
+
other progress for `AMICUS_TOOL_CALL_STALL_MS`, default 3 min) now fails fast with a distinct
|
|
87
|
+
`Tool call stalled: …` reason instead of burning the full run timeout. Fanout legs inherit automatically.
|
|
88
|
+
- **`amicus doctor --fix` sweeps orphaned sessions-index tmp files** (atomic-write artifacts from killed
|
|
89
|
+
processes; only files older than 60s are removed).
|
|
90
|
+
|
|
91
|
+
### Changed
|
|
92
|
+
- **README restructured for audience separation**: discovery + quick start + compact command table with
|
|
93
|
+
pointers; `docs/usage.md` is now the complete CLI reference (the ~30% duplicated content has one
|
|
94
|
+
canonical home each — nothing was dropped); deep dives live under `docs/`.
|
|
95
|
+
- The second-opinion skill's Stage-2 briefing prose reads cleanly again (hardening sentence moved before
|
|
96
|
+
the sentence it interrupted), and `report.md`'s contract is stated once, coherently: `report.html` is
|
|
97
|
+
the deterministic renderer default; `report.md` is the chair-synthesis document that embeds the
|
|
98
|
+
rendered Markdown as one section.
|
|
99
|
+
- **The fold completion marker is now per-run nonced: `[SIDECAR_FOLD:<nonce>]`.** Model output that
|
|
100
|
+
genuinely ends with a bare `[SIDECAR_FOLD]` can no longer force premature completion — the detector
|
|
101
|
+
requires the run's own nonce (BL-7's final hardening layer). The nonce is crypto-random, threaded through
|
|
102
|
+
every mode (headless, fanout, MCP shared-server, interactive GUI), and instructed to the model in the
|
|
103
|
+
prompt; `amicus resume` re-derives it from the transcript.
|
|
104
|
+
- **All session/wave metadata writes are atomic** (`writeFileAtomic` tmp+rename), retiring the torn-read
|
|
105
|
+
race class that pollers previously tolerated via missed-tick workarounds.
|
|
106
|
+
|
|
107
|
+
### Fixed
|
|
108
|
+
- `amicus council --help` now lists `save`/`list`/`show` (the Phase-16 usage-string omission caught by
|
|
109
|
+
a later binary-verification pass).
|
|
110
|
+
- **Setup wizard Step 3 (alias editor) now consumes the same TTL-cached catalog as Step 2** (#12) — one
|
|
111
|
+
catalog load for the whole wizard instead of a separate uncached network fetch per run; the redundant
|
|
112
|
+
`fetch-models` IPC channel is removed.
|
|
113
|
+
- **Stale catalog data is now labeled** (#13): a failed refresh records the attempt and reason in the cache
|
|
114
|
+
doc (never touching the good data), `amicus models` shows a stale memo when refreshing keeps failing,
|
|
115
|
+
`amicus models refresh` reports failure honestly instead of "Refreshed catalog: 0 models" (and its
|
|
116
|
+
`--json` reports the real stale `fetchedAt` instead of `null`), and the wizard shows a stale hint.
|
|
117
|
+
- **The free-council picker is readable** (#27): models grouped by provider with friendly names (raw id as
|
|
118
|
+
the mono secondary line), a roomier scroll area, and a provider count — selection values remain raw model
|
|
119
|
+
ids throughout.
|
|
120
|
+
- **Orphaned `opencode serve` processes on macOS/Linux.** Server teardown now SIGTERMs the Go binary
|
|
121
|
+
directly and escalates to SIGKILL after a bounded grace window on a ref'd poll (the old unref'd 2s timer
|
|
122
|
+
silently died with fast-exiting parents). Windows semantics unchanged.
|
|
123
|
+
- **Aborting a wave immediately after starting it can no longer flip its status back to `running`** — the
|
|
124
|
+
wave metadata merge now honors abort-wins precedence (same rule the per-leg writer already had).
|
|
125
|
+
- **`kill(pid, 0)` throwing `EPERM` now classifies a process as ALIVE** (signal denied ≠ dead) in
|
|
126
|
+
`isProcessAlive`/`checkSessionLiveness` and both MCP crash-detection probes. EPERM no longer marks
|
|
127
|
+
healthy sessions crashed.
|
|
128
|
+
- **A committed successful terminal status can no longer be clobbered to `error`** by a cleanup-step
|
|
129
|
+
failure in the MCP shared-server finalize chain (the Phase-5 review's residual gap).
|
|
130
|
+
- **`discoverCoworkMcps` now checks `%APPDATA%\Claude` on Windows** instead of the XDG path — Claude
|
|
131
|
+
Desktop discovery and doctor's Cowork signal were always wrong on win32.
|
|
132
|
+
|
|
133
|
+
### Removed
|
|
134
|
+
- **Every pre-rebrand `sidecar*` compatibility shim** — see **Migration** above for the full old-form →
|
|
135
|
+
new-form mapping. Also removed: **`sidecar_*` MCP tool aliases + the `AMICUS_LEGACY_ALIASES=1` opt-in**
|
|
136
|
+
(`src/mcp-server.js`) and the **public API `*Sidecar` aliases** (`src/index.js` `module.exports`) —
|
|
137
|
+
both covered in Migration.
|
|
138
|
+
|
|
139
|
+
### Documentation
|
|
140
|
+
- Full sweep of every doc describing the shims as live (README, docs/usage.md, docs/configuration.md,
|
|
141
|
+
docs/testing.md, docs/troubleshooting.md, docs/opencode-integration.md, docs/architecture.md,
|
|
142
|
+
skills/sidecar/SKILL.md, skills/second-opinion/MODEL-NOTES.md) rewritten to v2.0.0 reality.
|
|
143
|
+
`docs/SHIMS.md` re-scoped from a live shim inventory into the removal record the Migration section
|
|
144
|
+
above is built from.
|
|
145
|
+
|
|
146
|
+
## [1.9.1] - 2026-07-03
|
|
147
|
+
|
|
148
|
+
### Fixed
|
|
149
|
+
- **`server.json`'s description now fits the MCP Registry's 100-character cap.** The registry rejected
|
|
150
|
+
v1.9.0's publish (its first-ever attempt) with HTTP 422 — the description was 199 chars against a
|
|
151
|
+
100-char limit the schema doesn't advertise. Shortened to 98 chars; the cap is pinned by
|
|
152
|
+
`tests/scripts/package-manifest.test.js` (characters and UTF-8 bytes), and `docs/DISTRIBUTION.md` §3 now
|
|
153
|
+
documents that content-level 422s are not recoverable by workflow re-run (the re-run checks out the tag)
|
|
154
|
+
— fix `server.json` on main and use the manual path or the next tag. v1.9.0 itself shipped fully to npm
|
|
155
|
+
and GitHub Releases; this patch exists to land the registry publish.
|
|
156
|
+
|
|
8
157
|
## [1.9.0] - 2026-07-03
|
|
9
158
|
|
|
10
159
|
Engine pull-forwards, release-rail hardening, docs sync, and a new Council Review GitHub Action.
|
package/README.md
CHANGED
|
@@ -57,6 +57,13 @@ Claude is the orchestrator. The council and chat skills run *on top of* the engi
|
|
|
57
57
|
|
|
58
58
|
## Quick start
|
|
59
59
|
|
|
60
|
+
> **Two install channels — read this first.** Amicus ships two ways, and CLI commands look different in each:
|
|
61
|
+
>
|
|
62
|
+
> - **npm global** (`npm install -g amicus` or the install script) puts `amicus`/`am` on your `PATH`. Every `amicus <command>` example in this README works as written.
|
|
63
|
+
> - **Claude Code plugin** (`/plugin install amicus@bourbondog-amicus`) does **not** put a CLI on your `PATH`. CLI calls go through `npx -y amicus@latest <command>` instead — e.g. `amicus doctor` becomes `npx -y amicus@latest doctor`. In exchange, the plugin channel gets two things npm does **not**: the slash commands `/amicus:council` and `/amicus:sidecar`. **These are plugin-channel-ONLY — npm users don't get them** and drive the same skills by saying "council review this" / talking to Claude instead.
|
|
64
|
+
>
|
|
65
|
+
> **Convention used throughout this README:** plugin-channel users: prefix CLI examples with `npx -y amicus@latest` (skip the bare `amicus`/`am`). Individual code blocks are not duplicated per channel — this note is the one translation you need.
|
|
66
|
+
|
|
60
67
|
**Install** — pick whichever fits. Every path delivers the MCP server and both skills; the `amicus`/`am` CLI lands on your PATH with the **npm and install-script paths** (the plugin path runs the CLI on demand via `npx -y amicus@latest <command>`):
|
|
61
68
|
|
|
62
69
|
**As a Claude Code plugin** — the most native path if you use Claude Code:
|
|
@@ -67,7 +74,7 @@ Claude is the orchestrator. The council and chat skills run *on top of* the engi
|
|
|
67
74
|
/reload-plugins
|
|
68
75
|
```
|
|
69
76
|
|
|
70
|
-
Claude Code registers the MCP server and both skills for you — nothing to configure. (The plugin does not put `amicus` on your PATH — CLI calls go through `npx -y amicus@latest <command>`; the standalone Electron window is npm-only; and the first council/sidecar call downloads the OpenCode engine.)
|
|
77
|
+
Claude Code registers the MCP server and both skills for you — nothing to configure. It also gets you two slash commands the npm/install-script paths don't: **`/amicus:council`** (run a full council review) and **`/amicus:sidecar`** (fork a conversation to another model). (The plugin does not put `amicus` on your PATH — CLI calls go through `npx -y amicus@latest <command>`; the standalone Electron window is npm-only; and the first council/sidecar call downloads the OpenCode engine.)
|
|
71
78
|
|
|
72
79
|
**With the install script** — macOS, Linux, or Windows (needs [Node.js](https://nodejs.org) ≥ 18):
|
|
73
80
|
|
|
@@ -115,6 +122,8 @@ This opens a graphical wizard:
|
|
|
115
122
|
|
|
116
123
|
> *council review this*
|
|
117
124
|
|
|
125
|
+
Plugin-channel users can also type **`/amicus:council`** directly instead of phrasing it as a request — same skill, explicit invocation.
|
|
126
|
+
|
|
118
127
|
Claude prepares the material, recommends a bench of models, discloses the run shape and cost, and orchestrates the rest. You make the accept/deny calls at the end. (The `second-opinion` skill is what teaches Claude to recognize this — if nothing happens, run `amicus doctor` (or `npx -y amicus@latest doctor`). npm/install-script installs place the skill at `~/.claude/skills/second-opinion/`; plugin installs keep it inside the plugin itself — check `/plugin` in Claude Code to confirm amicus is enabled.)
|
|
119
128
|
|
|
120
129
|
**Your first sidecar.** The sidecar is the lower-level path — you can invoke it by phrase through Claude too, but the CLI gives you the flags directly:
|
|
@@ -178,12 +187,14 @@ Everything you need before your first run, and what's optional.
|
|
|
178
187
|
|
|
179
188
|
## The Council
|
|
180
189
|
|
|
190
|
+
> Trigger it by saying *"council review this"* to Claude, or, on the plugin channel, run **`/amicus:council`** directly.
|
|
191
|
+
|
|
181
192
|
**Why multi-model.** Any single model — including the one running your session — has consistent blind spots. Route the *same* material through models from *different* families and the disagreements surface: missed issues, overstated confidence, claims one model alone would have waved through. The council is the structured version of that idea.
|
|
182
193
|
|
|
183
194
|
**The flow, in five beats:**
|
|
184
195
|
|
|
185
196
|
1. **Independent reviews.** Each council model reviews the artifact on its own (one parallel wave), producing a structured findings list — claim, severity (`blocker | major | minor | nit`), location, rationale.
|
|
186
|
-
2. **Anonymized cross-review.** Claude relabels every review (Review A, B, C…) and sends the identical bundle to every model. Each model ranks the reviews and adjudicates every finding (`agree | dispute | neutral`) — *unknowingly judging its own*, so self-bias washes out. This yields a **street-cred** ranking and sorts findings into **Confirmed / Contested / Singleton** tiers.
|
|
197
|
+
2. **Anonymized cross-review.** Claude relabels every review (Review A, B, C…) and sends the identical bundle to every model. Each model ranks the reviews and adjudicates every finding (`agree | dispute | neutral`) — *unknowingly judging its own*, so self-bias washes out. This yields a **street-cred** ranking and sorts findings into **Disputed / Confirmed / Contested / Singleton** tiers.
|
|
187
198
|
3. **Chair verdict.** A designated **non-Claude** chair receives the de-anonymized picture — all reviews, rankings, and adjudications — and synthesizes an independent verdict. Claude presents it verbatim; Claude does not synthesize.
|
|
188
199
|
4. **Tiered decisions.** Confirmed findings get one bulk accept/deny; Contested and Singleton findings are decided one at a time (accept / deny / modify).
|
|
189
200
|
5. **Outputs applied.** Accepted findings are written into a reviewed copy of the source; the full run is captured in the run folder.
|
|
@@ -194,6 +205,8 @@ Everything you need before your first run, and what's optional.
|
|
|
194
205
|
- `crossreview-matrix.md` — the adjudication grid plus the de-anonymized street-cred table.
|
|
195
206
|
- `verdict.md` — the chair's synthesis.
|
|
196
207
|
- `report.md` — synthesis + the full decision log + a per-call run-stats table.
|
|
208
|
+
- `report.html` — the deterministic renderer output (adjudication matrix, street-cred table,
|
|
209
|
+
findings-by-tier, cost — no chair prose). This is the default artifact handed to the user.
|
|
197
210
|
- For an **editable source**, the accepted edits land in `<stem>-reviewed.<ext>` next to the original.
|
|
198
211
|
|
|
199
212
|
**Claude in the council** (default off): you can add Claude's own fresh review to the bundle so the bench ranks and adjudicates it — Claude is *judged* but never votes or chairs, so the verdict stays independent.
|
|
@@ -204,7 +217,7 @@ Everything you need before your first run, and what's optional.
|
|
|
204
217
|
|
|
205
218
|
Then the council waits for your confirmation.
|
|
206
219
|
|
|
207
|
-
The skill lives at **[`skills/second-opinion/SKILL.md`](./skills/second-opinion/SKILL.md)**; the design spec behind it is **[`skills/second-opinion/COUNCIL-DESIGN.md`](./skills/second-opinion/COUNCIL-DESIGN.md)**.
|
|
220
|
+
The skill lives at **[`skills/second-opinion/SKILL.md`](./skills/second-opinion/SKILL.md)**; the design spec behind it is **[`skills/second-opinion/COUNCIL-DESIGN.md`](./skills/second-opinion/COUNCIL-DESIGN.md)**. For what `amicus council tally|verdict|report|stats` actually take as input and produce — field-by-field schemas, verdict.json's provenance, and a full worked example run against the real CLI — see **[docs/council.md](./docs/council.md)**.
|
|
208
221
|
|
|
209
222
|
**Free council (zero-cost).** Want the cross-examination without the model spend? `amicus setup` offers a **Free OpenRouter council** mode — readline wizard option 2, and the Electron **Models** step. It detects the free `:free` models live from the catalog, lets you multi-pick (Enter takes a vendor-diverse default), and saves them as `councils.free` — a first-class `councils` config primitive seeded under collision-safe `free-*` aliases. Your `config.default` is left untouched, and all you need is an `OPENROUTER_API_KEY`.
|
|
210
223
|
|
|
@@ -216,6 +229,8 @@ amicus fanout --council free --prompt "Review this design"
|
|
|
216
229
|
|
|
217
230
|
The `amicus_fanout` MCP tool takes the same `council` parameter, and the `second-opinion` skill reads `councils.free` automatically. A member that gets delisted is dropped with a warning — the council still runs as long as ≥2 survive. Free models are **rate-limited and quality-variable**, and some return 404 unless you enable data-sharing at [openrouter.ai/settings/privacy](https://openrouter.ai/settings/privacy).
|
|
218
231
|
|
|
232
|
+
**Council presets.** Save your own named member lists with `amicus council save <name> --models a,b,c` (≥2 resolvable aliases or `provider/model` IDs), then run them with `--council <name>` anywhere a council runs. `amicus council list` shows saved presets plus three built-in benches that work with no setup at all — `free` (the same zero-cost dynamic pick described above, used when you haven't seeded `councils.free`), `budget` (cheap workhorses, one per vendor family), and `frontier` (premium flagships, one per vendor family). `amicus council show <name>` resolves any of them (saved or built-in) and reports which members are currently usable. A saved council always shadows a built-in of the same name — exactly how the wizard's `councils.free` seeding already worked.
|
|
233
|
+
|
|
219
234
|
---
|
|
220
235
|
|
|
221
236
|
## The parallel window
|
|
@@ -266,8 +281,9 @@ amicus update
|
|
|
266
281
|
| `amicus status <id>` | One-shot status for a session or fan-out wave (human or `--json`; `--wave <id>` alternative spelling). |
|
|
267
282
|
| `amicus models` | List, search, refresh the catalog, or audit aliases. |
|
|
268
283
|
| `amicus doctor` | Diagnose your setup — keys, default model, catalog, aliases, OpenCode binary, Electron, skills, MCP registration, OpenRouter credit (`--json`; `--fix` self-heals what it can). |
|
|
284
|
+
| `amicus spend` | Cross-run cost rollup from the spend ledger — total + per-model spend, tokens, and source mix, most-expensive first (`--since 7d` windows it; `--json` for a versioned doc; shows remaining OpenRouter credit when a key is configured). |
|
|
269
285
|
| `amicus key` | Manage API keys non-interactively: `amicus key <provider> <key>` saves after live validation; `--remove`; bare `amicus key` lists providers. |
|
|
270
|
-
| `amicus council` | Council math: `tally <input.json>` (deterministic tiers + ledger append), `stats` (reviewer reliability), `report <verdict.json> [--md\|--html]
|
|
286
|
+
| `amicus council` | Council math: `tally <input.json>` (deterministic tiers + ledger append), `stats` (reviewer reliability), `report <verdict.json> [--md\|--html]`, `validate <file>` (findings-block check, exit 0/2/1), `verdict <tally.json> [--decisions <d.json>] [-o <out.json>]` (build + write verdict.json). Presets: `save <name> --models a,b,c`, `list [--json]`, `show <name> [--json]` — see [The Council](#the-council) for the built-in `free`/`budget`/`frontier` benches. |
|
|
271
287
|
| `amicus abort` | Abort a running session (or `--all`). |
|
|
272
288
|
| `amicus setup` | Configure default model, API keys, and aliases. |
|
|
273
289
|
| `amicus update` | Update to the latest version. |
|
|
@@ -275,85 +291,9 @@ amicus update
|
|
|
275
291
|
|
|
276
292
|
The `am` alias is interchangeable with `amicus` everywhere.
|
|
277
293
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
| Option | Description | Default |
|
|
281
|
-
|--------|-------------|---------|
|
|
282
|
-
| `--model <model>` | Alias, `provider/model`, or `openrouter/provider/model`. | config default |
|
|
283
|
-
| `--prompt <text>` | Task description. | *(required unless `--prompt-file`)* |
|
|
284
|
-
| `--prompt-file <path>` | Read the prompt from a UTF-8 file (XOR `--prompt`). | |
|
|
285
|
-
| `--agent <agent>` | OpenCode agent: `Chat`, `Build`, `Plan`. | `Chat` interactive / `Build` headless |
|
|
286
|
-
| `--no-ui` | Run headless (autonomous, no window). | off |
|
|
287
|
-
| `--json` | Emit the run result as stable JSON (requires `--no-ui`). | off |
|
|
288
|
-
| `--timeout <minutes>` | Headless timeout. | 15 |
|
|
289
|
-
| `--context-turns <N>` | Max conversation turns to include. | 50 |
|
|
290
|
-
| `--context-since <duration>` | Time filter (e.g. `2h`); overrides turns. | |
|
|
291
|
-
| `--context-max-tokens <N>` | Max context tokens. | 80000 |
|
|
292
|
-
| `--no-context` | Skip parent conversation history. | off |
|
|
293
|
-
| `--thinking <level>` | Reasoning effort: `none`, `minimal`, `low`, `medium`, `high`, `xhigh`. | model default |
|
|
294
|
-
| `--summary-length <length>` | Fold summary verbosity: `brief`, `normal`, `verbose`. | `normal` |
|
|
295
|
-
| `--mcp <spec>` | Add an MCP server (`name=url` or `name=command`). | |
|
|
296
|
-
| `--mcp-config <path>` | Path to an `opencode.json` with MCP config. | |
|
|
297
|
-
| `--no-mcp` | Don't inherit MCP servers from the parent. | off |
|
|
298
|
-
| `--exclude-mcp <name>` | Exclude a specific inherited MCP server (repeatable). | |
|
|
299
|
-
| `--session-id <id\|current>` | Session to pull context from. | `current` |
|
|
300
|
-
| `--cwd <path>` | Project directory. | cwd |
|
|
301
|
-
| `--client <type>` | Client context: `code-local`, `code-web`, `cowork`. | `code-local` |
|
|
302
|
-
| `--position <pos>` | Window position: `right`, `left`, `center`. | `right` |
|
|
303
|
-
| `--fold-shortcut <key>` | Customize the fold keyboard shortcut. | `Cmd/Ctrl+Shift+F` |
|
|
304
|
-
| `--opencode-port <port>` | Port override for the OpenCode server. | |
|
|
305
|
-
| `--session-dir <path>` | Explicit session-data directory. | |
|
|
306
|
-
| `--setup` | Force-open configuration before launching. Does **not** relax the `--prompt`/`--prompt-file` requirement — `start --setup` still fails fast with "Error: --prompt or --prompt-file is required" if neither is given. | |
|
|
307
|
-
| `--no-validate-model` | Skip model-catalog validation before launch. | validation on |
|
|
308
|
-
|
|
309
|
-
> Agents: **Chat** auto-approves reads and asks before writes/bash (interactive default); **Build** has full tool access (headless default); **Plan** is read-only analysis. `--agent Chat` is interactive-only and incompatible with `--no-ui`.
|
|
310
|
-
|
|
311
|
-
### `amicus fanout` — same prompt, many models
|
|
312
|
-
|
|
313
|
-
```bash
|
|
314
|
-
amicus fanout --models "gemini,deepseek,gpt" --prompt "Review this design" --json
|
|
315
|
-
```
|
|
316
|
-
|
|
317
|
-
Fanout runs one **headless wave**: every leg gets the **same** prompt (this is the shared-prompt model the council's review stages are built on). When all legs are terminal it prints **one** JSON wave document on stdout.
|
|
318
|
-
|
|
319
|
-
- `--models <a,b,c>` — comma-separated aliases or `provider/model` IDs (required, unless `--council`).
|
|
320
|
-
- `--council <name>` — run a saved council (e.g. `free`) instead of `--models`; mutually exclusive with `--models`.
|
|
321
|
-
- `--prompt <text>` / `--prompt-file <path>` — the shared briefing. `--prompt-file` avoids the ~32 KB Windows argument cap and is mutually exclusive with `--prompt`.
|
|
322
|
-
- `--wave-id <id>` — set the wave ID explicitly (leg IDs become `<id>-1..N`).
|
|
323
|
-
- `--json` — emit the wave document.
|
|
324
|
-
- `--session-id <id|current>` — session to pull shared context from (same as `start`; supported on `fanout` too).
|
|
325
|
-
- Shared per-leg knobs: `--agent`, `--thinking`, `--timeout`, `--summary-length`, `--no-context`, the `--context-*` flags, the `--mcp*` flags, `--no-validate-model`, `--cwd`.
|
|
326
|
-
- **Exit codes:** `0` all legs complete, `2` partial wave, `1` none complete / hard failure.
|
|
327
|
-
|
|
328
|
-
### Other commands
|
|
329
|
-
|
|
330
|
-
```bash
|
|
331
|
-
amicus list # current project
|
|
332
|
-
amicus list --status running # filter by status: running, complete, error,
|
|
333
|
-
# timed-out, aborted, crashed, idle-timeout
|
|
334
|
-
amicus list --all # all projects
|
|
335
|
-
amicus list --json # machine-readable
|
|
336
|
-
|
|
337
|
-
amicus read <id> # summary (default)
|
|
338
|
-
amicus read <id> --conversation # full conversation
|
|
339
|
-
amicus read <id> --metadata # session metadata
|
|
340
|
-
amicus read <id> --json # stable JSON (run or wave document)
|
|
341
|
-
|
|
342
|
-
amicus status <id> # one-shot status for a session or wave
|
|
343
|
-
amicus status --wave <id> # alternative spelling for a wave ID
|
|
344
|
-
amicus status <id> --json # machine-readable output
|
|
294
|
+
**Every flag, every subcommand, every example** — including the full `amicus start` option table, `amicus fanout` (supports `--session-id`, `--council <name>` as an alternative to `--models`), council presets, and every other command — lives in **[docs/usage.md](./docs/usage.md)**, the canonical CLI reference. What follows here is just enough to see the shape of a run.
|
|
345
295
|
|
|
346
|
-
amicus
|
|
347
|
-
amicus continue <id> --prompt "..." # new session, previous one as read-only context
|
|
348
|
-
|
|
349
|
-
amicus abort <id> # stop one running session
|
|
350
|
-
amicus abort --all # stop all running sessions in this project
|
|
351
|
-
|
|
352
|
-
amicus setup --api-keys # open just the API-key window
|
|
353
|
-
amicus setup --add-alias fast=openrouter/google/gemini-2.5-flash # add/override one alias
|
|
354
|
-
```
|
|
355
|
-
|
|
356
|
-
**`amicus status <id>` output.** Human-readable:
|
|
296
|
+
`amicus status <id>` output. Human-readable:
|
|
357
297
|
|
|
358
298
|
```
|
|
359
299
|
$ amicus status demo123
|
|
@@ -371,41 +311,26 @@ $ amicus status demo123 --json
|
|
|
371
311
|
"taskId": "demo123",
|
|
372
312
|
"status": "complete",
|
|
373
313
|
"elapsed": "5m 0s",
|
|
374
|
-
"version": "
|
|
314
|
+
"version": "2.0.0",
|
|
375
315
|
"model": "google/gemini-2.5-flash",
|
|
376
316
|
"phase": "terminal"
|
|
377
317
|
}
|
|
378
318
|
```
|
|
379
319
|
|
|
380
|
-
|
|
320
|
+
`amicus list --status` accepts `running`, `complete`, `error`, `timed-out`, `aborted`, `crashed`, `idle-timeout`. Full field-by-field docs (a running session's `messages`/`STALLED` reporting, wave-ID status shape, etc.) are in [docs/usage.md](./docs/usage.md).
|
|
381
321
|
|
|
382
322
|
---
|
|
383
323
|
|
|
384
324
|
## Models
|
|
385
325
|
|
|
386
|
-
Amicus does **not** ship a frozen table of model names. Aliases and validation resolve against a **live catalog** fetched from provider APIs and cached at `~/.config/amicus/model-catalog.json` (24-hour TTL; the fetch works without an API key).
|
|
326
|
+
Amicus does **not** ship a frozen table of model names. Aliases and validation resolve against a **live catalog** fetched from provider APIs and cached at `~/.config/amicus/model-catalog.json` (24-hour TTL; the fetch works without an API key). Run `amicus models` to see exactly what resolves on *your* machine — that's the source of truth, not this README.
|
|
387
327
|
|
|
388
328
|
```bash
|
|
389
329
|
amicus models # list the catalog
|
|
390
|
-
amicus models --search gemini # filter by substring
|
|
391
|
-
amicus models --refresh # force-refresh from provider APIs
|
|
392
|
-
amicus models --check # audit your aliases against the catalog
|
|
330
|
+
amicus models --search gemini # filter by substring
|
|
393
331
|
```
|
|
394
332
|
|
|
395
|
-
`
|
|
396
|
-
|
|
397
|
-
**Validation on launch.** `start` and `fanout` validate the model against the catalog before launching. For an explicit `--model` on `continue`/`resume` this is **blocking** (a typo'd model fails fast with suggestions); for a model *inherited* from a prior session it's **advisory**. Skip it any time with `--no-validate-model`, or fix the catalog with `amicus models --refresh`.
|
|
398
|
-
|
|
399
|
-
**Aliases are a curated seed, not a fixed list.** `amicus setup` seeds a curated set of short aliases (e.g. `gemini`, `gpt`, `opus`, `deepseek`), and you add or override them with `amicus setup --add-alias name=provider/model`. To see exactly what resolves on *your* machine, run `amicus models` — that is the source of truth, not this README.
|
|
400
|
-
|
|
401
|
-
**Full-id passthrough.** You can always bypass aliases and name a model directly. The prefix decides which credentials are used:
|
|
402
|
-
|
|
403
|
-
| Format | Example | Credentials |
|
|
404
|
-
|--------|---------|-------------|
|
|
405
|
-
| `openrouter/provider/model` | `openrouter/google/gemini-2.5-flash` | `OPENROUTER_API_KEY` |
|
|
406
|
-
| `google/model` | `google/gemini-2.5-flash` | `GOOGLE_GENERATIVE_AI_API_KEY` |
|
|
407
|
-
| `openai/model` | `openai/gpt-5` | `OPENAI_API_KEY` |
|
|
408
|
-
| `anthropic/model` | `anthropic/claude-opus-4` (the `opus` alias resolves here by default) | `ANTHROPIC_API_KEY` |
|
|
333
|
+
`start`/`fanout` validate your model against the catalog before launching (skip with `--no-validate-model`). You can also always bypass aliases and pass a full `provider/model` or `openrouter/provider/model` ID directly. Catalog internals, alias management, and the full-id passthrough table are in **[docs/usage.md § Models](./docs/usage.md#amicus-models--the-model-catalog)**.
|
|
409
334
|
|
|
410
335
|
---
|
|
411
336
|
|
|
@@ -430,68 +355,25 @@ The MCP server is auto-registered on install (Claude Code and Claude Desktop / C
|
|
|
430
355
|
| `amicus_council_stats` | Reviewer-reliability stats from past council runs. |
|
|
431
356
|
| `amicus_verdict` | Build the final council verdict from a tally + decisions. |
|
|
432
357
|
|
|
433
|
-
The async pattern is **start → status → read
|
|
358
|
+
The async pattern is **start → status → read** — `amicus_start`/`amicus_fanout` return immediately, then you poll `amicus_status` and call `amicus_read`; `amicus_wait` collapses that poll loop into one blocking call.
|
|
434
359
|
|
|
435
|
-
|
|
360
|
+
> Legacy `sidecar_*` tool names were removed entirely in v2.0.0 — only `amicus_*` tools exist now. `AMICUS_LEGACY_ALIASES=1` is a no-op left over from the v1.8.0 opt-in switch. See [docs/SHIMS.md](./docs/SHIMS.md).
|
|
436
361
|
|
|
437
|
-
|
|
438
|
-
claude mcp add-json amicus '{"command":"npx","args":["-y","amicus@latest","mcp"]}' --scope user
|
|
439
|
-
```
|
|
440
|
-
|
|
441
|
-
> Legacy `sidecar_*` tool names are no longer registered by default (v1.8.0). To restore them, add `"env": {"AMICUS_LEGACY_ALIASES": "1"}` to the server entry. They will be removed entirely in the next major.
|
|
362
|
+
Manual registration and per-tool detail are in **[docs/usage.md § MCP Server](./docs/usage.md#mcp-server)**.
|
|
442
363
|
|
|
443
364
|
---
|
|
444
365
|
|
|
445
366
|
## Configuration
|
|
446
367
|
|
|
447
|
-
`amicus setup` is the recommended way to configure Amicus — it writes API keys to `~/.config/amicus/.env` (`0600`) and persists your default model and aliases.
|
|
448
|
-
|
|
449
|
-
**API keys**
|
|
450
|
-
|
|
451
|
-
| Variable | Purpose |
|
|
452
|
-
|----------|---------|
|
|
453
|
-
| `OPENROUTER_API_KEY` | OpenRouter (multi-provider access). |
|
|
454
|
-
| `GOOGLE_GENERATIVE_AI_API_KEY` | Direct Google access. |
|
|
455
|
-
| `OPENAI_API_KEY` | Direct OpenAI access. |
|
|
456
|
-
| `ANTHROPIC_API_KEY` | Direct Anthropic access. |
|
|
457
|
-
| `DEEPSEEK_API_KEY` | Direct DeepSeek access. |
|
|
458
|
-
|
|
459
|
-
**Behavior**
|
|
460
|
-
|
|
461
|
-
| Variable | Purpose | Default |
|
|
462
|
-
|----------|---------|---------|
|
|
463
|
-
| `LOG_LEVEL` | Log verbosity: `error`, `warn`, `info`, `debug`. | `error` |
|
|
464
|
-
| `AMICUS_CONFIG_DIR` | Override the config directory (keys, catalog, sessions). | `~/.config/amicus` |
|
|
465
|
-
| `AMICUS_FANOUT_MAX_LEGS` | Cap the number of legs in a single fanout wave; non-positive values fall back to 10. | `10` |
|
|
466
|
-
| `AMICUS_SHARED_SERVER` | When `1`, multiple MCP sessions share a single OpenCode Go process, eliminating cold-start latency. Set to `0` for per-process isolation or to diagnose a crash loop. | `1` |
|
|
467
|
-
| `AMICUS_MCP_CLIENT` | Override the auto-detected MCP caller (`code-local`, `code-web`, or `cowork`). Amicus detects Claude Code vs. Claude Desktop/Cowork from the MCP `initialize` handshake; set this only if detection picks the wrong one. Note: `code-web` requires an explicit `--session-dir` and is not usable for MCP-spawned sessions. | auto-detected |
|
|
468
|
-
|
|
469
|
-
**Headless poller tuning** (advanced — rarely needed)
|
|
470
|
-
|
|
471
|
-
| Variable | Purpose | Default |
|
|
472
|
-
|----------|---------|---------|
|
|
473
|
-
| `AMICUS_POLL_INTERVAL_MS` | Delay between poll cycles. | `2000` |
|
|
474
|
-
| `AMICUS_POLL_CALL_TIMEOUT_MS` | Per-poll call timeout. | `30000` |
|
|
475
|
-
| `AMICUS_STABLE_FINISHED_POLLS` | Stable polls required after a completion signal. | `2` |
|
|
476
|
-
| `AMICUS_STABLE_IDLE_POLLS` | Stable polls required with no completion signal (~60 s at 2 s). | `30` |
|
|
477
|
-
| `AMICUS_MAX_CONSECUTIVE_POLL_FAILURES` | Consecutive poll failures before bailing. | `15` |
|
|
478
|
-
|
|
479
|
-
**GUI & debug**
|
|
480
|
-
|
|
481
|
-
| Variable | Purpose | Default |
|
|
482
|
-
|----------|---------|---------|
|
|
483
|
-
| `AMICUS_GUI_LOAD_TIMEOUT_MS` | Max wait for the Electron UI to load before showing what's in flight. | `15000` |
|
|
484
|
-
| `AMICUS_DEBUG_PORT` | Chrome DevTools Protocol port for the Electron window. | `9222` |
|
|
368
|
+
`amicus setup` is the recommended way to configure Amicus — it writes API keys to `~/.config/amicus/.env` (`0600`) and persists your default model and aliases. Every environment variable (API keys, behavior tuning, headless poller, GUI/debug, process lifecycle) is documented in **[docs/configuration.md](./docs/configuration.md)**. v2.0.0 removed the legacy `SIDECAR_*` → `AMICUS_*` env-var mapping entirely; see [docs/SHIMS.md](./docs/SHIMS.md) for the removal record and rename table.
|
|
485
369
|
|
|
486
|
-
|
|
370
|
+
**New to the disk footprint?** The config tree's file-by-file contents, session storage layout, where (and whether) logs are written, `config.json`'s exact shape, and full uninstall instructions all live in **[docs/configuration.md § Where things live](./docs/configuration.md#where-things-live)**.
|
|
487
371
|
|
|
488
372
|
---
|
|
489
373
|
|
|
490
374
|
## JSON output
|
|
491
375
|
|
|
492
|
-
With `--json`, Amicus emits stable, versioned documents on stdout — built for scripting and agent consumption
|
|
493
|
-
|
|
494
|
-
**Run document** (a single session — `start`, `read`, each fanout leg):
|
|
376
|
+
With `--json`, Amicus emits stable, versioned run/wave documents on stdout — built for scripting and agent consumption:
|
|
495
377
|
|
|
496
378
|
```json
|
|
497
379
|
{
|
|
@@ -501,22 +383,7 @@ With `--json`, Amicus emits stable, versioned documents on stdout — built for
|
|
|
501
383
|
}
|
|
502
384
|
```
|
|
503
385
|
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
**Wave document** (`fanout`, and `read <waveId> --json`):
|
|
507
|
-
|
|
508
|
-
```json
|
|
509
|
-
{
|
|
510
|
-
"schemaVersion": 1, "waveId": "...",
|
|
511
|
-
"status": "complete",
|
|
512
|
-
"counts": { "total": 0, "complete": 0, "error": 0, "timeout": 0, "aborted": 0 },
|
|
513
|
-
"legs": [ /* one run document per model, in --models order */ ]
|
|
514
|
-
}
|
|
515
|
-
```
|
|
516
|
-
|
|
517
|
-
`status` is `complete | partial | error | aborted`. A leg's `summary` is that model's full response.
|
|
518
|
-
|
|
519
|
-
**Exit codes** (for `--no-ui` / `fanout`): `0` success / all legs complete · `2` partial wave · `1` error, nothing completed, or hard failure · `130` interrupted (SIGINT) · `143` terminated (SIGTERM).
|
|
386
|
+
The wave-document shape (for `fanout`), field meanings, and the full exit-code table are in **[docs/usage.md § JSON Output](./docs/usage.md#json-output)**.
|
|
520
387
|
|
|
521
388
|
---
|
|
522
389
|
|
|
@@ -535,10 +402,12 @@ Most Claude-adjacent tooling assumes macOS/Linux; Amicus doesn't.
|
|
|
535
402
|
|
|
536
403
|
## Troubleshooting
|
|
537
404
|
|
|
405
|
+
Run `amicus doctor` first — it checks keys, catalog, OpenCode binary, Electron, skills, and MCP registration in one pass and prints a targeted fix for whatever's failing. For symptoms not covered below, or more diagnostic depth on any of these, see **[docs/troubleshooting.md](./docs/troubleshooting.md)**.
|
|
406
|
+
|
|
538
407
|
| Symptom | Likely cause | Fix |
|
|
539
408
|
|---------|--------------|-----|
|
|
540
409
|
| "council review this" does nothing | The `second-opinion` skill isn't installed | Check `~/.claude/skills/second-opinion/SKILL.md` exists; re-run `npm install -g amicus` (postinstall installs both skills) |
|
|
541
|
-
| `npm install -g amicus` fails with `EEXIST: … claude-sidecar` | The old upstream `claude-sidecar` package is still installed globally; npm won't overwrite another package's bin shims | `npm uninstall -g claude-sidecar`, then `npm install -g amicus`. Your
|
|
410
|
+
| `npm install -g amicus` fails with `EEXIST: … claude-sidecar` | The old upstream `claude-sidecar` package is still installed globally; npm won't overwrite another package's bin shims | `npm uninstall -g claude-sidecar`, then `npm install -g amicus`. Your keys and past sessions are not lost, but v2.0.0 no longer reads the old paths automatically — see [docs/SHIMS.md](./docs/SHIMS.md) for the one-time migration steps (rename `~/.config/sidecar/` and any `.claude/sidecar_sessions/` dirs). |
|
|
542
411
|
| Install fails partway, or `amicus doctor` reports the OpenCode binary "not found" | A **transient** error during the OpenCode engine's own postinstall (a spawn `ENOENT`, or an antivirus file-lock while it lays down its 11 per-platform binaries) can roll back the whole atomic install — retrying usually succeeds | Just re-run `npm install -g amicus`. If it still fails, clear the cache first: `npm cache clean --force && npm install -g amicus`. |
|
|
543
412
|
| `401` / auth error | API key missing, or the model prefix doesn't match the key you have | Run `amicus setup`; make sure the prefix (`openrouter/…` vs `google/…` vs `openai/…` vs `anthropic/…`) matches the credentials you configured. |
|
|
544
413
|
| `402` / "Payment Required" on first council review / `start` / `fanout` call | Your OpenRouter key is real but has no credit. Key save (`amicus key openrouter <key>` or the setup wizard's key step) only checks that the key **authenticates** — it doesn't check balance, so a zero-credit key saves cleanly and only fails later, on the first real model call. (The `amicus council` subcommand itself is deterministic math and never calls a model.) | Add credit at [openrouter.ai/credits](https://openrouter.ai/credits), **or** switch to a zero-cost council: `amicus setup` → option 2 (Free OpenRouter council) builds one from live `:free`-suffixed models and saves it as `councils.free` — then run `amicus fanout --council free …`. See "Free council (zero-cost)" under [The Council](#the-council) above. |
|
|
@@ -562,7 +431,8 @@ LOG_LEVEL=debug amicus start --model gemini --prompt "test" --no-ui
|
|
|
562
431
|
|
|
563
432
|
| Doc | Description |
|
|
564
433
|
|-----|-------------|
|
|
565
|
-
| [docs/usage.md](./docs/usage.md) |
|
|
434
|
+
| [docs/usage.md](./docs/usage.md) | The complete CLI & MCP reference — every flag, every subcommand, every example. |
|
|
435
|
+
| [docs/council.md](./docs/council.md) | Council pipeline reference: `tally`/`verdict`/`report` schemas, provenance, and a worked example. |
|
|
566
436
|
| [docs/configuration.md](./docs/configuration.md) | Full configuration and environment reference. |
|
|
567
437
|
| [docs/architecture.md](./docs/architecture.md) | How the engine, Electron shell, and context sharing fit together. |
|
|
568
438
|
| [docs/opencode-integration.md](./docs/opencode-integration.md) | How Amicus drives the OpenCode runtime. |
|
|
@@ -570,7 +440,7 @@ LOG_LEVEL=debug amicus start --model gemini --prompt "test" --no-ui
|
|
|
570
440
|
| [docs/electron-testing.md](./docs/electron-testing.md) | Chrome DevTools Protocol patterns for UI testing. |
|
|
571
441
|
| [docs/testing.md](./docs/testing.md) | Test suite layout and how to run it. |
|
|
572
442
|
| [docs/publishing.md](./docs/publishing.md) | Release and publish process. |
|
|
573
|
-
| [docs/SHIMS.md](./docs/SHIMS.md) |
|
|
443
|
+
| [docs/SHIMS.md](./docs/SHIMS.md) | v2.0.0 removal record for the pre-rebrand `sidecar*` compatibility shims — what was removed and how to migrate. |
|
|
574
444
|
| [skills/second-opinion/SKILL.md](./skills/second-opinion/SKILL.md) | The LLM Council skill. |
|
|
575
445
|
| [skills/sidecar/SKILL.md](./skills/sidecar/SKILL.md) | The `sidecar` chat skill. |
|
|
576
446
|
| [evals/README.md](./evals/README.md) | End-to-end eval harness for LLM interactions. |
|
package/bin/amicus.js
CHANGED
|
@@ -7,18 +7,7 @@
|
|
|
7
7
|
* Routes commands to appropriate handlers.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
//
|
|
11
|
-
// the canonical ~/.config/amicus (copy; legacy kept as a backup). Runs before
|
|
12
|
-
// any config/credential read so both resolve to the unified dir. Best-effort.
|
|
13
|
-
try {
|
|
14
|
-
const { migrateLegacyConfigDir } = require('../src/utils/config');
|
|
15
|
-
const _m = migrateLegacyConfigDir();
|
|
16
|
-
if (_m && _m.migrated) {
|
|
17
|
-
process.stderr.write(`[amicus] Migrated config ${_m.from} → ${_m.to} (legacy kept as a backup).\n`);
|
|
18
|
-
}
|
|
19
|
-
} catch { /* best-effort: never block startup on migration */ }
|
|
20
|
-
|
|
21
|
-
// Load API keys from all sources: process.env > sidecar .env > auth.json
|
|
10
|
+
// Load API keys from all sources: process.env > amicus .env > auth.json
|
|
22
11
|
const { loadCredentials } = require('../src/utils/env-loader');
|
|
23
12
|
loadCredentials();
|
|
24
13
|
|
|
@@ -123,6 +112,11 @@ async function main() {
|
|
|
123
112
|
exitCode = await handleDoctor(args);
|
|
124
113
|
break;
|
|
125
114
|
}
|
|
115
|
+
case 'spend': {
|
|
116
|
+
const { handleSpend } = require('../src/cli-handlers-spend');
|
|
117
|
+
exitCode = await handleSpend(args);
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
126
120
|
case 'setup':
|
|
127
121
|
await handleSetup(args);
|
|
128
122
|
break;
|
|
@@ -162,9 +156,9 @@ async function main() {
|
|
|
162
156
|
* Spec Reference: §4.2
|
|
163
157
|
*/
|
|
164
158
|
async function handleList(args) {
|
|
165
|
-
const {
|
|
159
|
+
const { listAmicus } = require('../src/index');
|
|
166
160
|
|
|
167
|
-
await
|
|
161
|
+
await listAmicus({
|
|
168
162
|
status: args.status,
|
|
169
163
|
all: args.all,
|
|
170
164
|
json: args.json,
|
|
@@ -181,7 +175,7 @@ async function handleResume(args) {
|
|
|
181
175
|
|
|
182
176
|
if (!taskId) {
|
|
183
177
|
console.error('Error: task_id is required for resume');
|
|
184
|
-
console.error('Usage:
|
|
178
|
+
console.error('Usage: amicus resume <task_id>');
|
|
185
179
|
process.exit(1);
|
|
186
180
|
}
|
|
187
181
|
|
|
@@ -191,9 +185,9 @@ async function handleResume(args) {
|
|
|
191
185
|
process.exit(1);
|
|
192
186
|
}
|
|
193
187
|
|
|
194
|
-
const {
|
|
188
|
+
const { resumeAmicus } = require('../src/index');
|
|
195
189
|
|
|
196
|
-
return await
|
|
190
|
+
return await resumeAmicus({
|
|
197
191
|
taskId,
|
|
198
192
|
project: args.cwd,
|
|
199
193
|
headless: args['no-ui'],
|
|
@@ -210,7 +204,7 @@ async function handleContinue(args) {
|
|
|
210
204
|
|
|
211
205
|
if (!taskId) {
|
|
212
206
|
console.error('Error: task_id is required for continue');
|
|
213
|
-
console.error('Usage:
|
|
207
|
+
console.error('Usage: amicus continue <task_id> --prompt "..."');
|
|
214
208
|
process.exit(1);
|
|
215
209
|
}
|
|
216
210
|
|
|
@@ -245,9 +239,9 @@ async function handleContinue(args) {
|
|
|
245
239
|
args.model = await validateFallbackModel(args, alias);
|
|
246
240
|
}
|
|
247
241
|
|
|
248
|
-
const {
|
|
242
|
+
const { continueAmicus } = require('../src/index');
|
|
249
243
|
|
|
250
|
-
return await
|
|
244
|
+
return await continueAmicus({
|
|
251
245
|
taskId,
|
|
252
246
|
newTaskId: args['task-id'],
|
|
253
247
|
briefing: args.prompt || args.briefing,
|
package/commands/council.md
CHANGED
|
@@ -19,4 +19,6 @@ don't re-ask for what is already present).
|
|
|
19
19
|
|
|
20
20
|
Then follow the second-opinion skill end to end: Stage 0 intake/prep and run-folder
|
|
21
21
|
setup, council selection with a cost estimate and explicit user confirmation, the
|
|
22
|
-
three review waves, `amicus council
|
|
22
|
+
three review waves, `amicus council validate` on each leg's findings block,
|
|
23
|
+
`amicus council tally`, the accept/deny decision pass, and `amicus council verdict`
|
|
24
|
+
to write the final `verdict.json`.
|