@sechroom/cli 2026.7.32 → 2026.8.1

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.
Files changed (3) hide show
  1. package/README.md +26 -262
  2. package/dist/index.js +1753 -696
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -1,295 +1,59 @@
1
- # sechroom-cli (Route 1 skeleton)
1
+ # Sechroom CLI
2
2
 
3
- A thin **npm-distributed** CLI over the Sechroom HTTP API. A deliberate
4
- alternative agent/human surface to MCP — and because the agentic coding tools
5
- (Claude Code, Codex, Cursor) drive CLIs by reading `--help` and parsing stdout,
6
- every command emits clean JSON via `--json`.
7
-
8
- ## Why this shape (grounded in the backend, verified against source)
9
-
10
- - **One contract.** OpenAPI is served at `/openapi/v1.json` (`Program.cs`:
11
- `AddOpenApi()` + `MapOpenApi()`) — the same doc the UI's
12
- `frontend/packages/api-client` and Bruno consume. The CLI generates its
13
- client from it; there is no hand-maintained request/response surface.
14
- - **The API is the real surface.** Every MCP tool is a thin shim over a
15
- Wolverine handler that is _also_ a `[WolverinePost]`/`[WolverineGet]` endpoint
16
- carrying the same `[TenantPermission]`. The permission middleware is HTTP-only,
17
- so the CLI inherits identical enforcement.
18
- - **Tenant is mandatory.** `MapWolverineEndpoints` calls `TenantId.AssertExists()`
19
- — a missing `tenant` header is a hard 400. The client sets it on every request.
20
- - **Auth matches the AS.** `OAuthEndpointMappings.cs` exposes auth-code + PKCE
21
- (`/oauth/authorize` -> `/oauth/token`), RFC 8414 discovery, and RFC 7591
22
- dynamic client registration (`/oauth/register`). No device-code or
23
- client-credentials grant — so the CLI uses the loopback auth-code + PKCE
24
- pattern and self-registers via DCR, mirroring how Claude.ai web connects.
25
- Headless/CI sets `SECHROOM_TOKEN`.
26
-
27
- ### Verified specifics that shaped the code
28
-
29
- - **DCR `client_id` is deterministic** (`RegisterClientEndpoint.cs`):
30
- `dyn-` + base64url(SHA256(sorted `redirect_uris`))[:22], idempotent on the
31
- redirect set. PKCE-only, no secret. The CLI therefore registers a **fixed set
32
- of candidate loopback ports** as the redirect_uris (stable set -> stable id)
33
- and binds whichever is free — so re-login never mints a new client or stales
34
- the cache.
35
- - **PKCE is S256-only** (`TokenEndpoint.VerifyPkce`).
36
- - **Refresh works** (`TokenEndpoint`): `grant_type=refresh_token` is a real
37
- grant, and the token body returns a `refresh_token` for non-browser clients.
38
- `requireToken()` refreshes automatically near expiry.
39
- - **`POST /memories`** binds `CreateMemoryInput` — `Content` and `Confidence`
40
- are required (MCP shim defaults `"{}"` / `1.0`); `Owner` is nullable (omit for
41
- Unfiled). The `create` command applies those defaults.
42
- - **`GET /memories/{memoryId}`** returns an `OperationsItem<MemoryReadModel>` envelope.
43
- - **`POST /memories/search`** (`SearchMemoriesEndpoint`) — `SemanticQuery`
44
- routes to the hybrid vector+FTS RRF ranker; the `search` command uses it.
3
+ The Sechroom CLI lets you sign in, wire your AI tools, and work with your sechroom from the terminal. Every command supports `--json` for scripts and agent workflows.
45
4
 
46
5
  ## Install
47
6
 
48
7
  ```bash
49
- # pre-GA / internal builds are published under the `next` dist-tag
50
- npx @sechroom/cli@next login
51
- npm i -g @sechroom/cli@next
8
+ # Install globally
9
+ npm i -g @sechroom/cli
52
10
 
53
- # once GA (promoted to `latest`)
54
- npx @sechroom/cli login
11
+ # Run without installing
12
+ npx @sechroom/cli
55
13
  ```
56
14
 
57
- ## Develop
15
+ Node.js 20 or later is required.
58
16
 
59
- This is a **pnpm workspace member** (`frontend/apps/cli`). Install from the repo root
60
- (`pnpm install`), then run scripts via the filter (or `pnpm <script>` from this dir):
61
-
62
- ```bash
63
- pnpm --filter @sechroom/cli run gen # regenerate the typed client
64
- pnpm --filter @sechroom/cli run check-types
65
- pnpm --filter @sechroom/cli run build
66
- pnpm --filter @sechroom/cli run dev -- --help # tsx, no build
67
- ```
17
+ ## Get started
68
18
 
