specrails-desktop 2.56.0 → 2.57.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/cli/dist/args.js CHANGED
@@ -9,14 +9,7 @@ exports.DEFAULT_PORT = 4200;
9
9
  exports.KNOWN_VERBS = new Set([
10
10
  'implement',
11
11
  'batch-implement',
12
- 'why',
13
- 'get-backlog-specs',
14
- 'auto-propose-backlog-specs',
15
- 'propose-spec',
16
- 'refactor-recommender',
17
- 'health-check',
18
- 'compat-check',
19
- 'enrich',
12
+ 'retry',
20
13
  ]);
21
14
  function parseArgs(argv) {
22
15
  // argv is process.argv.slice(2)
package/cli/dist/help.js CHANGED
@@ -45,13 +45,7 @@ ${(0, output_1.bold)('Project Required:')}
45
45
  ${(0, output_1.bold)('Usage:')}
46
46
  specrails-desktop implement #42 Run a known specrails verb (prepends /specrails:)
47
47
  specrails-desktop batch-implement #40 #41 Batch implementation across issues
48
- specrails-desktop why Explain recent changes
49
- specrails-desktop get-backlog-specs View prioritized spec backlog
50
- specrails-desktop auto-propose-backlog-specs Generate new spec ideas
51
- specrails-desktop propose-spec Explore an idea and produce a spec
52
- specrails-desktop refactor-recommender Find refactoring opportunities
53
- specrails-desktop health-check Run codebase health check
54
- specrails-desktop compat-check Check for breaking API changes
48
+ specrails-desktop retry Resume the saved implementation run
55
49
  specrails-desktop "any raw prompt" Pass a raw prompt directly to claude
56
50
  specrails-desktop --status Print manager status and exit
57
51
  specrails-desktop --jobs Print recent job history and exit
@@ -7,14 +7,16 @@ read-only discovery; it does not execute a PATH shim or install a global package
7
7
  An explicit `SPECRAILS_CORE_BIN` wins when it resolves to a usable compatible
8
8
  package. Otherwise Desktop selects the newest compatible package from its
9
9
  activated managed installation, bundled resources, local dependency and external
10
- CLI on PATH. Core 4 and 5 remain supported. A runtime older than the active
10
+ CLI on PATH. Supported Core majors are 4, 5 and 6 (`SUPPORTED_CORE_MAJORS` in
11
+ `server/core-package.ts`). A runtime older than the active
11
12
  framework is rejected rather than silently replacing an update.
12
13
 
13
14
  ## Persistence and publication
14
15
 
15
- The release bundle pins Core 5.6.0 in `desktop-release.yml` and
16
- `scripts/assemble-bundled-core.lock.json`. This includes scoped runtime recovery
17
- and the Opus 5.5 alias. Update both pins together and check compatibility against
16
+ The release bundle pins Core 6.0.0 in `desktop-release.yml` and
17
+ `scripts/assemble-bundled-core.lock.json`. Core 6 is the Desktop-only engine: it
18
+ publishes integration contract 5.0 (no standalone `update`) and ships only the
19
+ implement, batch-implement and retry workflows. Update both pins together and check compatibility against
18
20
  the staged published package; retained runs still use their original runtime.
19
21
 
20
22
  Desktop updates retain the complete npm installation, including dependencies,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "specrails-desktop",
3
- "version": "2.56.0",
3
+ "version": "2.57.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -22,13 +22,7 @@ const WHICH_CMD = process.platform === 'win32' ? 'where' : 'which';
22
22
  const DESKTOP_KNOWN_COMMANDS = new Set([
23
23
  'implement',
24
24
  'batch-implement',
25
- 'why',
26
- 'product-backlog',
27
- 'update-product-driven-backlog',
28
- 'refactor-recommender',
29
- 'health-check',
30
- 'compat-check',
31
- 'enrich',
25
+ 'retry',
32
26
  ]);
33
27
  function isRecord(value) {
34
28
  return typeof value === 'object' && value !== null && !Array.isArray(value);
@@ -46,11 +40,14 @@ function isRenderedProviderContract(provider, value) {
46
40
  return false;
47
41
  // Core 5 has a deterministic installer. Enrichment no longer exists and is
48
42
  // therefore not evidence of provider availability on this contract shape.
49
- if (value.initCommand === 'init' && value.updateCommand === 'update') {
43
+ // Core 6 (contract 5.0) dropped the standalone `update` command: Desktop
44
+ // refreshes installs through init and the offline framework lifecycle.
45
+ if (value.initCommand === 'init' && (value.updateCommand === undefined || value.updateCommand === 'update')) {
50
46
  if (!isRecord(value.cli) || !isRecord(value.workflows))
51
47
  return false;
52
- if (!isStringArray(value.cli.initArgs) || !isStringArray(value.cli.updateArgs)
53
- || !value.cli.initArgs.includes('init') || !value.cli.updateArgs.includes('update'))
48
+ if (!isStringArray(value.cli.initArgs) || !value.cli.initArgs.includes('init'))
49
+ return false;
50
+ if (value.updateCommand === 'update' && (!isStringArray(value.cli.updateArgs) || !value.cli.updateArgs.includes('update')))
54
51
  return false;
55
52
  const workflows = value.workflows;
56
53
  if (!['implement', 'batch-implement', 'retry'].every(name => typeof workflows[name] === 'string' && workflows[name]))
@@ -1,10 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CORE_PACKAGE_SPEC = void 0;
4
- /** Online fallback selects the supported Core 5 lifecycle; 5.1.0 is the floor
5
- * because it quotes the command path in its Windows shell runner (OpenSpec init
6
- * from an install directory with spaces). The desktop bundles the same version.
7
- * Bundled Core 4 remains readable for installed apps; the runtime resolver
8
- * selects the newest usable compatible package and never downgrades a newer
9
- * activated framework. */
10
- exports.CORE_PACKAGE_SPEC = 'specrails-core@^5.1.0';
3
+ exports.CORE_PACKAGE_SPEC = exports.SUPPORTED_CORE_MAJORS = void 0;
4
+ exports.isSupportedCoreVersion = isSupportedCoreVersion;
5
+ /** Core majors this Desktop can drive. Core 6 publishes integration contract
6
+ * 5.0 (no standalone `update`); Cores 4 and 5 remain readable for installed
7
+ * apps. The runtime resolver selects the newest usable compatible package and
8
+ * never downgrades a newer activated framework. */
9
+ exports.SUPPORTED_CORE_MAJORS = [4, 5, 6];
10
+ function isSupportedCoreVersion(version) {
11
+ return exports.SUPPORTED_CORE_MAJORS.includes(Number(version.split('.')[0]));
12
+ }
13
+ /** Online fallback selects the Core 6 lifecycle, the same major the desktop bundles. */
14
+ exports.CORE_PACKAGE_SPEC = 'specrails-core@^6.0.0';
@@ -15,6 +15,7 @@ const fs_1 = __importDefault(require("fs"));
15
15
  const path_1 = __importDefault(require("path"));
16
16
  const artifact_registry_1 = require("./artifact-registry");
17
17
  const bundled_core_1 = require("./bundled-core");
18
+ const core_package_1 = require("./core-package");
18
19
  const semver_lite_1 = require("./semver-lite");
19
20
  const VERSION = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
20
21
  function managedCoreRoot(home) {
@@ -114,8 +115,8 @@ function resolveCoreRuntime(home, external) {
114
115
  const runtime = packageForBinary(override, 'override');
115
116
  if (!runtime)
116
117
  throw new Error('SPECRAILS_CORE_BIN does not resolve to a usable specrails-core package.');
117
- if (![4, 5].includes(Number(runtime.version.split('.')[0])))
118
- throw new Error('The explicit Core package is not compatible with this Desktop. Supported Core majors: 4 and 5.');
118
+ if (!(0, core_package_1.isSupportedCoreVersion)(runtime.version))
119
+ throw new Error(`The explicit Core package is not compatible with this Desktop. Supported Core majors: ${core_package_1.SUPPORTED_CORE_MAJORS.join(', ')}.`);
119
120
  if (current && (0, semver_lite_1.compareVersions)(runtime.version, current) < 0)
120
121
  throw new Error(`The explicit Core ${runtime.version} is older than active framework ${current}; Desktop will not downgrade it.`);
121
122
  return runtime;
@@ -135,10 +136,7 @@ function resolveCoreRuntime(home, external) {
135
136
  candidates.push(managed);
136
137
  }
137
138
  candidates.push(...(external ?? (home === undefined ? discoverExternalCoreRuntimes() : [])));
138
- const compatible = candidates.filter(candidate => {
139
- const major = Number(candidate.version.split('.')[0]);
140
- return major >= 4 && major <= 5;
141
- }).sort((a, b) => (0, semver_lite_1.compareVersions)(b.version, a.version));
139
+ const compatible = candidates.filter(candidate => (0, core_package_1.isSupportedCoreVersion)(candidate.version)).sort((a, b) => (0, semver_lite_1.compareVersions)(b.version, a.version));
142
140
  const selected = compatible[0] ?? null;
143
141
  if (current && (!selected || (0, semver_lite_1.compareVersions)(selected.version, current) < 0)) {
144
142
  throw new Error(`Core framework ${current} is installed, but its runtime package is unavailable. Reinstall Core ${current} or a newer compatible version; Desktop will not downgrade it.`);
@@ -13,6 +13,7 @@ const semver_lite_1 = require("./semver-lite");
13
13
  const win_spawn_1 = require("./util/win-spawn");
14
14
  const bundled_core_1 = require("./bundled-core");
15
15
  const core_runtime_1 = require("./core-runtime");
16
+ const core_package_1 = require("./core-package");
16
17
  const artifact_registry_1 = require("./artifact-registry");
17
18
  /** Voluntary Core updates retain the complete npm package and dependencies,
18
19
  * publish its framework, then await every project refresh. Partial refreshes
@@ -117,8 +118,8 @@ class CoreUpdateManager {
117
118
  if (!requested || !(0, semver_lite_1.isValidVersion)(requested)) {
118
119
  return { ok: false, error: 'No valid target version to update to. Check for updates first.' };
119
120
  }
120
- if (!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(requested) || ![4, 5].includes(Number(requested.split('.')[0]))) {
121
- return { ok: false, error: 'This Desktop supports Core 4 and 5. Update Desktop before installing another major version.' };
121
+ if (!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(requested) || !(0, core_package_1.isSupportedCoreVersion)(requested)) {
122
+ return { ok: false, error: `This Desktop supports Core ${core_package_1.SUPPORTED_CORE_MAJORS.join(', ')}. Update Desktop before installing another major version.` };
122
123
  }
123
124
  const current = (0, framework_manager_1.readCurrentFrameworkVersion)(this.home);
124
125
  if (current && !(0, semver_lite_1.isNewer)(requested, current) && !(requested === current && ((0, core_runtime_1.getCoreRuntimeStatus)(this.home).error || this.pendingVersion === requested))) {
@@ -1,271 +0,0 @@
1
- ---
2
- name: "Compatibility Impact Analyzer"
3
- description: "Snapshot the current API surface and detect breaking changes against a prior baseline. Generates a migration guide when breaking changes are found."
4
- category: Workflow
5
- tags: [workflow, compatibility, breaking-changes, migration]
6
- ---
7
-
8
- Analyze the API surface of **specrails-desktop** for backwards compatibility. Extracts the current contract surface (CLI flags, template placeholders, command names, argument flags, agent names, config keys), compares against a stored baseline, classifies each change by severity, and generates a migration guide when breaking changes are found.
9
-
10
- **Input:** `$ARGUMENTS` — optional flags:
11
- - `--diff` — compare current surface to most recent snapshot (default when snapshots exist)
12
- - `--snapshot` — capture current surface and save without diffing (default on first run)
13
- - `--since <date>` — diff against snapshot from this date (ISO format: YYYY-MM-DD)
14
- - `--propose <change-dir>` — diff proposed changes in `openspec/changes/<change-dir>/` against current surface
15
- - `--dry-run` — run all phases but skip saving the snapshot
16
-
17
- ---
18
-
19
- ## Phase 0: Argument Parsing
20
-
21
- Parse `$ARGUMENTS` to set runtime variables.
22
-
23
- **Variables to set:**
24
-
25
- - `MODE` — string, one of `"snapshot"`, `"diff"`, `"propose"`. Default: `"diff"` if `.claude/compat-snapshots/` contains any `.json` files; `"snapshot"` otherwise.
26
- - `COMPARE_DATE` — string (ISO date) or empty string. Default: `""` (use most recent snapshot).
27
- - `PROPOSE_DIR` — string or empty string. Default: `""`.
28
- - `DRY_RUN` — boolean. Default: `false`.
29
-
30
- **Parsing rules:**
31
-
32
- 1. Scan `$ARGUMENTS` for `--snapshot`. If found, set `MODE=snapshot`.
33
- 2. Scan for `--diff`. If found, set `MODE=diff`.
34
- 3. Scan for `--since <date>`. If found, set `COMPARE_DATE=<date>` and (if `MODE` not already set to `snapshot`) set `MODE=diff`.
35
- 4. Scan for `--propose <change-dir>`. If found, set `PROPOSE_DIR=<change-dir>` and `MODE=propose`.
36
- - Verify `openspec/changes/<change-dir>/` exists. If not: print `Error: no change found at openspec/changes/<change-dir>/` and stop.
37
- 5. Scan for `--dry-run`. If found, set `DRY_RUN=true`.
38
- 6. Apply default-mode logic if `MODE` is not yet set: check whether `.claude/compat-snapshots/` exists and contains `.json` files. If yes: `MODE=diff`. If no: `MODE=snapshot`.
39
-
40
- **Verify prerequisites:**
41
-
42
- - Check whether `templates/` directory exists. If not: print `Error: templates/ not found — is this a specrails repo?` and stop.
43
- - Check whether `bin/specrails-core.mjs` exists. If not: set `INSTALLER_AVAILABLE=false` (installer flags category will be skipped). Otherwise set `INSTALLER_AVAILABLE=true`.
44
-
45
- **Print active configuration:**
46
-
47
- ```
48
- Mode: <MODE> | Compare date: <COMPARE_DATE or "latest"> | Dry-run: <true/false>
49
- ```
50
-
51
- ---
52
-
53
- ## Phase 1: Extract Current Surface
54
-
55
- Read the codebase and build the surface snapshot. Print one progress line as each category completes.
56
-
57
- **Surface category: installer_flags**
58
-
59
- If `INSTALLER_AVAILABLE=false`: print ` installer_flags: skipped (bin/specrails-core.mjs not found)` and record as unavailable.
60
-
61
- Otherwise: read `bin/specrails-core.mjs`. Extract every `--<word>` flag pattern that is accepted by the CLI dispatcher. For each flag, record the flag string and line number.
62
-
63
- Print: ` installer_flags: N found`
64
-
65
- **Surface category: template_placeholders**
66
-
67
- Read all files matching `templates/**/*.md`. For each file, extract all `` patterns (regex: `\{\{[A-Z][A-Z0-9_]*\}\}`). Deduplicate across files. For each unique key, record the list of source files it appears in.
68
-
69
- Note: Skip patterns inside code fences that are used as documentation examples (i.e., patterns that appear inside triple-backtick blocks describing placeholder syntax rather than actual template usage). Use judgment to distinguish real template placeholders from documented examples.
70
-
71
- Print: ` template_placeholders: N unique keys found`
72
-
73
- **Surface category: command_names and command_arguments**
74
-
75
- Read each file in `templates/commands/`. For each:
76
- - Extract `name:` value from the YAML frontmatter (between the first `---` and second `---`)
77
- - Extract the display name from the frontmatter `name:` field (the quoted string)
78
- - Find all `--<word>` flag patterns in the `$ARGUMENTS` section or argument description prose
79
- - Record command name, display name, source file, and flags list
80
-
81
- Print: ` command_names: N commands found`
82
- Print: ` command_arguments: N commands with flags documented`
83
-
84
- **Surface category: agent_names**
85
-
86
- Read each file in `templates/agents/`. Extract `name:` value from the YAML frontmatter.
87
-
88
- Print: ` agent_names: N agents found`
89
-
90
- **Surface category: config_keys**
91
-
92
- Read `openspec/config.yaml`. Extract all top-level YAML keys (lines matching `^<key>:` at zero indentation).
93
-
94
- Print: ` config_keys: N keys found`
95
-
96
- **Build the surface object:**
97
-
98
- Assemble all extracted data into a snapshot object matching the schema:
99
-
100
- ```json
101
- {
102
- "schema_version": "1",
103
- "captured_at": "<ISO 8601 datetime>",
104
- "git_sha": "<git rev-parse HEAD or 'unknown'>",
105
- "git_branch": "<git rev-parse --abbrev-ref HEAD or 'unknown'>",
106
- "surfaces": {
107
- "installer_flags": [...],
108
- "template_placeholders": [...],
109
- "command_names": [...],
110
- "command_arguments": [...],
111
- "agent_names": [...],
112
- "config_keys": [...]
113
- }
114
- }
115
- ```
116
-
117
- Set `CURRENT_SURFACE` to this object.
118
-
119
- If `MODE=snapshot`: proceed directly to Phase 5 (skip Phases 2–4 diff logic, but still print a surface summary).
120
-
121
- ---
122
-
123
- ## Phase 2: Load Baseline
124
-
125
- Applies in `diff` and `propose` modes only.
126
-
127
- **For `diff` mode:**
128
-
129
- 1. Check whether `.claude/compat-snapshots/` exists and contains `.json` files.
130
- - If empty or missing: print `Advisory: no prior snapshot found. Switching to snapshot mode.` Set `MODE=snapshot`. Proceed to Phase 5.
131
- 2. If `COMPARE_DATE` is empty: select the most recently modified `.json` file.
132
- 3. If `COMPARE_DATE` is set: find the snapshot whose filename date is closest to `COMPARE_DATE` without exceeding it. If no match within 7 days: print `Warning: no snapshot found near <COMPARE_DATE>. Falling back to most recent.` Use most recent.
133
- 4. Load the selected file as `BASELINE_SURFACE`.
134
- 5. Print: `Baseline: <YYYY-MM-DD> (<sha from filename>)`
135
-
136
- **For `propose` mode:**
137
-
138
- 1. Load the most recent snapshot from `.claude/compat-snapshots/` as `BASELINE_SURFACE` (same selection logic as `diff` mode with `COMPARE_DATE` empty).
139
- 2. Additionally read `openspec/changes/<PROPOSE_DIR>/design.md` to understand the projected surface changes.
140
- - If `design.md` does not exist: print `Warning: no design.md found in openspec/changes/<PROPOSE_DIR>/. Proceeding with surface extraction only (no projection).`
141
- - If it exists: read also `openspec/changes/<PROPOSE_DIR>/tasks.md` if present.
142
- 3. Use the proposed changes to project the "after" surface: identify which elements would be added, removed, or modified based on the design document.
143
- 4. Print: `Propose mode: analyzing openspec/changes/<PROPOSE_DIR>/`
144
-
145
- Set `BASELINE_SURFACE` and `PROJECTED_CHANGES` (in propose mode).
146
-
147
- ---
148
-
149
- ## Phase 3: Diff and Classify
150
-
151
- Applies in `diff` and `propose` modes. Skipped in `snapshot` mode.
152
-
153
- For each surface category (`installer_flags`, `template_placeholders`, `command_names`, `command_arguments`, `agent_names`, `config_keys`):
154
-
155
- 1. Build identifier sets from baseline and current (or projected, in propose mode).
156
- 2. Compute:
157
- - `removed = identifiers in baseline but not in current`
158
- - `added = identifiers in current but not in baseline`
159
- - `common = identifiers in both`
160
- 3. For common elements: check whether attributes changed (display name, flags list, file list). Classify attribute changes as Category 3 (Signature Change) if they affect the interface.
161
- 4. Classify each removal:
162
- - If a similar-looking name appears in `added`: classify as **Category 2: Rename** (BREAKING — MAJOR)
163
- - Otherwise: classify as **Category 1: Removal** (BREAKING — MAJOR)
164
- 5. Classify additions as non-breaking (new additions do not break existing callers).
165
- 6. Classify behavioral changes detected from the design document (in propose mode) as **Category 4: Behavioral Change** (ADVISORY).
166
-
167
- Build two lists:
168
- - `BREAKING_CHANGES` — list of `{ category, element, surface, severity, description }` objects (Categories 1, 2, 3)
169
- - `ADVISORY_CHANGES` — list of `{ category, element, surface, description }` objects (Category 4)
170
-
171
- ---
172
-
173
- ## Phase 4: Generate Report
174
-
175
- Print the full compatibility report.
176
-
177
- ```
178
- ## Compatibility Impact Report — specrails-desktop
179
- Date: <ISO date> | Commit: <git_short_sha or "unknown">
180
-
181
- ### Surface Snapshot
182
- | Category | Elements Found |
183
- |----------|---------------|
184
- | Installer flags | N |
185
- | Template placeholders | N |
186
- | Command names | N |
187
- | Command argument flags | N |
188
- | Agent names | N |
189
- | Config keys | N |
190
-
191
- ### Breaking Changes (N found)
192
- <if BREAKING_CHANGES is empty:>
193
- None detected.
194
-
195
- <if BREAKING_CHANGES is non-empty, for each:>
196
- - [Category <N>: <category-name>] <surface>: `<element>` — <description>
197
-
198
- ### Advisory Changes (N found)
199
- <if ADVISORY_CHANGES is empty:>
200
- None detected.
201
-
202
- <if ADVISORY_CHANGES is non-empty, for each:>
203
- - [Category 4: Behavioral Change] <surface>: `<element>` — <description>
204
- ```
205
-
206
- **Migration Guide** (only when `len(BREAKING_CHANGES) > 0`):
207
-
208
- For each breaking change, append a Migration Guide block:
209
-
210
- ```
211
- ## Migration Guide
212
-
213
- **Change type:** <Removal | Rename | Signature Change>
214
- **Severity:** BREAKING
215
- **Affects:** <who is affected>
216
-
217
- ### What Changed
218
- <one paragraph describing before and after>
219
-
220
- ### Before
221
- <concrete example of old usage>
222
-
223
- ### After
224
- <concrete example of new usage>
225
-
226
- ### Remediation Options
227
-
228
- **Option A — Backwards-compatible alias (recommended)**
229
- <how to add an alias or shim>
230
-
231
- **Option B — Clean break with changelog**
232
- <what to put in CHANGELOG.md>
233
-
234
- ### Version Strategy
235
- <MAJOR bump if removing/renaming; MINOR if signature-only>
236
- ```
237
-
238
- ---
239
-
240
- ## Phase 5: Save Snapshot
241
-
242
- **If `DRY_RUN=true`:**
243
-
244
- Print: `Snapshot not saved — dry-run mode`
245
-
246
- Skip the save. Still perform the housekeeping check and `.gitignore` check below.
247
-
248
- **If `DRY_RUN=false`:**
249
-
250
- 1. Determine filename: `<YYYY-MM-DD>-<git_short_sha>.json`. If git is unavailable: `<YYYY-MM-DD>-unknown.json`.
251
- 2. Create `.claude/compat-snapshots/` if it does not exist.
252
- 3. Write `CURRENT_SURFACE` serialized as JSON to `.claude/compat-snapshots/<filename>`.
253
- 4. Print: `Snapshot saved: .claude/compat-snapshots/<filename>`
254
-
255
- **Housekeeping notice:**
256
-
257
- Count `.json` files in `.claude/compat-snapshots/`. If count > 30, print:
258
-
259
- ```
260
- Note: .claude/compat-snapshots/ has N snapshots. Consider pruning old ones with:
261
- ls -t .claude/compat-snapshots/ | tail -n +31 | xargs -I{} rm .claude/compat-snapshots/{}
262
- ```
263
-
264
- **.gitignore suggestion:**
265
-
266
- Check whether `.claude/compat-snapshots/` appears in `.gitignore` (if `.gitignore` exists). If it does not appear, print:
267
-
268
- ```
269
- Tip: compat snapshots are local artifacts. Add to .gitignore:
270
- echo '.claude/compat-snapshots/' >> .gitignore
271
- ```
@@ -1,62 +0,0 @@
1
- # Doctor: specrails Health Check
2
-
3
- Run the specrails health check to validate that all prerequisites are correctly configured for this repository.
4
-
5
- ---
6
-
7
- ## What it checks
8
-
9
- | Check | Pass condition |
10
- |-------|---------------|
11
- | Claude Code CLI | `claude` binary found in PATH |
12
- | Claude API key | `claude config list` shows a key OR `ANTHROPIC_API_KEY` env var set |
13
- | Agent files | Generated agent files exist under `.claude/agents/` |
14
- | CLAUDE.md | `CLAUDE.md` present in the repo root |
15
- | Git initialized | `.git/` directory present |
16
- | npm | `npm` binary found in PATH |
17
-
18
- ## How to run
19
-
20
- This command uses the Node-native doctor runtime. Run it directly with:
21
-
22
- ```
23
- npx specrails-core@latest doctor
24
- ```
25
-
26
- If `specrails-core` is already on your `PATH`, this works too:
27
-
28
- ```
29
- specrails-core doctor
30
- ```
31
-
32
- ## Output
33
-
34
- Each check is displayed as ✅ (pass) or ❌ (fail with fix instruction).
35
-
36
- On all checks passed:
37
- ```
38
- All 6 checks passed. Run /specrails:get-backlog-specs to get started.
39
- ```
40
-
41
- On failure:
42
- ```
43
- ❌ API key: not configured
44
- Fix: Run: claude config set api_key <your-key> | Get a key: https://console.anthropic.com/
45
-
46
- 1 check(s) failed.
47
- ```
48
-
49
- ## Exit codes
50
-
51
- - `0` — all checks passed
52
- - `1` — one or more checks failed
53
-
54
- ## Log file
55
-
56
- Each run appends a timestamped summary to `~/.specrails/doctor.log`:
57
-
58
- ```
59
- 2026-03-20T10:00:00Z checks=6 passed=6 failed=0
60
- ```
61
-
62
- The `~/.specrails/` directory is created automatically if it does not exist.