@elmundi/ship-cli 0.12.2 → 0.14.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/README.md CHANGED
@@ -1,717 +1,134 @@
1
1
  # @elmundi/ship-cli
2
2
 
3
- `shipctl` is the command-line interface to **Ship**. Three jobs:
4
-
5
- 1. **Bootstrap a repo** so its agents (Cursor, Codex, Claude, Aider, Cline,
6
- Continue, Windsurf, Zed, Gemini, OpenCode, Copilot, …) can consume Ship
7
- artifacts the same way every other client does.
8
- 2. **Sync the catalog** of `pattern` / `tool` / `collection` artifacts into
9
- `.ship/cache/` and pin versions for reproducible runs.
10
- 3. **Run lanes** (one-shot dispatch + GitHub Actions wrappers) and
11
- **report Runs** so the operator console can render outcomes and route any
12
- escalations into the Inbox.
13
-
14
- Published as **`@elmundi/ship-cli`** under the [elmundi](https://www.npmjs.com/org/elmundi) org; the binary name is **`shipctl`**.
15
-
16
- > **Vocabulary.** The CLI speaks the protocol layer, the operator console
17
- > speaks the product layer. Both are correct; they refer to the same things.
18
- >
19
- > | CLI / YAML / API (literal) | Operator console (prose) |
20
- > |----------------------------|--------------------------|
21
- > | `lanes:` entries in `.ship/config.yml`, `--lane <id>` | **Automations** |
22
- > | `pattern:` artifacts (RFC-0001) | **Plays** |
23
- > | `pipeline_runs` rows + `shipctl callback` payloads | **Runs** |
24
- > | clarifications / improvements / approvals queue | **Inbox** items |
25
- >
26
- > The CLI keeps `lanes:` / `pattern:` / `--lane` literal forever; we are
27
- > never going to break the YAML and flag surface. Help text and prose
28
- > reach for the operator nouns when describing what users see.
3
+ `shipctl` is the developer workbench for Ship. Product owners should start in the console and docs; use the CLI when you need local repo setup, config validation, artifact sync, agent rule installation, or reproducible diagnostics.
4
+
5
+ Published package: `@elmundi/ship-cli`. Binary: `shipctl`.
29
6
 
30
7
  ## Requirements
31
8
 
32
- - **Node.js 20+**
9
+ - Node.js 20+
33
10
 
34
11
  ## Install
35
12
 
36
13
  ```bash
37
14
  npm install -g @elmundi/ship-cli
38
- # or one-off:
15
+ # or one-off
39
16
  npx @elmundi/ship-cli help
40
17
  ```
41
18
 
42
- ## Bring Ship into your project (main path)
19
+ ## When to use the CLI
43
20
 
44
- You **do not** need the Ship monorepo cloned for day-to-day use. Work in **your product repo** and wire agents to the same artifacts protocol the CLI uses.
21
+ Use `shipctl` to:
45
22
 
46
- ### 1. Pick the API URL
23
+ - create or validate `.ship/config.yml`;
24
+ - install versioned agent rules into files such as `AGENTS.md`, `CLAUDE.md`, or `.cursor/rules/*.mdc`;
25
+ - sync patterns, tools, and collections into `.ship/cache/`;
26
+ - verify local repo wiring in CI or before a PR;
27
+ - inspect detected stack signals with `doctor`;
28
+ - fetch catalog or docs content for agents;
29
+ - draft and submit feedback on artifacts;
30
+ - run technical routines where the repo-level workflow requires it.
47
31
 
48
- - **`SHIP_API_BASE`** env var the CLI and injected snippets use (no trailing slash).
49
- - Or pass **`--base-url`** on each command.
50
- - Default matches other Ship tooling (public host unless you override for local FastAPI).
32
+ Do not use the CLI as the main product onboarding story. The product setup path is workspace → repo → tracker → knowledge → dashboard/Inbox.
51
33
 
52
- ### 2. Preview what `shipctl init` will change
34
+ ## First local setup
53
35
 
54
- From the **root of the repo** you want agents to use:
36
+ Preview before writing:
55
37
 
56
38
  ```bash
57
- cd /path/to/your-product
58
39
  npx @elmundi/ship-cli init --dry-run
59
40
  ```
60
41
 
61
- `shipctl init` **detects what is already in the tree** and only plans injections for those stacks:
62
-
63
- | If the repo has… | `shipctl init` can add… |
64
- |------------------|-------------------------|
65
- | `.cursor/` | Cursor rule **`.cursor/rules/ship-artifacts-protocol.mdc`** |
66
- | **`AGENTS.md`** | Appended section (Codex-style / generic agents file) |
67
- | **`CLAUDE.md`** | Appended section |
68
- | **`.codex/`** | **`SHIP_API.md`** under `.codex/` |
69
- | **`.github/copilot-instructions.md`** | Appended section |
70
- | **`.aider.conf.yml`** / `AIDER.md` | **`AIDER.md`** section |
71
- | **`.clinerules`** / `.rooignore` | **`.clinerules`** section |
72
- | **`.continue/`** | **`.continue/ship.md`** side-file |
73
- | **`.windsurfrules`** | **`.windsurfrules`** section |
74
- | **`.zed/`** | **`.zed/ship.md`** |
75
- | **`GEMINI.md`** / `.gemini/` | **`GEMINI.md`** section |
76
- | **`.opencode/`** | **`.opencode/ship.md`** |
77
- | **`.cursor/environments.json`** | Marker-guarded update to existing file |
78
-
79
- If **none** of the above exist, init offers a **standalone** **`SHIP_AGENT_API.md`** in the repo root so humans can copy the contract into whatever system you use later.
80
-
81
- Use **`--agents <csv>`** to limit targets and **`--cwd <dir>`** to point at another root. Example:
82
-
83
- ```bash
84
- npx @elmundi/ship-cli init --agents cursor,codex,claude --dry-run
85
- ```
86
-
87
- ### 3. Stack hints
88
-
89
- `init` also accepts `--tracker`, `--ci`, `--preset` (per RFC-0002 stack block). For now they land in the plan payload and are echoed back; a future release writes them into `.ship/config.yml` and triggers the bootstrap adapters (RFC-0004).
42
+ Apply only after the preview looks right:
90
43
 
91
44
  ```bash
92
45
  npx @elmundi/ship-cli init --yes \
93
- --agents cursor,codex --tracker linear --ci gh-actions --preset web-app
94
- ```
95
-
96
- ### 4. Apply with confirmation (recommended)
97
-
98
- Interactive run prints the plan and asks **Apply these changes? [y/N]**:
99
-
100
- ```bash
101
- npx @elmundi/ship-cli init
102
- ```
103
-
104
- After you confirm **`y`**, it writes/updates the files above. Injected content tells agents to **resolve Ship artifacts before use** via the CLI: **search → fetch → record `kind:id@version`** workflow, **`shipctl docs fetch`** for documentation paths, **`shipctl pattern|tool|collection`** for catalog bodies, and **`shipctl docs feedback`** for safe retro notes.
105
-
106
- ### 5. Non-interactive (CI or scripts)
107
-
108
- Only after you are happy with **`--dry-run`**:
109
-
110
- ```bash
111
- npx @elmundi/ship-cli init --yes
112
- ```
113
-
114
- **`--force`** replaces blocks that were already injected (same marker). Without **`--force`**, existing injections are skipped.
115
-
116
- ## Init flow
117
-
118
- `shipctl init` is the primary adoption entrypoint. It composes four steps in one
119
- command:
120
-
121
- 1. **Config** — creates `.ship/config.yml` (via `DEFAULT_CONFIG`), seeds an
122
- anonymous telemetry id, writes `.ship/state.json`, and appends
123
- `.ship/cache/` to `.gitignore`. Existing configs are respected and only
124
- updated with the flags/doctor proposal.
125
- 2. **Telemetry** — prompts once for opt-in (default **OFF**). Non-TTY runs and
126
- `--yes` default to OFF. `--telemetry on|off|ask` overrides the prompt.
127
- 3. **Doctor (no network)** — runs the adapter detect-layer to propose
128
- `tracker / ci / agents / language` values for gaps the user didn't set
129
- explicitly via flags. Detection never overrides explicit flags.
130
- 4. **Sync** — calls `syncArtifacts()` to pull the derived collection artifacts
131
- (`collection/agent-rules-<agent>`, `collection/preset-<preset>`, optionally
132
- `collection/adoption-playbook`) into `.ship/cache/`.
133
-
134
- Optional post-steps:
135
-
136
- - **`--copy-rules`** — for every agent in `stack.agents`, reads the cached
137
- `agent-rules-<agent>` artifact, extracts `install_target` + `marker` from the
138
- front-matter, and writes (or upserts) the rules file at the target path.
139
- A `<!-- ship-cli: installed-from collection/agent-rules-<agent>@<version> -->`
140
- footer is appended so re-runs can detect the installed version. Downgrades /
141
- different versions are skipped unless `--force` is passed.
142
- - **`--bootstrap`** — renders CI + tracker + secrets scaffolding. v1 special-
143
- cases `mobile-app + gh-actions + linear` (writes `.github/workflows/ship-pilot.yml`
144
- skeleton, `.ship/labels.yml`, and a `# --- ship-managed ---` block appended to
145
- `.env.example`). All other combinations emit `SHIP_BOOTSTRAP_PLAN.md` with a
146
- TODO checklist pointing at the preset artifact for full details.
147
- - **`--copy-playbook`** — fetches `collection/adoption-playbook` when
148
- published; a 404 is silently skipped (does not fail the command).
149
-
150
- ### Three primary invocations
151
-
152
- **MVP (dry-run preview, recommended first run):**
153
-
154
- ```bash
155
- shipctl init --dry-run --agents cursor --preset adoption-minimum --tracker none --ci manual
156
- ```
157
-
158
- **Pilot (apply, no scaffolding):**
159
-
160
- ```bash
161
- shipctl init --yes \
162
- --agents cursor,claude-md \
163
- --preset web-app --tracker linear --ci gh-actions \
164
- --copy-rules --telemetry off
165
- ```
166
-
167
- **Full bootstrap (mobile-app, with scaffolding skeletons):**
168
-
169
- ```bash
170
- shipctl init --bootstrap --yes \
171
- --agents cursor,claude-md,codex \
172
- --tracker linear --ci gh-actions --preset mobile-app \
173
- --copy-rules --telemetry off
174
- ```
175
-
176
- ### Full flag surface
177
-
178
- ```
179
- shipctl init
180
- [--yes] [--force] [--dry-run] [--cwd DIR] [--json]
181
- [--agents cursor,codex,claude-md] # preferred, csv
182
- [--tracker linear] # linear|jira|github-issues|…|none
183
- [--ci gh-actions] # gh-actions|gitlab-ci|…|manual
184
- [--preset mobile-app] # web-app|api-backend|mobile-app|…
185
- [--language ts] # ts|js|py|go|rust|…|multi
186
- [--channel stable|edge] # override api.channel
187
- [--copy-rules] # install agent-rules-<agent> files
188
- [--copy-playbook] # fetch adoption-playbook into cache
189
- [--bootstrap] # render CI/tracker scaffolding from preset
190
- [--telemetry on|off|ask] # override the interactive prompt
46
+ --agents cursor,codex \
47
+ --tracker github-issues \
48
+ --ci gh-actions \
49
+ --preset web-app \
50
+ --copy-rules
191
51
  ```
192
52
 
193
- ### Example output
194
-
195
- ```
196
- Ship init complete
197
- -----------------
198
- Config: .ship/config.yml
199
- Agents: cursor, claude-md
200
- Tracker: linear
201
- CI: gh-actions
202
- Preset: mobile-app
203
- Channel: stable
204
- Telemetry: off
205
-
206
- Installed rules:
207
- - .cursor/rules/ship-artifacts-protocol.mdc (from collection/agent-rules-cursor@1.0.0) [wrote]
208
- - CLAUDE.md (from collection/agent-rules-claude-md@1.0.0) [wrote]
209
-
210
- Bootstrap (preset=mobile-app):
211
- - wrote SHIP_BOOTSTRAP_PLAN.md
212
- - wrote .github/workflows/ship-pilot.yml
213
- - wrote .ship/labels.yml
214
- - appended .env.example
215
-
216
- Next:
217
- shipctl sync # keep artifacts fresh
218
- shipctl verify # check tracker labels, CI secrets, rules markers
219
- shipctl feedback draft # submit improvement idea
220
- ```
221
-
222
- ## Commands (quick reference)
223
-
224
- | Command | Role | Manual |
225
- |---------|------|--------|
226
- | **`shipctl init`** | Bootstrap an existing repo: agent rules, `.ship/config.yml`, optional CI scaffolding. | `documentation/discovery.md` |
227
- | **`shipctl new`** | Greenfield: `git init` + minimal README + `init`. | this README, `New & Verify` |
228
- | **`shipctl doctor`** | Inspect repo, propose stack, optionally write `.ship/inventory.json`. | this README, `Doctor` |
229
- | **`shipctl config`** | Safe edits to `.ship/config.yml` (`init` / `get` / `set` / `validate` / `show` / `path`). | `documentation/configuration.md` |
230
- | **`shipctl search`** | Vector search over docs + prompts (`POST /search`). | `documentation/discovery.md` |
231
- | **`shipctl docs fetch`**, **`shipctl docs feedback`** | Documentation file fetch and retro feedback. | `documentation/discovery.md` |
232
- | **`shipctl pattern\|tool\|collection`** **`list \| show \| fetch \| search`** | Versioned artifact bodies; plural aliases (`patterns`, `tools`, `collections`) work. | `documentation/authoring.md` |
233
- | **`shipctl sync`** | Pull artifacts into `.ship/cache/`; with `--lock` writes `.ship/shipctl.lock.json` covering every Play the declared lanes depend on. | this README, `Config & Sync` |
234
- | **`shipctl run`** | One-shot dispatch entry point. `kind: once` runs locally; other lane kinds are queued for the workspace runner. Reports its terminal status via the callback URL Ship injected. | `documentation/automations.md`, this README |
235
- | **`shipctl lanes`** | Generate / inspect / delete the `.github/workflows/ship-<lane>.yml` thin wrappers (`install` / `list` / `remove`). | `documentation/automations.md`, this README |
236
- | **`shipctl kickoff`** | Print a Play's pattern body for piping into the customer's agent in CI. | `documentation/automations.md` |
237
- | **`shipctl callback`** | Pattern-side: report a Run's terminal status + RunSummary outcome so Ship can render the row and route escalations into the Inbox. | this README |
238
- | **`shipctl knowledge init`** | Open a PR that seeds `.ship/knowledge/*.md` starter buckets. | `documentation/knowledge-buckets.md` |
239
- | **`shipctl telemetry`** | Opt-in anonymous usage events (default OFF). | this README, `Telemetry & Feedback` |
240
- | **`shipctl feedback`** | Local markdown drafts → POST `/feedback` → GitHub issue. | this README |
241
- | **`shipctl verify`** | Post-adoption liveness checks (local + config + network). | this README, `New & Verify` |
242
- | **`shipctl migrate`** | Upgrade `.ship/config.yml` from v1 to v2 (lanes-as-config). | `documentation/configuration.md` |
243
- | **`shipctl help`** | Top-level command list with the same vocabulary callout. | — |
244
-
245
- **Maintainers / full Ship checkout:** if the current directory (or **`SHIP_REPO`**) is inside the Ship monorepo, **`list` / `show` / `fetch`** for catalogs can read manifests from **disk** instead of HTTP. **`shipctl search`** always uses HTTP.
246
-
247
- Run **`shipctl help`** for the operator-first overview with the same vocabulary callout printed at the top.
248
-
249
- ## Doctor
250
-
251
- **`shipctl doctor`** inspects a repository using the pluggable adapter registry
252
- (`cli/lib/adapters/`) and proposes a best-guess Ship stack. It runs every
253
- tracker / CI / language / agent adapter's `detect(cwd)` hook, scores the
254
- findings, and infers a preset from repository structure (e.g. `pubspec.yaml`
255
- or `react-native` in deps → `mobile-app`; `packages/` or `pnpm-workspace.yaml`
256
- → `monorepo`). Nothing is ever written without **`--write-inventory`**.
53
+ Then check the repo:
257
54
 
258
55
  ```bash
259
- shipctl doctor # human report
260
- shipctl doctor --json # machine-readable
261
- shipctl doctor --cwd /path/to/other-repo # inspect elsewhere
262
- shipctl doctor --write-inventory # persist .ship/inventory.json
263
- ```
264
-
265
- Example output (trimmed):
266
-
267
- ```text
268
- Ship doctor — inspecting /path/to/your-product
269
-
270
- Tracker: linear (0.95) · evidence: .env (LINEAR_API_KEY), package.json (@linear/sdk)
271
- CI: gh-actions (1.00) · evidence: .github/workflows/ (3 workflow(s))
272
- Language: ts (1.00) · evidence: tsconfig.json (present)
273
- Agents: cursor (1.00), claude-md (1.00)
274
-
275
- Inferred preset: web-app (evidence: next.config.ts)
276
-
277
- Existing Ship artifacts:
278
- .ship/config.yml missing
279
- .ship/cache/ missing
280
- .ship/inventory.json missing
281
- .cursor/rules/ship-* missing
282
-
283
- Recommendations:
284
- 1. shipctl config init
285
- 2. shipctl init --bootstrap --tracker linear --ci gh-actions --agents cursor,claude-md --preset web-app
286
- 3. shipctl sync
287
- 4. shipctl verify
288
- ```
289
-
290
- Passing **`--write-inventory`** persists the findings to `.ship/inventory.json`
291
- so that `shipctl init --bootstrap` can pick up the inferred stack without
292
- re-running detection.
293
-
294
- ## Config & Sync
295
-
296
- Ship stores local state under **`.ship/`**. Methodology bodies never live in your
297
- repo git history — `shipctl sync` caches them in `.ship/cache/`, which is
298
- `.gitignore`d by default.
299
-
300
- ### `.ship/` layout
301
-
302
- ```
303
- .ship/
304
- ├── config.yml # RFC-0002 schema; committed. `lanes:` entries
305
- │ # are what the operator console renders as
306
- │ # Automations.
307
- ├── state.json # last_sync_at, last_manifest_hash; gitignored
308
- ├── shipctl.lock.json # set by `shipctl sync --lock`; pins every
309
- │ # pattern the declared lanes depend on
310
- ├── cache/ # per-repo artifact cache (gitignored)
311
- │ ├── pattern/<id>@<v>/
312
- │ │ ├── ARTIFACT.md # full body (frontmatter + content), per RFC-0005
313
- │ │ └── .meta.json # source, sha256, fetched_at, etc.
314
- │ ├── tool/<id>@<v>/…
315
- │ ├── collection/<id>@<v>/…
316
- │ └── doc/…
317
- ├── knowledge/ # operator-edited markdown buckets, committed
318
- ├── telemetry-outbox.jsonl # buffered telemetry events (gitignored)
319
- └── feedback-drafts/ # feedback draft markdowns (gitignored)
56
+ shipctl verify
320
57
  ```
321
58
 
322
- ### `shipctl config`
59
+ ## Core commands
323
60
 
324
- ```bash
325
- shipctl config init # bootstrap .ship/config.yml + state.json + cache/
326
- shipctl config path # print absolute path to config.yml
327
- shipctl config show # pretty-print effective YAML
328
- shipctl config get <dotted.key> # e.g. shipctl config get api.channel
329
- shipctl config set <k> <value> # atomic write, validates before saving
330
- shipctl config validate # exit 10 on invalid enum / bad URL / bad pin key
331
- ```
61
+ | Command | Use |
62
+ | --- | --- |
63
+ | `shipctl init` | Create config, infer stack, sync selected artifacts, optionally install agent rules. |
64
+ | `shipctl doctor` | Inspect repo signals without changing files unless `--write-inventory` is passed. |
65
+ | `shipctl verify` | Check config, cache, agent rules, generated files, and optional network/provider reachability. |
66
+ | `shipctl sync` | Refresh catalog artifacts into `.ship/cache/`; `--lock` writes a lockfile. |
67
+ | `shipctl config` | Show, validate, get, and set `.ship/config.yml` fields. |
68
+ | `shipctl pattern|tool|collection` | List, show, fetch, or search artifact bodies. |
69
+ | `shipctl docs fetch` | Fetch documentation content for agent context. |
70
+ | `shipctl knowledge init` | Seed starter `.ship/knowledge/*.md` files where supported. |
71
+ | `shipctl feedback` | Draft and submit artifact or docs feedback. |
72
+ | `shipctl telemetry` | Opt-in usage telemetry controls. |
332
73
 
333
- Value parsing for `config set`:
74
+ Run `shipctl help` and `shipctl <command> --help` for the exact flag surface.
334
75
 
335
- - Bare `true|false|null` → booleans / null.
336
- - `-?\d+(.\d+)?` → number.
337
- - `[a,b,c]` → array of strings (quotes optional).
338
- - Anything else → string.
76
+ ## Configuration
339
77
 
340
- Dotted keys under `artifacts.pins` preserve the embedded slash:
341
- `artifacts.pins.pattern/role-developer`.
78
+ The CLI reads `.ship/config.yml` from the repo root. It records stack hints, API settings, artifact pins, telemetry preference, cache behavior, and technical routine wiring.
342
79
 
343
- ```bash
344
- shipctl config set stack.agents [cursor,codex]
345
- shipctl config set api.channel edge
346
- shipctl config set artifacts.pins.pattern/role-developer 1.4.2
347
- ```
80
+ See [`../documentation/configuration.md`](../documentation/configuration.md) for the maintained field reference.
348
81
 
349
- ### `shipctl sync`
82
+ ## Agent rules
350
83
 
351
- ```bash
352
- shipctl sync # pull latest for this stack
353
- shipctl sync --check-only # report changes without writing cache
354
- shipctl sync --dry-run # --check-only + planned HTTP calls
355
- shipctl sync --only pattern:role-developer [--only tool:gh-actions]
356
- shipctl sync --channel edge
357
- shipctl sync --force-unpin # temporarily ignore version pins
358
- shipctl sync --lock # write .ship/shipctl.lock.json after sync
359
- ```
84
+ `shipctl init --copy-rules` installs marker-delimited blocks into the selected agent targets. Keep custom text outside the markers so re-runs can safely refresh the Ship-owned block.
360
85
 
361
- Summary format:
86
+ Typical targets include:
362
87
 
363
- ```
364
- up_to_date: 12
365
- updated: 3
366
- skipped_pin: 2
367
- deprecated: 1 (…)
368
- yanked: 0
369
- failed: 0
370
- ```
88
+ - `.cursor/rules/*.mdc`
89
+ - `AGENTS.md`
90
+ - `CLAUDE.md`
91
+ - `.codex/*`
92
+ - `.github/copilot-instructions.md`
371
93
 
372
- Pins are honoured: an entry whose manifest version does not satisfy the pin is
373
- reported as `skipped_pin` unless `--force-unpin` is set. After a successful
374
- sync, `.ship/state.json` records `last_sync_at` and `last_manifest_hash`. With
375
- `--lock`, `shipctl sync` also writes `.ship/shipctl.lock.json` covering every
376
- Play that the declared lanes depend on, so subsequent `shipctl run` invocations
377
- can refuse to drift off the pinned set.
94
+ Use [`../documentation/agent-matrix.md`](../documentation/agent-matrix.md) for the current agent id table.
378
95
 
379
- > Methodology docs never live in your repo. `shipctl sync` caches them in
380
- > `.ship/cache/`, sealed by `content_sha256` from the Ship manifest.
96
+ ## Artifacts
381
97
 
382
- ## Run
98
+ Ship distributes versioned artifacts:
383
99
 
384
- `shipctl run` is the **one-shot dispatch entry point** for an Automation
385
- (YAML key: `lanes:`). What it does depends on the lane's `kind`:
100
+ - `pattern` reusable procedures and prompt bodies;
101
+ - `tool` integration and adapter descriptions;
102
+ - `collection` — presets, agent rules, and addenda.
386
103
 
387
- | `kind:` value | Behaviour of `shipctl run` |
388
- |---------------|----------------------------|
389
- | `once` | Executes the lane fully on the local machine (the pattern body is fed to the configured agent; the result is reported back via `shipctl callback`). |
390
- | `lane` / `event` / `schedule` | Refuses to execute locally; the workspace's GitHub Actions runner picks the lane up via `.github/workflows/run-agent.yml`. The CLI exits with a clear message naming the lane id and its kind. |
104
+ The CLI can read artifacts directly from this monorepo during development or fetch them from the configured Ship API in a product repo.
391
105
 
392
- ```bash
393
- # preview which patterns + parameters the lane would dispatch with
394
- shipctl run --lane pr-self-review --dry-run
395
-
396
- # fanout: the same pattern over every repo in the workspace
397
- shipctl run --lane fleet-mobile-knowledge-refresh \
398
- --pattern fleet-knowledge-pack \
399
- --fanout matrix \
400
- --trigger event \
401
- --json
402
-
403
- # CI usage: shipctl injects --ship-run-id / --ship-callback-url / --ship-run-token
404
- # automatically; you only set them by hand when running outside the workspace runner
405
- shipctl run --lane release-cut \
406
- --ship-run-id "$SHIP_RUN_ID" \
407
- --ship-callback-url "$SHIP_CALLBACK_URL" \
408
- --ship-run-token "$SHIP_RUN_TOKEN"
409
- ```
106
+ ## Verification in CI
410
107
 
411
- Important flags:
412
-
413
- - `--pattern <id>` — override the lane's default pattern (a composite Play may
414
- declare several; this lets you target one specifically).
415
- - `--fanout matrix|sequential|concurrent` — only meaningful for fleet-scope
416
- lanes that target multiple repos.
417
- - `--trigger event|schedule|manual|once` — the trigger the lane was wired for;
418
- used to choose the payload shape.
419
- - `--offline` — skip every HTTP probe (resolves patterns from `.ship/cache/`
420
- only); useful for hermetic CI.
421
- - `--dry-run` — print the dispatch plan and exit 0; no agent invocation.
422
-
423
- A full Run lifecycle in production looks like: console (or schedule) creates a
424
- `pipeline_run` row → workspace runner is dispatched → runner calls
425
- `shipctl run --lane <id>` for `kind: once` lanes (or invokes the agent
426
- directly for `kind: lane`) → the pattern calls `shipctl callback` with the
427
- RunSummary → console renders the outcome row in `/runs` and any escalations
428
- land in `/inbox`.
429
-
430
- ## Lanes
431
-
432
- `shipctl lanes` manages the **thin GitHub Actions wrappers** that delegate to
433
- the reusable `run-agent.yml` workflow. Each lane in `.ship/config.yml`
434
- generates one `.github/workflows/ship-<lane>.yml` file. The file itself is a
435
- ~12-line yaml that does nothing more than `uses: ./.github/workflows/run-agent.yml`
436
- with the right `lane:` input — all the logic lives in the reusable workflow,
437
- so wrappers can be regenerated without touching execution semantics.
108
+ Use `shipctl verify` as the gate. For offline CI, commit the required cache or narrow checks to local categories:
438
109
 