69
- ## Generate the client (once, and after any API change)
19
+ For guided setup, run:
70
20
 
71
21
  ```bash
72
- # defaults to https://app.sechroom.ai/api/openapi/v1.json
73
- pnpm --filter @sechroom/cli run gen
74
- SECHROOM_OPENAPI_URL=https://<host>/api/openapi/v1.json pnpm --filter @sechroom/cli run gen # other envs
22
+ sechroom onboard
75
23
  ```
76
24
 
77
- `gen` overwrites `src/generated/api.d.ts`. The **real generated types are
78
- committed** (regenerated from the live prod spec) so builds are hermetic — no
79
- live-API dependency at compile time; re-run `gen` after any API change. Generating
80
- against the live schema is what caught the original placeholder's shape drift
81
- (e.g. the work-log append body is `{bullet, laneId, workspaceId, title}`, and
82
- `CreateMemoryInput`/`SearchInput` require several nullable fields present), now
83
- fixed in the command bodies.
84
-
85
- ## Use
25
+ To configure the CLI manually:
86
26
 
87
27
  ```bash
88
- sechroom config set baseUrl https://app.sechroom.ai/api # prod (staging: https://staging.app.sechroom.ai/api)
89
- sechroom config set tenant ocd
28
+ sechroom config set baseUrl https://app.sechroom.ai/api
29
+ sechroom config set tenant <your-tenant>
90
30
  sechroom login
91
-
92
- sechroom memory create --text "first note from the CLI" --type reference
93
- sechroom memory get mem_XXXX
94
- sechroom memory search "convention lifecycle drift" --limit 5
95
- sechroom worklog append --text "shipped CLI skeleton; pointers: ..." --source claude-code-chris
96
-
97
- sechroom lookup mem_XXXX # what is this id? -> kind / title / view URL
98
- sechroom lookup sechroom:mem_XXXX --json # namespaced form also resolves
99
-
100
- sechroom --json memory get mem_XXXX # agent-friendly
101
- ```
102
-
103
- **Output shape.** Mutating commands (`memory create`, `worklog append`) print a concise confirmation line — id + view URL — the way the MCP tools hand an LLM a result, instead of dumping the raw envelope. Pass `--json` for the full response body (the machine channel) on any command. Output is lightly colorized on a TTY and auto-plain when piped, under `--json`, or when `NO_COLOR` is set.
104
-
105
- ```bash
106
- sechroom memory create --text "a note" --title "Note"
107
- # ✓ created memory mem_XXXX "Note" → https://sechroom.yi.ocd.codes/view/mem_XXXX
108
- ```
109
-
110
- **Per-directory config.** A project dir can pin its own `tenant` + `baseUrl` in a local `.sechroom.json`, discovered by walking **up** from cwd (nearest wins, so any subdir inherits it). It overrides the global config — precedence: `--flag` > env > directory-local > global > default. `clientId` / auth state stays global.
111
-
112
- ```bash
113
- sechroom config set --local tenant cli-smoke # this dir + subdirs
114
- sechroom config set --local baseUrl https://staging.app.sechroom.ai/api
115
- sechroom config show # resolved values + which source won
116
- ```
117
-
118
- **Smoke testing.** There is a dedicated **`cli-smoke`** tenant on **both staging and prod** for exercising the CLI without touching real tenants — point at staging and use it:
119
-
120
- ```bash
121
- sechroom config set --local baseUrl https://staging.app.sechroom.ai/api
122
- sechroom config set --local tenant cli-smoke
123
- sechroom login
124
- sechroom worklog append --text "cli smoke" --source claude-code-chris
125
- ```
126
-
127
- Headless:
128
-
129
- ```bash
130
- export SECHROOM_TOKEN="<bearer: a PAT or dev-token JWT>"
131
- export SECHROOM_TENANT=ocd
132
- sechroom --json memory search "rate limiting"
133
31
  ```
134
32
 
135
- ## Executor channel migration
136
-
137
- `sechroom channel` now consumes the generic executor advertisement and claims a
138
- durable exact-instance offer before forwarding work. Configure the checkout once,
139
- then install the channel entry:
33
+ ## Everyday commands
140
34
 
141
35
  ```bash
142
- sechroom executor install --connector <approved-connector-id>
143
- sechroom channel install
36
+ sechroom memory create --text "Project kickoff notes" --title "Project kickoff"
37
+ sechroom memory get mem_XXXX
38
+ sechroom memory search "project decisions" --limit 5
39
+ sechroom lookup mem_XXXX
40
+ sechroom worklog append --text "Prepared the release notes" --source terminal
144
41
  ```
145
42
 
