@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.
- package/README.md +26 -262
- package/dist/index.js +1753 -696
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,295 +1,59 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Sechroom CLI
|
|
2
2
|
|
|
3
|
-
|
|
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
|
-
#
|
|
50
|
-
|
|
51
|
-
npm i -g @sechroom/cli@next
|
|
8
|
+
# Install globally
|
|
9
|
+
npm i -g @sechroom/cli
|
|
52
10
|
|
|
53
|
-
#
|
|
54
|
-
npx @sechroom/cli
|
|
11
|
+
# Run without installing
|
|
12
|
+
npx @sechroom/cli
|
|
55
13
|
```
|
|
56
14
|
|
|
57
|
-
|
|
15
|
+
Node.js 20 or later is required.
|
|
58
16
|
|
|
59
|
-
|
|
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
|
-
|
|
19
|
+
For guided setup, run:
|
|
70
20
|
|
|
71
21
|
```bash
|
|
72
|
-
|
|
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
|
-
|
|
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
|
|
89
|
-
sechroom config set tenant
|
|
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
|
-
##
|
|
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
|
|
143
|
-
sechroom
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|