439
110
  ```bash
440
- # write workflow files for every lane in config.yml
441
- shipctl lanes install --dry-run
442
- shipctl lanes install --yes
443
-
444
- # only one lane (or a few)
445
- shipctl lanes install --only pr-self-review,release-cut
446
-
447
- # wire to a specific shipctl version pin
448
- shipctl lanes install --shipctl-version 0.12.1 \
449
- --owner elmundi --repo ship --ref v0.12.1
450
-
451
- # inspect what's on disk vs config.yml
452
- shipctl lanes list --json
453
-
454
- # remove generated wrappers (does NOT touch lanes: config)
455
- shipctl lanes remove --dry-run
456
- shipctl lanes remove --only deprecated-lane --yes
457
- ```
458
-
459
- Notes:
460
-
461
- - `lanes install` writes files **only** for lanes with a configured trigger
462
- (`on.push`, `on.schedule`, `on.workflow_dispatch`). `kind: once` lanes
463
- intended to run only via `shipctl run` don't get a wrapper.
464
- - The same wrapper covers a fleet-scope lane (one workflow file in your
465
- pilot repo, fanout happens server-side via the matrix Ship dispatches).
466
- - Removing a wrapper does **not** remove the lane from `.ship/config.yml`;
467
- to fully retire an Automation, drop the `lanes.<id>` block from the YAML
468
- and re-run `shipctl lanes install` so the file is reconciled.
469
-
470
- ## Callback
471
-
472
- `shipctl callback` is what a Play's pattern calls to **close the loop on a
473
- Run**. It POSTs a structured payload to the URL Ship injected into the
474
- runner (`SHIP_CALLBACK_URL` env or `--callback-url`) so the operator console
475
- can render an outcome-first row in `/runs` and route any escalations into
476
- `/inbox`.
477
-
478
- The flag surface is **protocol-stable** (the workspace API depends on it);
479
- the help is grouped by intent.
480
-
481
- ### Identity (one of these is required)
482
-
483
- ```
484
- --run-id <uuid> # falls back to SHIP_RUN_ID
485
- --callback-url <url> # falls back to SHIP_CALLBACK_URL
486
- SHIP_RUN_TOKEN=<jwt> # bearer for the callback URL (CI sets this)
487
- SHIP_API_BASE=<url> # base for {api}/v1/runs/<id>/callback when only --run-id is set
488
- ```
489
-
490
- ### Status & summary
491
-
492
- ```
493
- --status ok|fail|cancelled # required terminal state
494
- --summary "Free text" # short human readout (kept in addition to outcome)
495
- --metric key=value # repeatable; persisted as-is
496
- ```
497
-
498
- ### RunSummary outcome (Phase 3)
499
-
500
- These map 1:1 to the `outcome:` JSONB column on `pipeline_runs` and to what
501
- the console renders:
502
-
503
- ```
504
- --outcome-text "Reviewed PR · 3 suggestions · 1 fix applied"
505
- --findings-count 3
506
- --severity high=1 --severity medium=2 # repeatable; map of sev → count
507
- --artifact pr:"Auto-fix: typo":"https://...": # repeatable; type:title[:ref]
508
- --artifact comment:"Self-review summary":"https://github.com/.../pull/42#…"
509
- --escalation clarification:"agent_low_confidence" # repeatable; type:reason
510
- --requires-approval # toggle the approval gate
511
- --approval-payload '{"...": "..."}' # JSON forwarded to the Inbox item
512
- ```
513
-
514
- You can also pass the full RunSummary as JSON via:
515
-
516
- - `SHIP_RUN_OUTCOME=$JSON_STRING`
517
- - `SHIP_RUN_OUTCOME_FILE=/path/to/outcome.json`
518
-
519
- Flags merge on top of the env / file payload (CLI wins).
520
-
521
- ### Example (canonical pattern recipe)
522
-
523
- ```bash
524
- shipctl callback --status ok \
525
- --outcome-text "Reviewed PR · 3 suggestions · 1 fix applied" \
526
- --findings-count 3 \
527
- --severity high=1 --severity medium=2 \
528
- --artifact comment:"PR self-review summary":"https://github.com/elmundi/ship/pull/42#issuecomment-…" \
529
- --artifact pr:"Auto-fix: typo in README":"https://github.com/elmundi/ship/pull/43"
530
- ```
531
-
532
- The same `## Reporting` block lives at the bottom of every top-Play pattern
533
- (see `artifacts/patterns/flow-pr-self-review/ARTIFACT.md` for the canonical
534
- example). When you author a new Play, copy that block as the contract you
535
- expect runners to honour.
536
-
537
- ## Knowledge
538
-
539
- `shipctl knowledge init` opens a PR in the target repo that seeds the
540
- `.ship/knowledge/` starter buckets (e.g. `code-style.md`, `ui-runbook.md`).
541
- The PR is intentionally minimal — operators are expected to fill the buckets
542
- in over time.
543
-
544
- ```bash
545
- # requires SHIP_API_TOKEN; targets the workspace's wired GitHub installation
546
- shipctl knowledge init \
547
- --workspace 11111111-1111-1111-1111-111111111111 \
548
- --repo elmundi/ship-pilot \
549
- --only code-style,ui-runbook \
550
- --json
551
- ```
552
-
553
- Behind the scenes, this hits the workspace API which uses the GitHub App
554
- installation to open the PR. The buckets the Plays read at runtime live
555
- under the same `.ship/knowledge/` tree the PR seeds.
556
-
557
- ## Telemetry & Feedback
558
-
559
- Anonymous telemetry is **opt-in and OFF by default** (RFC-0003). Nothing leaves
560
- the repo until you explicitly flip the switch with `shipctl telemetry on`.
561
- Events are first buffered to `.ship/telemetry-outbox.jsonl`; flushing to
562
- `POST /telemetry` is a deliberate, retry-safe step.
563
-
564
- ```bash
565
- # inspect current state
566
- shipctl telemetry status # share=..., anonymous_id=..., outbox_pending=N
567
-
568
- # opt in, with a narrow scope, non-interactively
569
- shipctl telemetry on --scope artifact_usage,improvement_drafts --yes
570
-
571
- # look at what's queued locally before sending
572
- shipctl telemetry buffer --limit 10
573
-
574
- # send any queued events (batches of 100); succeeded lines are removed
575
- shipctl telemetry flush
576
- shipctl telemetry flush --dry-run # preview only
577
-
578
- # data rights: export or delete by anonymous_id
579
- shipctl telemetry export --out telemetry.json
580
- shipctl telemetry delete-my-data # interactive confirmation required
581
-
582
- # rotate identity (server treats the previous id as a separate adopter)
583
- shipctl telemetry reset-id
584
-
585
- # fully disable
586
- shipctl telemetry off
587
- ```
588
-
589
- Allowed event types: `artifact.fetch`, `artifact.use`, `artifact.sync`,
590
- `feedback.submit`, `doctor.result`. Payload keys in the RFC-0003 denylist
591
- (`path, code, diff, branch, remote, email`) are stripped client-side before
592
- anything is appended to the outbox.
593
-
594
- Feedback is always drafted locally as a markdown file before it is sent
595
- anywhere:
596
-
597
- ```bash
598
- # create a draft
599
- shipctl feedback draft --kind pattern --id role-developer --version 1.4.2 \
600
- --title "Missing mobile preview step" \
601
- --summary "Evidence checklist misses mobile preview" \
602
- --recommendation "Add a bullet under Evidence"
603
-
604
- # review / edit (uses $EDITOR)
605
- shipctl feedback list
606
- shipctl feedback show .ship/feedback-drafts/2026-04-17-11-30-15-pattern-role-developer.md
607
- shipctl feedback edit .ship/feedback-drafts/2026-04-17-11-30-15-pattern-role-developer.md
608
-
609
- # submit → POST /feedback → GitHub issue URL; draft moves to sent/
610
- shipctl feedback submit .ship/feedback-drafts/2026-04-17-11-30-15-pattern-role-developer.md --yes
611
- ```
612
-
613
- Submission requires `kind`, `id`, `title`, and `summary`; missing fields fail
614
- with exit 1 (nothing sent). When `telemetry.share=true` and
615
- `scope.improvement_drafts=true`, a `feedback.submit` event is appended to the
616
- telemetry outbox on successful submission.
617
-
618
- ## New & Verify
619
-
620
- ### `shipctl new <name>`
621
-
622
- Scaffolds a fresh repo with the Ship wiring already in place: creates the
623
- target directory, runs `git init -q`, drops a minimal `README.md`, seeds
624
- `.ship/config.yml` via `shipctl config init`, applies the provided stack
625
- flags via `shipctl config set`, and (when `--agents` is supplied) runs
626
- `shipctl init --yes --copy-rules …` to install the agent rule files.
627
-
628
- ```bash
629
- shipctl new pharma-pilot \
630
- --preset mobile-app --tracker linear --ci gh-actions \
631
- --agents cursor,claude,codex --yes
632
- cd pharma-pilot
633
111
  shipctl verify --no-network
634
112
  ```