146
- The former `channel --workspace ... --tag ...` shape is retired. Those options are
147
- accepted for one compatibility release and print a deprecation warning, but they
148
- no longer participate in eligibility or reconnect recovery. Running `channel
149
- install` rewrites the managed `.mcp.json` entry without them. Workspace authority,
150
- capabilities, runtime profiles, instance identity, and lane affinity now come from
151
- the installed executor state plus server-side persona/connector resolution.
152
-
153
- Reconnect recovery reads durable offers for the exact executor instance; it no
154
- longer queries a workspace memory feed. Existing unmanaged channel entries should
155
- remove `--workspace`, `--tag`, and `--executor-instance` after the executor harness
156
- has been installed.
157
-
158
- ## Command surface (MCP parity)
159
-
160
- The CLI mirrors the sechroom MCP tool surface — every command is a thin wrapper over the same HTTP endpoint the matching MCP tool shims, so enforcement (`[TenantPermission]`) is identical. Run `sechroom <group> --help` for the subcommands + examples.
161
-
162
- | Group | Covers |
163
- | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
164
- | `memory` | create / get / search · edit-text(+batch) · archive / restore / move · versions / revert · list-archived · owners / tags / types · sum-tokens · similar · by-url |
165
- | `relationship` | create / list / delete · suggest · `suggestion` get / accept / reject / defer |
166
- | `workspace` | create / list / get · rename / describe / move · archive / restore · feed |
167
- | `project` | create / list / get · rename / describe / move · status · victory-conditions · archive / restore |
168
- | `filing` | suggestions / get · preview · accept / reject / defer / edit-and-accept |
169
- | `continuity` | snapshot-create / -get · snapshots · resume-me / resume-lane · changed-since · load-set · grant / revoke-grant |
170
- | `id` | next / peek (FR-_/D-_ sequence allocation) |
171
- | `account` | profile / set-profile · feed · reviews / review-get / review-accept · lookup-batch |
172
- | `chat` | send · messages · replies · stop-tracking (Slack / Discord, via `--surface`) |
173
- | `worklog` · `lookup` | append · resolve any id |
174
-
175
- Notes on deliberate gaps (API-rooted, not CLI):
176
-
177
- - **No `memory delete`** — the API exposes no hard DELETE; `memory archive` is the soft-delete path.
178
- - **`memory revert`** needs `--text` + `--content` — the revert endpoint doesn't reconstruct a version's body from its number; pull them from `memory versions` / `memory get` first.
179
-
180
- ## Onboarding (`init` / `setup`)
181
-
182
- `sechroom init` wires a project for sechroom by rendering the server's
183
- operator-surface setup descriptors (`GET /operator-surface/setup`, tenant-scoped
184
- — the aggregator URL is baked in) into local AI-client config + agent instruction
185
- files. **Idempotent — merges/appends, never clobbers** (JSON `mcpServers` merge;
186
- Codex TOML table replace; instruction files use a managed marker block).
43
+ Add `--json` when you need machine-readable output:
187
44
 
188
45
  ```bash
189
- sechroom init # Claude Code (default): .mcp.json + CLAUDE.md
190
- sechroom init --client all # claude-code, claude-desktop, codex, cursor
191
- sechroom init --client codex,cursor # a subset
192
- sechroom init --mcp-only # just the MCP config (skip agent files)
193
- sechroom init --dry-run --json # preview the writes, no changes
194
-
195
- # granular pieces init orchestrates:
196
- sechroom setup mcp claude-desktop # just the MCP config for one client
197
- sechroom setup agent-files codex # just the AGENTS.md instruction file
46
+ sechroom --json memory search "project decisions"
198
47
  ```
199
48
 
200
- ### `sechroom onboard` — guided first run
201
-
202
- `onboard` orchestrates the whole zero-to-wired path interactively: configure base
203
- URL + tenant, sign in, set the profile timezone, then wire your AI client(s). Two
204
- prompts make it fit how you actually work:
49
+ ## Headless use
205
50
 
206
- - **Where to save config** globally (`~/.config/sechroom`, all projects) or a
207
- directory-local `.sechroom.json` (this project + subdirs). Defaults to local
208
- when a `.sechroom.json` already governs the dir.
209
- - **How far to wire** — full (MCP server + agent instructions), agent
210
- instructions only (skip `.mcp.json`), or **CLI only** (write nothing for AI
211
- clients — for when you just want the `sechroom` command).
51
+ Set a bearer token and tenant in the environment when browser login isn't available:
212
52
 
213
53
  ```bash
214
- sechroom onboard # interactive: asks where to save + how to wire
215
- sechroom onboard --cli-only # just the CLI — no .mcp.json, no agent files
216
- sechroom onboard --no-mcp # agent instructions only, skip MCP config
217
- sechroom onboard --local # save tenant + base URL to ./.sechroom.json
218
- sechroom onboard --yes # non-interactive: defaults + global config + full wire
54
+ SECHROOM_TOKEN=<bearer-token> SECHROOM_TENANT=<your-tenant> sechroom --json memory search "project decisions"
219
55
  ```