635
113
 
636
- Common flags:
637
-
638
- - `--here` — initialize in the current directory instead of creating `<name>/`.
639
- - `--preset / --tracker / --ci / --agents / --language / --channel` —
640
- forwarded to `config set` + `init`.
641
- - `--yes` — non-interactive (required for CI / dry-run).
642
- - `--dry-run` — describe the plan without touching disk.
643
- - `--json` — machine-readable summary of created files.
644
-
645
- ### `shipctl verify`
646
-
647
- Post-adoption liveness check. A collection of independent checks under
648
- `cli/lib/verify/checks/` grouped by category:
114
+ Warnings do not fail the command by default; failures do. Treat warnings as review prompts, not as proof the setup is broken.
649
115
 
650
- - **local** `.ship/config.yml` present, `.gitignore` excludes
651
- `.ship/cache/`, agent rule files have the
652
- `<!-- ship-cli: artifacts-protocol v1 -->` marker and `installed-from`
653
- footer, cached artifacts match their `.meta.json` sha256, bootstrap
654
- scaffolding (mobile-app + gh-actions + linear) carries
655
- `ship-managed` markers.
656
- - **config** — `stack.*` enum re-validation, declared agents have
657
- on-disk signals.
658
- - **network** (skip with `--no-network`) — `/health` (or `/patterns` as a
659
- fallback) reachable, local cache matches the channel catalog aggregated
660
- across `/patterns`, `/tools`, `/collections`, Linear labels exist (needs
661
- `LINEAR_API_KEY`), every `${{ secrets.X }}` reference in gh-actions
662
- workflows is declared in `.env.example`.
116
+ ## Telemetry and feedback
663
117
 