220
56
 
221
- Per client → where it writes:
222
-
223
- | client | MCP config | instruction file |
224
- | ---------------- | -------------------------------------- | --------------------- |
225
- | `claude-code` | `./.mcp.json` | `./CLAUDE.md` |
226
- | `claude-desktop` | `claude_desktop_config.json` (OS path) | `~/.claude/CLAUDE.md` |
227
- | `codex` | `~/.codex/config.toml` | `./AGENTS.md` |
228
- | `cursor` | `./.cursor/mcp.json` | `./AGENTS.md` |
229
-
230
- The instruction-file step pulls the role template the SEM Starter bundle ships
231
- (via the descriptor's tag-query artifact). If that bundle isn't installed in the
232
- tenant, the step **skips gracefully** with a note (MCP config still gets written).
233
-
234
- ## Layout
235
-
236
- ```
237
- src/
238
- index.ts commander root + global flags + login/config
239
- auth.ts OAuth auth-code+PKCE loopback (fixed-port DCR) + refresh + cache
240
- client.ts openapi-fetch client (auth + tenant middleware) + emit/fail
241
- config.ts base-url / tenant / token resolution + persistence
242
- generated/api.d.ts typed client — `pnpm run gen`; real types committed (hermetic)
243
- commands/
244
- memory.ts create / get / search / edit / archive / move / versions / …
245
- relationships.ts relationships + relationship-suggestions
246
- workspace.ts workspace CRUD + feed
247
- project.ts project CRUD + status / victory-conditions
248
- filing.ts filing-suggestion review (accept / reject / defer / edit-and-accept)
249
- continuity.ts snapshots + resume / grant
250
- account.ts id next/peek + profile / feed / reviews / lookup-batch
251
- chat.ts read Slack / Discord messages + replies
252
- worklog.ts append
253
- lookup.ts resolve any id (mem_…/unprefixed/sechroom:<id>) -> kind/title/url
254
- setup.ts init + setup mcp/agent-files
255
- setup/
256
- operator-surface.ts fetch GET /operator-surface/setup + resolve template artifacts
257
- clients.ts client→(surface, local paths, format) registry
258
- apply.ts writers: mcp json merge / codex toml / instruction marker block
259
- ```
260
-
261
- ## Remaining before ship
262
-
263
- - **Provision the npm publish credential** (the only blocker): create the
264
- `@sechroom` npmjs org + an Automation token and paste it into the
265
- `Sechroom_PublishCli` build config's `NPM_TOKEN` param. See
266
- [`ci/PUBLISHING.md`](./ci/PUBLISHING.md).
267
- - Decide the registered candidate-port set (`CANDIDATE_PORTS` in `auth.ts`) —
268
- three localhost ports today; keep them stable, since the DCR client id is a
269
- function of that set.
270
-
271
- ## Distribution (initial)
272
-
273
- Public **npmjs** under the `@sechroom` org is the host; **TeamCity** is the
274
- publisher (build config `Sechroom_PublishCli`). The full pipeline — steps,
275
- parameters, npm auth, provisioning, and how to run a publish — is documented in
276
- [`ci/PUBLISHING.md`](./ci/PUBLISHING.md). In short: a manual-trigger config runs
277
- `pnpm install → gen → check-types → build → publish` (filtered to `@sechroom/cli`)
278
- in a `node:20` container, authed by a masked `NPM_TOKEN` param. Every publish gets a
279
- fresh calendar version `YYYY.M.<n>` (own counter); the dist-tag separates next/latest.
280
-
281
- Why public npmjs: the CLI is customer-facing, and `npx @sechroom/cli` must work
282
- with zero `.npmrc`/token on the customer side. GitHub Packages or a private
283
- registry would force every external adopter to authenticate just to install.
284
-
285
- Pure Node — no runtime prerequisite beyond Node 20. If a zero-dependency single
286
- binary is later preferred, the alternative is per-platform AOT binaries published
287
- as npm `optionalDependencies` behind a launcher shim (the esbuild/biome pattern),
288
- at the cost of an OS×arch build matrix. This (plain Node) keeps install friction
289
- lowest.
290
-
291
- ## Onboarding hook
57
+ ## More commands
292
58
 
293
- Parallels `BuildMcpConfigSection` in `OperatorSurfaceDescriptors`: a
294
- `BuildCliConfigSection` can emit the `npx @sechroom/cli` invocation + the
295
- `config set` bootstrap the same way the MCP config is surfaced today.
59
+ Run `sechroom --help` for the full command list, or `sechroom <group> --help` for group-specific options and examples.