664
- Exit `0` when no check returned `fail`; warnings do not fail.
118
+ Telemetry is opt-in and off by default. Feedback drafts stay local until explicitly submitted.
665
119
 
666
120
  ```bash
667
- shipctl verify # full run
668
- shipctl verify --no-network # skip HTTP + Linear calls
669
- shipctl verify --check rules-markers,cache-integrity
670
- shipctl verify --severity warn # hide pass rows
671
- shipctl verify --json # { checks:[…], summary:{…}, exit_code }
121
+ shipctl telemetry off
122
+ shipctl feedback draft --kind pattern --id role-developer
672
123
  ```
673
124
 
674
- ## Versioning
675
-
676
- `shipctl --version` (or `shipctl version`) prints the running release. The
677
- version is part of every outbound `User-Agent` header so the methodology API
678
- can correlate adoption metrics with the client release.
679
-
680
- This package follows the **monorepo-wide** Ship version: a single `VERSION`
681
- file at the repo root drives `cli/package.json`, `landing/package.json`,
682
- `backend/app/main.py`, and the root `package.json` in lockstep via
683
- `scripts/version.mjs` (`npm run version:bump -- patch|minor|major|x.y.z`).
684
- See the root [`README.md`](../README.md#versioning--releases) for the full
685
- release recipe.
686
-
687
- ## Publishing (maintainers)
125
+ ## Development in this repo
688
126
 
689
- The GitHub Action **Publish @elmundi/ship-cli to npm** is triggered by either
690
- the unified `v<x.y.z>` tag (preferred — bumps every component in lockstep) or
691
- the legacy `cli-v<x.y.z>` tag (escape hatch for CLI-only patches). It runs
692
- `scripts/version.mjs check` before publishing so an out-of-sync tree never
693
- ships to npm.
127
+ From the repository root:
694
128
 
695
129
  ```bash
696
- npm run version:bump -- minor # 0.10.0 → 0.11.0, syncs everything
697
- git commit -am "release v$(cat VERSION)"
698
- git tag "v$(cat VERSION)"
699
- git push --follow-tags # publish workflow picks up v0.11.0
130
+ npm run shipctl -- help
131
+ npm test --prefix cli
700
132
  ```
701
133
 
702
- Repository secret **`NPM_TOKEN`** is required. Publish from the monorepo
703
- root: **`npm publish -w @elmundi/ship-cli`** — not `npm publish --prefix cli`
704
- (the root package is private).
705
-
706
- ## Reference
707
-
708
- Protocol-stable surfaces:
709
-
710
- - **Artifacts protocol** (`POST /search`, `POST /fetch`) — RFC-0001.
711
- - **Stack block + presets + adapters** — RFCs 0002 / 0004 / 0006.
712
- - **Telemetry** — RFC-0003.
713
- - **Operator IA** (Plays / Automations / Runs / Inbox) — RFC-0010.
714
- - **HTTP schemas live next to the source**: `artifacts/tools/methodology-api/ARTIFACT.md`.
715
-
716
- Every consumed artifact should be recorded in the PR or commit log as
717
- `<kind>:<id>@<version>` so reviewers can replay what the agent saw.
134
+ Catalog commands read `artifacts/**/ARTIFACT.md` directly when run inside this repo. Search and docs fetch still use the configured HTTP API.