@trieungoctam/speckit 0.3.4 → 0.3.6
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 +7 -0
- package/dist/adapters/tool-checks.d.ts +2 -0
- package/dist/adapters/tool-checks.js +37 -10
- package/dist/cli.js +8 -2
- package/dist/commands/doctor.js +16 -7
- package/dist/commands/graph.js +31 -3
- package/dist/commands/init.js +4 -2
- package/dist/commands/next.js +2 -2
- package/dist/commands/ready.js +6 -4
- package/dist/commands/setup.d.ts +9 -0
- package/dist/commands/setup.js +131 -0
- package/dist/commands/sync.js +4 -2
- package/dist/commands/validate.js +4 -2
- package/dist/core/colors.d.ts +11 -0
- package/dist/core/colors.js +40 -0
- package/docs/adapters.md +21 -0
- package/docs/beads-viewer-setup.md +58 -0
- package/docs/development-roadmap.md +3 -3
- package/docs/project-changelog.md +26 -0
- package/docs/use-cases.md +12 -0
- package/docs/workflow-model.md +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -11,6 +11,7 @@ The curated skill set is intentionally small: `spec-shape`, `spec-research`, `sp
|
|
|
11
11
|
## Quickstart
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
+
npx @trieungoctam/speckit@latest setup
|
|
14
15
|
npx @trieungoctam/speckit@latest init --ide cursor
|
|
15
16
|
npx @trieungoctam/speckit@latest init --ide all
|
|
16
17
|
npx @trieungoctam/speckit@latest init --enterprise --ide all
|
|
@@ -19,6 +20,7 @@ npx @trieungoctam/speckit@latest session start "Add checkout validation"
|
|
|
19
20
|
npx @trieungoctam/speckit@latest quick "Add checkout validation"
|
|
20
21
|
npx @trieungoctam/speckit@latest context .speckit/stories/<story>.md
|
|
21
22
|
npx @trieungoctam/speckit@latest sync
|
|
23
|
+
npx @trieungoctam/speckit@latest graph setup
|
|
22
24
|
npx @trieungoctam/speckit@latest sprint plan
|
|
23
25
|
npx @trieungoctam/speckit@latest graph triage --json
|
|
24
26
|
npx @trieungoctam/speckit@latest validate --json
|
|
@@ -28,6 +30,8 @@ npx @trieungoctam/speckit@latest session checkpoint --note "red complete"
|
|
|
28
30
|
npx @trieungoctam/speckit@latest review
|
|
29
31
|
```
|
|
30
32
|
|
|
33
|
+
Interactive CLI output is colorized when the terminal supports ANSI colors. Use `NO_COLOR=1` to disable colors, or `SPECKIT_COLOR=1` to force colors for demos and snapshots.
|
|
34
|
+
|
|
31
35
|
Or install globally:
|
|
32
36
|
|
|
33
37
|
```bash
|
|
@@ -66,6 +70,7 @@ For implementation stories, red-green-refactor evidence is mandatory. A story is
|
|
|
66
70
|
|
|
67
71
|
| Command | Purpose |
|
|
68
72
|
| --- | --- |
|
|
73
|
+
| `speckit setup` | Open an interactive setup wizard for mode, IDE adapter, overwrite policy, and Beads Viewer setup. |
|
|
69
74
|
| `speckit init` | Create `.speckit/` core runtime, super-agent, skill catalog, and all IDE adapters. |
|
|
70
75
|
| `speckit init --enterprise` | Add flow, tool policy, and prompt harness files on top of the shared runtime. |
|
|
71
76
|
| `speckit init --ide <name>` | Generate shared Speckit runtime plus one adapter: `claude-code`, `codex`, `antigravity`, `opencode`, or `cursor`. |
|
|
@@ -88,6 +93,7 @@ For implementation stories, red-green-refactor evidence is mandatory. A story is
|
|
|
88
93
|
| `speckit next` | Safely wraps `bv --robot-next --format json`. |
|
|
89
94
|
| `speckit sprint plan` | Build a sprint plan and status file from synced stories. |
|
|
90
95
|
| `speckit sprint next` | Pick the next selectable story from sprint state. |
|
|
96
|
+
| `speckit graph setup` | Print Beads Viewer install commands, check `br`/`bd`/`bv`, and prepare `.beads/beads.jsonl`. |
|
|
91
97
|
| `speckit graph triage` | Run Beads Viewer robot triage, or local JSON fallback if `bv` is missing. |
|
|
92
98
|
| `speckit graph plan` | Run Beads Viewer robot plan, or local JSON fallback if `bv` is missing. |
|
|
93
99
|
| `speckit graph insights` | Run Beads Viewer robot insights, or local JSON fallback if `bv` is missing. |
|
|
@@ -112,6 +118,7 @@ See `docs/adapters.md` for exact output paths.
|
|
|
112
118
|
## Guides
|
|
113
119
|
|
|
114
120
|
- `docs/use-cases.md` covers setup, migration, quick changes, full planning, long sessions, TDD, graph automation, review, CI, and troubleshooting.
|
|
121
|
+
- `docs/beads-viewer-setup.md` covers Beads Viewer installation, `bv` verification, and robot-safe graph usage.
|
|
115
122
|
- `docs/workflow-model.md` describes the quick and full workflow lanes.
|
|
116
123
|
- `docs/prompt-architecture.md` describes the prompt contract used by the super-agent, skills, workflows, run prompt, and IDE adapters.
|
|
117
124
|
- `docs/spec-quality-gates.md` describes validation gates for release readiness.
|
|
@@ -3,6 +3,8 @@ export type ToolCheck = {
|
|
|
3
3
|
required: boolean;
|
|
4
4
|
available: boolean;
|
|
5
5
|
hint: string;
|
|
6
|
+
install?: string[];
|
|
6
7
|
};
|
|
7
8
|
export declare function checkTools(): ToolCheck[];
|
|
9
|
+
export declare function beadsViewerInstallGuide(): string;
|
|
8
10
|
export declare function commandExists(command: string): boolean;
|
|
@@ -1,23 +1,50 @@
|
|
|
1
1
|
import { spawnSync } from "node:child_process";
|
|
2
2
|
const tools = [
|
|
3
|
-
["git", true, "Install Git and run Speckit inside a repository."],
|
|
4
|
-
["node", true, "Install Node.js 20 or newer."],
|
|
5
|
-
["br", false, "Recommended beads CLI. Use bd only for older projects."],
|
|
6
|
-
["bd", false, "Legacy beads CLI fallback."],
|
|
7
|
-
[
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
["git", true, "Install Git and run Speckit inside a repository.", ["https://git-scm.com/downloads"]],
|
|
4
|
+
["node", true, "Install Node.js 20 or newer.", ["https://nodejs.org/"]],
|
|
5
|
+
["br", false, "Recommended beads CLI. Use bd only for older projects.", ["Install beads_rust/br from your team's preferred channel."]],
|
|
6
|
+
["bd", false, "Legacy beads CLI fallback.", ["brew install beads", "go install github.com/steveyegge/beads/cmd/bd@latest"]],
|
|
7
|
+
[
|
|
8
|
+
"bv",
|
|
9
|
+
false,
|
|
10
|
+
"Recommended for Beads Viewer robot commands.",
|
|
11
|
+
[
|
|
12
|
+
"brew install dicklesworthstone/tap/bv",
|
|
13
|
+
"go install github.com/Dicklesworthstone/beads_viewer/cmd/bv@latest",
|
|
14
|
+
"nix run github:Dicklesworthstone/beads_viewer -- --help",
|
|
15
|
+
],
|
|
16
|
+
],
|
|
17
|
+
["claude", false, "Claude Code adapter runtime.", ["https://docs.anthropic.com/en/docs/claude-code"]],
|
|
18
|
+
["codex", false, "Codex adapter runtime.", ["https://developers.openai.com/codex"]],
|
|
19
|
+
["opencode", false, "OpenCode adapter runtime.", ["https://opencode.ai/"]],
|
|
20
|
+
["cursor", false, "Cursor adapter runtime.", ["https://cursor.com/"]],
|
|
12
21
|
];
|
|
13
22
|
export function checkTools() {
|
|
14
|
-
return tools.map(([name, required, hint]) => ({
|
|
23
|
+
return tools.map(([name, required, hint, install]) => ({
|
|
15
24
|
name,
|
|
16
25
|
required,
|
|
17
26
|
available: commandExists(name),
|
|
18
27
|
hint,
|
|
28
|
+
install: [...install],
|
|
19
29
|
}));
|
|
20
30
|
}
|
|
31
|
+
export function beadsViewerInstallGuide() {
|
|
32
|
+
return `Beads Viewer setup
|
|
33
|
+
|
|
34
|
+
Install bv with one of:
|
|
35
|
+
brew install dicklesworthstone/tap/bv
|
|
36
|
+
go install github.com/Dicklesworthstone/beads_viewer/cmd/bv@latest
|
|
37
|
+
nix run github:Dicklesworthstone/beads_viewer -- --help
|
|
38
|
+
|
|
39
|
+
Verify:
|
|
40
|
+
bv --version
|
|
41
|
+
speckit sync
|
|
42
|
+
speckit graph triage --json
|
|
43
|
+
|
|
44
|
+
Rules:
|
|
45
|
+
Never run bare bv from agents. Use Speckit wrappers or bv --robot-* flags.
|
|
46
|
+
Speckit writes .beads/beads.jsonl from .speckit stories before graph commands.`;
|
|
47
|
+
}
|
|
21
48
|
export function commandExists(command) {
|
|
22
49
|
const result = spawnSync(command, ["--version"], {
|
|
23
50
|
encoding: "utf8",
|
package/dist/cli.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { initCommand } from "./commands/init.js";
|
|
2
|
+
import { setupCommand } from "./commands/setup.js";
|
|
2
3
|
import { doctorCommand } from "./commands/doctor.js";
|
|
3
4
|
import { startCommand } from "./commands/start.js";
|
|
4
5
|
import { shapeCommand } from "./commands/shape.js";
|
|
@@ -18,6 +19,7 @@ import { runCommand } from "./commands/run.js";
|
|
|
18
19
|
import { readyCommand } from "./commands/ready.js";
|
|
19
20
|
import { reviewCommand } from "./commands/review.js";
|
|
20
21
|
import { closeCommand } from "./commands/close.js";
|
|
22
|
+
import { createColors } from "./core/colors.js";
|
|
21
23
|
export async function main(argv = process.argv.slice(2), root = process.cwd()) {
|
|
22
24
|
const parsed = parseArgs(argv);
|
|
23
25
|
try {
|
|
@@ -26,6 +28,8 @@ export async function main(argv = process.argv.slice(2), root = process.cwd()) {
|
|
|
26
28
|
return 0;
|
|
27
29
|
}
|
|
28
30
|
switch (parsed.command) {
|
|
31
|
+
case "setup":
|
|
32
|
+
return setupCommand({ root });
|
|
29
33
|
case "init":
|
|
30
34
|
return initCommand({
|
|
31
35
|
root,
|
|
@@ -142,9 +146,11 @@ function isHelp(parsed) {
|
|
|
142
146
|
return parsed.command === "help" || parsed.command === "--help" || parsed.command === "-h" || has(parsed, "help");
|
|
143
147
|
}
|
|
144
148
|
function printHelp() {
|
|
145
|
-
|
|
149
|
+
const colors = createColors();
|
|
150
|
+
console.log(`${colors.bold(colors.cyan("Speckit"))} - Agile + TDD workflow compiler for agentic IDEs
|
|
146
151
|
|
|
147
152
|
Usage:
|
|
153
|
+
speckit setup
|
|
148
154
|
speckit init [--ide all|claude-code|codex|antigravity|opencode|cursor] [--force]
|
|
149
155
|
speckit init --enterprise [--ide all] [--force]
|
|
150
156
|
speckit doctor [--json] [--deep]
|
|
@@ -157,7 +163,7 @@ Usage:
|
|
|
157
163
|
speckit permissions audit [--path <path>] [--command <command>] [--json]
|
|
158
164
|
speckit session start|checkpoint|compact|resume|status [target] [--note "..."] [--json]
|
|
159
165
|
speckit sprint plan|next [--json]
|
|
160
|
-
speckit graph triage|plan|insights [--json]
|
|
166
|
+
speckit graph setup|triage|plan|insights [--json]
|
|
161
167
|
speckit validate [--json]
|
|
162
168
|
speckit triage [--json]
|
|
163
169
|
speckit next
|
package/dist/commands/doctor.js
CHANGED
|
@@ -6,8 +6,10 @@ import { detectTestCommands } from "../core/test-detection.js";
|
|
|
6
6
|
import { coreFiles, enterpriseFiles } from "../core/scaffold.js";
|
|
7
7
|
import { agentFiles } from "../core/agent-scaffold.js";
|
|
8
8
|
import { validateWorkflowContract } from "../core/workflow-validator.js";
|
|
9
|
+
import { createColors } from "../core/colors.js";
|
|
9
10
|
export async function doctorCommand(options) {
|
|
10
11
|
const stdout = options.stdout ?? console;
|
|
12
|
+
const colors = createColors();
|
|
11
13
|
const tools = checkTools();
|
|
12
14
|
const tests = await detectTestCommands(options.root);
|
|
13
15
|
const deepChecks = options.deep ? await runDeepChecks(options.root) : [];
|
|
@@ -29,18 +31,25 @@ export async function doctorCommand(options) {
|
|
|
29
31
|
stdout.log(JSON.stringify(report, null, 2));
|
|
30
32
|
}
|
|
31
33
|
else {
|
|
32
|
-
stdout.log(
|
|
33
|
-
stdout.log(
|
|
34
|
-
stdout.log(`Tools: ${tools.map((tool) => `${tool.name}=${tool.available
|
|
35
|
-
|
|
34
|
+
stdout.log(`${colors.bold("Speckit doctor")}: ${colors.status(report.status === "ok", "ok", report.status)}`);
|
|
35
|
+
stdout.log(`${colors.bold("Node")}: ${report.node}`);
|
|
36
|
+
stdout.log(`Tools: ${tools.map((tool) => `${tool.name}=${colors.status(tool.available)}`).join(", ")}`);
|
|
37
|
+
for (const tool of tools.filter((tool) => !tool.available)) {
|
|
38
|
+
stdout.log(`${colors.yellow("Tool hint")} ${tool.name}: ${tool.hint}`);
|
|
39
|
+
if (tool.install?.length) {
|
|
40
|
+
stdout.log(`${colors.cyan(`Install ${tool.name}`)}: ${tool.install.join(" OR ")}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
stdout.log(`${colors.bold("Tests")}: ${tests[0]?.command ?? colors.yellow("not detected")}`);
|
|
36
44
|
for (const check of deepChecks) {
|
|
37
|
-
stdout.log(`Deep ${check.name}: ${check.ok
|
|
45
|
+
stdout.log(`Deep ${check.name}: ${colors.status(check.ok)}`);
|
|
38
46
|
}
|
|
39
47
|
for (const check of contractChecks) {
|
|
40
|
-
stdout.log(`Contract ${check.name}: ${check.ok ? "ok" : check.detail}`);
|
|
48
|
+
stdout.log(`Contract ${check.name}: ${check.ok ? colors.green("ok") : colors.red(check.detail)}`);
|
|
41
49
|
}
|
|
42
50
|
for (const adapter of adapters) {
|
|
43
|
-
|
|
51
|
+
const ok = adapter.present === adapter.total;
|
|
52
|
+
stdout.log(`Adapter ${adapter.name}: ${colors.status(ok, `${adapter.present}/${adapter.total}`, `${adapter.present}/${adapter.total}`)} files present`);
|
|
44
53
|
}
|
|
45
54
|
}
|
|
46
55
|
return report.status === "ok" ? 0 : 1;
|
package/dist/commands/graph.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { spawnSync } from "node:child_process";
|
|
2
|
-
import { commandExists } from "../adapters/tool-checks.js";
|
|
2
|
+
import { beadsViewerInstallGuide, checkTools, commandExists } from "../adapters/tool-checks.js";
|
|
3
3
|
import { prepareBeadsMirror } from "../core/beads-mirror.js";
|
|
4
|
+
import { createColors } from "../core/colors.js";
|
|
4
5
|
import { readSyncedStories, selectableStories } from "../core/synced-stories.js";
|
|
5
6
|
const robotActions = new Map([
|
|
6
7
|
["triage", "--robot-triage"],
|
|
@@ -9,9 +10,12 @@ const robotActions = new Map([
|
|
|
9
10
|
]);
|
|
10
11
|
export async function graphCommand(options) {
|
|
11
12
|
const stdout = options.stdout ?? console;
|
|
13
|
+
if (options.action === "setup") {
|
|
14
|
+
return graphSetup(options);
|
|
15
|
+
}
|
|
12
16
|
const robotFlag = robotActions.get(options.action);
|
|
13
17
|
if (!robotFlag) {
|
|
14
|
-
stdout.error("Usage: speckit graph triage|plan|insights [--json]");
|
|
18
|
+
stdout.error("Usage: speckit graph setup|triage|plan|insights [--json]");
|
|
15
19
|
return 1;
|
|
16
20
|
}
|
|
17
21
|
if (commandExists("bv")) {
|
|
@@ -32,6 +36,30 @@ export async function graphCommand(options) {
|
|
|
32
36
|
stdout.log(JSON.stringify(fallback, null, 2));
|
|
33
37
|
return 0;
|
|
34
38
|
}
|
|
39
|
+
async function graphSetup(options) {
|
|
40
|
+
const stdout = options.stdout ?? console;
|
|
41
|
+
const colors = createColors();
|
|
42
|
+
const tools = checkTools().filter((tool) => ["br", "bd", "bv"].includes(tool.name));
|
|
43
|
+
const mirrorPath = await prepareBeadsMirror(options.root);
|
|
44
|
+
const report = {
|
|
45
|
+
status: tools.find((tool) => tool.name === "bv")?.available ? "ready" : "needs-bv",
|
|
46
|
+
mirror: mirrorPath,
|
|
47
|
+
tools,
|
|
48
|
+
install: beadsViewerInstallGuide(),
|
|
49
|
+
};
|
|
50
|
+
if (options.json) {
|
|
51
|
+
stdout.log(JSON.stringify(report, null, 2));
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
stdout.log(beadsViewerInstallGuide());
|
|
55
|
+
stdout.log("");
|
|
56
|
+
stdout.log(`${colors.bold("Mirror")}: ${colors.cyan(mirrorPath)}`);
|
|
57
|
+
for (const tool of tools) {
|
|
58
|
+
stdout.log(`${colors.bold(tool.name)}: ${colors.status(tool.available)} - ${colors.dim(tool.hint)}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return 0;
|
|
62
|
+
}
|
|
35
63
|
async function localGraphFallback(root, action) {
|
|
36
64
|
const stories = await readSyncedStories(root);
|
|
37
65
|
const selectable = selectableStories(stories);
|
|
@@ -46,6 +74,6 @@ async function localGraphFallback(root, action) {
|
|
|
46
74
|
top_pick: selectable[0] ?? null,
|
|
47
75
|
},
|
|
48
76
|
recommendations: selectable.slice(0, 3),
|
|
49
|
-
command: "Install Beads Viewer for graph metrics:
|
|
77
|
+
command: "Install Beads Viewer for graph metrics: brew install dicklesworthstone/tap/bv",
|
|
50
78
|
};
|
|
51
79
|
}
|
package/dist/commands/init.js
CHANGED
|
@@ -2,8 +2,10 @@ import { coreFiles, enterpriseFiles } from "../core/scaffold.js";
|
|
|
2
2
|
import { agentFiles } from "../core/agent-scaffold.js";
|
|
3
3
|
import { writeManagedFiles } from "../core/managed-files.js";
|
|
4
4
|
import { getAdapters } from "../config/adapter-registry.js";
|
|
5
|
+
import { createColors } from "../core/colors.js";
|
|
5
6
|
export async function initCommand(options) {
|
|
6
7
|
const stdout = options.stdout ?? console;
|
|
8
|
+
const colors = createColors();
|
|
7
9
|
const selectedIde = options.ide ?? "all";
|
|
8
10
|
const sharedFiles = [...coreFiles(), ...agentFiles()];
|
|
9
11
|
const baseFiles = options.enterprise ? [...sharedFiles, ...enterpriseFiles()] : sharedFiles;
|
|
@@ -13,9 +15,9 @@ export async function initCommand(options) {
|
|
|
13
15
|
const updated = results.filter((result) => result.status === "updated").length;
|
|
14
16
|
const skipped = results.filter((result) => result.status === "skipped");
|
|
15
17
|
const mode = options.enterprise ? "enterprise" : "standard";
|
|
16
|
-
stdout.log(
|
|
18
|
+
stdout.log(`${colors.bold("Speckit initialized")} (${colors.cyan(mode)}): ${colors.green(String(created))} created, ${colors.yellow(String(updated))} updated, ${colors.status(skipped.length === 0, String(skipped.length), String(skipped.length))} skipped.`);
|
|
17
19
|
for (const result of skipped) {
|
|
18
|
-
stdout.log(
|
|
20
|
+
stdout.log(`${colors.yellow("skipped")} ${result.path}: ${result.reason}`);
|
|
19
21
|
}
|
|
20
22
|
return skipped.length > 0 ? 2 : 0;
|
|
21
23
|
}
|
package/dist/commands/next.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { spawnSync } from "node:child_process";
|
|
2
|
-
import { commandExists } from "../adapters/tool-checks.js";
|
|
2
|
+
import { beadsViewerInstallGuide, commandExists } from "../adapters/tool-checks.js";
|
|
3
3
|
export async function nextCommand(options = {}) {
|
|
4
4
|
const stdout = options.stdout ?? console;
|
|
5
5
|
if (!commandExists("bv")) {
|
|
6
|
-
stdout.error(
|
|
6
|
+
stdout.error(`bv is not installed.\n\n${beadsViewerInstallGuide()}`);
|
|
7
7
|
return 1;
|
|
8
8
|
}
|
|
9
9
|
const result = spawnSync("bv", ["--robot-next", "--format", "json"], {
|
package/dist/commands/ready.js
CHANGED
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
import { evaluateReadiness } from "../core/readiness.js";
|
|
2
|
+
import { createColors } from "../core/colors.js";
|
|
2
3
|
export async function readyCommand(options) {
|
|
3
4
|
const stdout = options.stdout ?? console;
|
|
5
|
+
const colors = createColors();
|
|
4
6
|
const report = await evaluateReadiness(options.root, options.target);
|
|
5
7
|
if (options.json) {
|
|
6
8
|
stdout.log(JSON.stringify(report, null, 2));
|
|
7
9
|
return report.status === "ready" ? 0 : 1;
|
|
8
10
|
}
|
|
9
|
-
stdout.log(`# Speckit Readiness: ${report.status}`);
|
|
11
|
+
stdout.log(`# ${colors.bold("Speckit Readiness")}: ${colors.status(report.status === "ready", "ready", report.status)}`);
|
|
10
12
|
if (report.story) {
|
|
11
|
-
stdout.log(
|
|
13
|
+
stdout.log(`${colors.bold("Story")}: ${colors.cyan(report.story.path)}`);
|
|
12
14
|
}
|
|
13
15
|
for (const check of report.checks) {
|
|
14
|
-
stdout.log(`- ${check.ok
|
|
16
|
+
stdout.log(`- ${colors.status(check.ok, "ok", "blocked")} ${check.name}: ${check.detail}`);
|
|
15
17
|
}
|
|
16
18
|
if (report.status !== "ready") {
|
|
17
|
-
stdout.error("Run the suggested setup commands before `speckit run`.");
|
|
19
|
+
stdout.error(colors.yellow("Run the suggested setup commands before `speckit run`."));
|
|
18
20
|
}
|
|
19
21
|
return report.status === "ready" ? 0 : 1;
|
|
20
22
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Readable, Writable } from "node:stream";
|
|
2
|
+
export type SetupOptions = {
|
|
3
|
+
root: string;
|
|
4
|
+
answers?: string[];
|
|
5
|
+
stdin?: Readable;
|
|
6
|
+
output?: Writable;
|
|
7
|
+
stdout?: Pick<typeof console, "log" | "error">;
|
|
8
|
+
};
|
|
9
|
+
export declare function setupCommand(options: SetupOptions): Promise<number>;
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { createInterface } from "node:readline/promises";
|
|
2
|
+
import { adapters } from "../config/adapter-registry.js";
|
|
3
|
+
import { createColors } from "../core/colors.js";
|
|
4
|
+
import { graphCommand } from "./graph.js";
|
|
5
|
+
import { initCommand } from "./init.js";
|
|
6
|
+
const modeChoices = [
|
|
7
|
+
{ label: "Enterprise Agile + TDD harness", value: "enterprise" },
|
|
8
|
+
{ label: "Standard Agile + TDD runtime", value: "standard" },
|
|
9
|
+
];
|
|
10
|
+
const ideChoices = [
|
|
11
|
+
{ label: "All supported IDEs", value: "all" },
|
|
12
|
+
...adapters.map((adapter) => ({
|
|
13
|
+
label: adapter.displayName,
|
|
14
|
+
value: adapter.name,
|
|
15
|
+
})),
|
|
16
|
+
];
|
|
17
|
+
export async function setupCommand(options) {
|
|
18
|
+
const stdin = options.stdin ?? process.stdin;
|
|
19
|
+
const output = options.output ?? process.stdout;
|
|
20
|
+
const stdout = options.stdout ?? console;
|
|
21
|
+
const colors = createColors(output);
|
|
22
|
+
if (options.answers) {
|
|
23
|
+
return setupFromAnswers(options, stdout, options.answers);
|
|
24
|
+
}
|
|
25
|
+
if (!stdin.isTTY || !output.isTTY) {
|
|
26
|
+
stdout.error("Interactive setup requires a TTY. Use `speckit init --enterprise --ide all` for non-interactive setup.");
|
|
27
|
+
return 1;
|
|
28
|
+
}
|
|
29
|
+
const rl = createInterface({ input: stdin, output });
|
|
30
|
+
try {
|
|
31
|
+
stdout.log(colors.bold(colors.cyan("Speckit setup")));
|
|
32
|
+
stdout.log("");
|
|
33
|
+
const mode = await select(rl, stdout, modeChoices, "Choose setup mode", "1", colors);
|
|
34
|
+
const ide = await select(rl, stdout, ideChoices, "Choose IDE adapter", "1", colors);
|
|
35
|
+
const force = await confirm(rl, stdout, "Overwrite unmanaged files if needed?", false, colors);
|
|
36
|
+
const configureGraph = await confirm(rl, stdout, "Run Beads Viewer setup after init?", true, colors);
|
|
37
|
+
stdout.log("");
|
|
38
|
+
stdout.log(colors.dim(`Selected: ${mode}, ide=${ide}, force=${force ? "yes" : "no"}, graph=${configureGraph ? "yes" : "no"}`));
|
|
39
|
+
stdout.log("");
|
|
40
|
+
const initExit = await initCommand({
|
|
41
|
+
root: options.root,
|
|
42
|
+
ide,
|
|
43
|
+
enterprise: mode === "enterprise",
|
|
44
|
+
force,
|
|
45
|
+
stdout,
|
|
46
|
+
});
|
|
47
|
+
if (configureGraph) {
|
|
48
|
+
stdout.log("");
|
|
49
|
+
await graphCommand({ root: options.root, action: "setup", stdout });
|
|
50
|
+
}
|
|
51
|
+
return initExit;
|
|
52
|
+
}
|
|
53
|
+
finally {
|
|
54
|
+
rl.close();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async function setupFromAnswers(options, stdout, answers) {
|
|
58
|
+
const colors = createColors();
|
|
59
|
+
stdout.log(colors.bold(colors.cyan("Speckit setup")));
|
|
60
|
+
stdout.log("");
|
|
61
|
+
const mode = selectAnswer(stdout, modeChoices, "Choose setup mode", "1", answers.shift(), colors);
|
|
62
|
+
const ide = selectAnswer(stdout, ideChoices, "Choose IDE adapter", "1", answers.shift(), colors);
|
|
63
|
+
const force = confirmAnswer("Overwrite unmanaged files if needed?", false, answers.shift());
|
|
64
|
+
const configureGraph = confirmAnswer("Run Beads Viewer setup after init?", true, answers.shift());
|
|
65
|
+
stdout.log("");
|
|
66
|
+
stdout.log(colors.dim(`Selected: ${mode}, ide=${ide}, force=${force ? "yes" : "no"}, graph=${configureGraph ? "yes" : "no"}`));
|
|
67
|
+
stdout.log("");
|
|
68
|
+
const initExit = await initCommand({
|
|
69
|
+
root: options.root,
|
|
70
|
+
ide,
|
|
71
|
+
enterprise: mode === "enterprise",
|
|
72
|
+
force,
|
|
73
|
+
stdout,
|
|
74
|
+
});
|
|
75
|
+
if (configureGraph) {
|
|
76
|
+
stdout.log("");
|
|
77
|
+
await graphCommand({ root: options.root, action: "setup", stdout });
|
|
78
|
+
}
|
|
79
|
+
return initExit;
|
|
80
|
+
}
|
|
81
|
+
function selectAnswer(stdout, choices, prompt, defaultValue, answer, colors = createColors()) {
|
|
82
|
+
stdout.log(colors.bold(prompt));
|
|
83
|
+
choices.forEach((choice, index) => stdout.log(` ${colors.cyan(String(index + 1))}. ${choice.label}`));
|
|
84
|
+
const selected = (answer?.trim() || defaultValue);
|
|
85
|
+
const index = Number.parseInt(selected, 10) - 1;
|
|
86
|
+
if (!Number.isInteger(index) || !choices[index]) {
|
|
87
|
+
throw new Error(`Invalid selection: ${selected}`);
|
|
88
|
+
}
|
|
89
|
+
stdout.log("");
|
|
90
|
+
return choices[index].value;
|
|
91
|
+
}
|
|
92
|
+
function confirmAnswer(prompt, defaultValue, answer) {
|
|
93
|
+
const selected = answer?.trim().toLowerCase();
|
|
94
|
+
if (!selected)
|
|
95
|
+
return defaultValue;
|
|
96
|
+
if (["y", "yes"].includes(selected))
|
|
97
|
+
return true;
|
|
98
|
+
if (["n", "no"].includes(selected))
|
|
99
|
+
return false;
|
|
100
|
+
throw new Error(`Invalid yes/no answer for "${prompt}": ${answer}`);
|
|
101
|
+
}
|
|
102
|
+
async function select(rl, stdout, choices, prompt, defaultValue, colors = createColors()) {
|
|
103
|
+
for (;;) {
|
|
104
|
+
stdout.log(colors.bold(prompt));
|
|
105
|
+
choices.forEach((choice, index) => {
|
|
106
|
+
const number = String(index + 1);
|
|
107
|
+
stdout.log(` ${colors.cyan(number)}. ${choice.label}`);
|
|
108
|
+
});
|
|
109
|
+
const answer = (await rl.question(`${colors.dim("Select")} [${colors.cyan(defaultValue)}]: `)).trim() || defaultValue;
|
|
110
|
+
const index = Number.parseInt(answer, 10) - 1;
|
|
111
|
+
if (Number.isInteger(index) && choices[index]) {
|
|
112
|
+
stdout.log("");
|
|
113
|
+
return choices[index].value;
|
|
114
|
+
}
|
|
115
|
+
stdout.log(colors.red(`Invalid selection: ${answer}`));
|
|
116
|
+
stdout.log("");
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
async function confirm(rl, stdout, prompt, defaultValue, colors = createColors()) {
|
|
120
|
+
const suffix = defaultValue ? "Y/n" : "y/N";
|
|
121
|
+
for (;;) {
|
|
122
|
+
const answer = (await rl.question(`${prompt} [${colors.cyan(suffix)}]: `)).trim().toLowerCase();
|
|
123
|
+
if (!answer)
|
|
124
|
+
return defaultValue;
|
|
125
|
+
if (["y", "yes"].includes(answer))
|
|
126
|
+
return true;
|
|
127
|
+
if (["n", "no"].includes(answer))
|
|
128
|
+
return false;
|
|
129
|
+
stdout.log(colors.yellow("Please answer y or n."));
|
|
130
|
+
}
|
|
131
|
+
}
|
package/dist/commands/sync.js
CHANGED
|
@@ -3,8 +3,10 @@ import { join } from "node:path";
|
|
|
3
3
|
import { markdown, writeManagedFiles } from "../core/managed-files.js";
|
|
4
4
|
import { firstHeading, frontmatterValue } from "../core/story.js";
|
|
5
5
|
import { writeBeadsMirror } from "../core/beads-mirror.js";
|
|
6
|
+
import { createColors } from "../core/colors.js";
|
|
6
7
|
export async function syncCommand(options) {
|
|
7
8
|
const stdout = options.stdout ?? console;
|
|
9
|
+
const colors = createColors();
|
|
8
10
|
const storiesDir = join(options.root, ".speckit", "stories");
|
|
9
11
|
let entries;
|
|
10
12
|
try {
|
|
@@ -45,7 +47,7 @@ bv --robot-next --format json
|
|
|
45
47
|
},
|
|
46
48
|
], true);
|
|
47
49
|
const beadsPath = await writeBeadsMirror(options.root, stories);
|
|
48
|
-
stdout.log(`Synced ${stories.length} stories to .speckit/sync/beads-sync.jsonl`);
|
|
49
|
-
stdout.log(`Prepared Beads Viewer mirror at ${beadsPath}`);
|
|
50
|
+
stdout.log(`Synced ${colors.cyan(String(stories.length))} stories to ${colors.cyan(".speckit/sync/beads-sync.jsonl")}`);
|
|
51
|
+
stdout.log(`Prepared Beads Viewer mirror at ${colors.cyan(beadsPath)}`);
|
|
50
52
|
return 0;
|
|
51
53
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { validateWorkflowContract } from "../core/workflow-validator.js";
|
|
2
|
+
import { createColors } from "../core/colors.js";
|
|
2
3
|
export async function validateCommand(options) {
|
|
3
4
|
const stdout = options.stdout ?? console;
|
|
5
|
+
const colors = createColors();
|
|
4
6
|
const checks = await validateWorkflowContract(options.root);
|
|
5
7
|
const status = checks.every((check) => check.ok) ? "ok" : "needs-attention";
|
|
6
8
|
const report = { status, checks };
|
|
@@ -8,9 +10,9 @@ export async function validateCommand(options) {
|
|
|
8
10
|
stdout.log(JSON.stringify(report, null, 2));
|
|
9
11
|
}
|
|
10
12
|
else {
|
|
11
|
-
stdout.log(
|
|
13
|
+
stdout.log(`${colors.bold("Speckit workflow contract")}: ${colors.status(status === "ok", "ok", status)}`);
|
|
12
14
|
for (const check of checks) {
|
|
13
|
-
stdout.log(`${check.ok
|
|
15
|
+
stdout.log(`${colors.status(check.ok, "ok", "fail")} ${check.name}: ${check.detail}`);
|
|
14
16
|
}
|
|
15
17
|
}
|
|
16
18
|
return status === "ok" ? 0 : 1;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
type ColorOutput = {
|
|
2
|
+
isTTY?: boolean;
|
|
3
|
+
};
|
|
4
|
+
type ColorName = "blue" | "cyan" | "dim" | "green" | "red" | "yellow" | "bold";
|
|
5
|
+
export type Colors = Record<ColorName, (text: string) => string> & {
|
|
6
|
+
enabled: boolean;
|
|
7
|
+
status(ok: boolean, okText?: string, failText?: string): string;
|
|
8
|
+
};
|
|
9
|
+
export declare function createColors(output?: ColorOutput): Colors;
|
|
10
|
+
export declare function colorsEnabled(output?: ColorOutput): boolean;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const ansi = {
|
|
2
|
+
blue: [34, 39],
|
|
3
|
+
cyan: [36, 39],
|
|
4
|
+
dim: [2, 22],
|
|
5
|
+
green: [32, 39],
|
|
6
|
+
red: [31, 39],
|
|
7
|
+
yellow: [33, 39],
|
|
8
|
+
bold: [1, 22],
|
|
9
|
+
};
|
|
10
|
+
export function createColors(output) {
|
|
11
|
+
const enabled = colorsEnabled(output);
|
|
12
|
+
const style = (name) => (text) => {
|
|
13
|
+
if (!enabled)
|
|
14
|
+
return text;
|
|
15
|
+
const [open, close] = ansi[name];
|
|
16
|
+
return `\u001B[${open}m${text}\u001B[${close}m`;
|
|
17
|
+
};
|
|
18
|
+
return {
|
|
19
|
+
enabled,
|
|
20
|
+
blue: style("blue"),
|
|
21
|
+
cyan: style("cyan"),
|
|
22
|
+
dim: style("dim"),
|
|
23
|
+
green: style("green"),
|
|
24
|
+
red: style("red"),
|
|
25
|
+
yellow: style("yellow"),
|
|
26
|
+
bold: style("bold"),
|
|
27
|
+
status(ok, okText = "ok", failText = "missing") {
|
|
28
|
+
return ok ? this.green(okText) : this.red(failText);
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export function colorsEnabled(output) {
|
|
33
|
+
if (process.env.NO_COLOR || process.env.SPECKIT_COLOR === "0")
|
|
34
|
+
return false;
|
|
35
|
+
if (process.env.FORCE_COLOR === "0")
|
|
36
|
+
return false;
|
|
37
|
+
if (process.env.FORCE_COLOR || process.env.SPECKIT_COLOR === "1")
|
|
38
|
+
return true;
|
|
39
|
+
return output?.isTTY ?? process.stdout.isTTY ?? false;
|
|
40
|
+
}
|
package/docs/adapters.md
CHANGED
|
@@ -25,3 +25,24 @@ Speckit never invokes bare `bv`. The `next` command calls:
|
|
|
25
25
|
```bash
|
|
26
26
|
bv --robot-next --format json
|
|
27
27
|
```
|
|
28
|
+
|
|
29
|
+
Run this once on a new machine to see install commands and prepare the graph mirror:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
speckit graph setup
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Common `bv` installs:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
brew install dicklesworthstone/tap/bv
|
|
39
|
+
go install github.com/Dicklesworthstone/beads_viewer/cmd/bv@latest
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Graph wrappers use robot mode:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
speckit graph triage --json
|
|
46
|
+
speckit graph plan --json
|
|
47
|
+
speckit graph insights --json
|
|
48
|
+
```
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
<!-- speckit:managed -->
|
|
2
|
+
# Beads Viewer Setup
|
|
3
|
+
|
|
4
|
+
Speckit works without Beads Viewer by falling back to local JSON. Install `bv` when you want graph-aware prioritization, bottleneck detection, critical path analysis, and robot-mode planning.
|
|
5
|
+
|
|
6
|
+
## Install `bv`
|
|
7
|
+
|
|
8
|
+
Recommended on macOS/Linux:
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
brew install dicklesworthstone/tap/bv
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Go install:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
go install github.com/Dicklesworthstone/beads_viewer/cmd/bv@latest
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Nix:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
nix run github:Dicklesworthstone/beads_viewer -- --help
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Verify With Speckit
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
speckit graph setup
|
|
30
|
+
speckit sync
|
|
31
|
+
speckit graph triage --json
|
|
32
|
+
speckit next
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
`speckit graph setup` prepares `.beads/beads.jsonl` from Speckit stories and reports whether `bv` is available.
|
|
36
|
+
|
|
37
|
+
## Agent Safety Rule
|
|
38
|
+
|
|
39
|
+
Do not run bare `bv` from an agent session. Bare `bv` opens the interactive TUI. Use:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
speckit graph triage --json
|
|
43
|
+
speckit graph plan --json
|
|
44
|
+
speckit graph insights --json
|
|
45
|
+
bv --robot-triage --format json
|
|
46
|
+
bv --robot-next --format json
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Data Flow
|
|
50
|
+
|
|
51
|
+
```text
|
|
52
|
+
.speckit/stories/*.md
|
|
53
|
+
-> speckit sync
|
|
54
|
+
-> .speckit/sync/beads-sync.jsonl
|
|
55
|
+
-> .beads/beads.jsonl
|
|
56
|
+
-> bv --robot-* or Speckit graph wrappers
|
|
57
|
+
```
|
|
58
|
+
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
Speckit MVP is implemented and pushed to `git@github.com:trieungoctam/speckit.git` on `main`.
|
|
6
6
|
|
|
7
|
-
Current package target: `@trieungoctam/speckit@0.3.
|
|
7
|
+
Current package target: `@trieungoctam/speckit@0.3.5`.
|
|
8
8
|
|
|
9
9
|
The CLI is npx-ready, generates Agile + TDD rules, creates workflow artifacts, supports five IDE adapters, wraps Beads Viewer safely, includes an enterprise harness, and has automated prompt/readiness/session tests plus CI.
|
|
10
10
|
|
|
@@ -13,11 +13,11 @@ The CLI is npx-ready, generates Agile + TDD rules, creates workflow artifacts, s
|
|
|
13
13
|
| Milestone | Status | Notes |
|
|
14
14
|
| --- | --- | --- |
|
|
15
15
|
| Product contract | Complete | Contract, workflow model, and command surface documented. |
|
|
16
|
-
| CLI scaffold | Complete | `bin/speckit`, TypeScript build, command router, managed file writer. |
|
|
16
|
+
| CLI scaffold | Complete | `bin/speckit`, TypeScript build, command router, interactive setup wizard, managed file writer. |
|
|
17
17
|
| Workflow engine | Complete | `start`, `shape`, `plan`, `context`, `quick`, `sync`, `triage`, `ready`, `run`, `review`, and `close` generate linked artifacts. |
|
|
18
18
|
| Long session manager | Complete | `memory refresh` plus `session start/checkpoint/compact/resume/status` preserve agent continuity outside chat history. |
|
|
19
19
|
| IDE adapters | Complete | Claude Code, Codex, Antigravity, OpenCode, Cursor. |
|
|
20
|
-
| Beads integration | MVP Complete | `next` and `graph triage/plan/insights` wrap BV robot mode; `sync` exports story metadata JSONL. |
|
|
20
|
+
| Beads integration | MVP Complete | `graph setup` prints install commands and prepares `.beads/beads.jsonl`; `next` and `graph triage/plan/insights` wrap BV robot mode; `sync` exports story metadata JSONL. |
|
|
21
21
|
| Sprint automation | MVP Complete | `sprint plan` and `sprint next` select work from synced stories. |
|
|
22
22
|
| Enterprise harness | MVP Complete | `init --enterprise` creates flow, tool-policy, and prompt harness files; `doctor --deep` verifies them. |
|
|
23
23
|
| Curated skill catalog | Complete | Speckit now generates focused phase skills, a schema, delegation statuses, and task hydration/sync-back guidance. |
|
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# Project Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.6 - 2026-05-11
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Added ANSI color rendering for interactive CLI and TUI output, including setup prompts, init summaries, doctor checks, graph setup, readiness, validation, sync, and help headers.
|
|
8
|
+
- Added `SPECKIT_COLOR=1` / `FORCE_COLOR` support for demos and snapshots, with `NO_COLOR` / `SPECKIT_COLOR=0` opt-out support.
|
|
9
|
+
|
|
10
|
+
### Quality
|
|
11
|
+
|
|
12
|
+
- Added color helper regression tests.
|
|
13
|
+
- JSON output remains uncolored for automation.
|
|
14
|
+
|
|
15
|
+
## 0.3.5 - 2026-05-11
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- Added `speckit setup`, an interactive TUI wizard for setup mode, IDE adapter, overwrite policy, and optional Beads Viewer setup.
|
|
20
|
+
- Added `speckit graph setup` to print Beads Viewer install commands, check `br`/`bd`/`bv`, and prepare `.beads/beads.jsonl`.
|
|
21
|
+
- Added `docs/beads-viewer-setup.md` with Homebrew, Go, and Nix setup paths plus robot-safe verification commands.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- `speckit doctor` now prints install hints for missing tools.
|
|
26
|
+
- `speckit next` now prints concrete Beads Viewer setup guidance when `bv` is missing.
|
|
27
|
+
- README and workflow docs now include the graph setup step.
|
|
28
|
+
|
|
3
29
|
## 0.3.4 - 2026-05-11
|
|
4
30
|
|
|
5
31
|
### Fixed
|
package/docs/use-cases.md
CHANGED
|
@@ -6,6 +6,16 @@ This guide shows how to use Speckit for common product and engineering workflows
|
|
|
6
6
|
|
|
7
7
|
Use when a repository does not have Speckit runtime files yet.
|
|
8
8
|
|
|
9
|
+
Interactive:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npx @trieungoctam/speckit@latest setup
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
The wizard asks for setup mode, IDE adapter, overwrite policy, and whether to run Beads Viewer setup.
|
|
16
|
+
|
|
17
|
+
Scripted:
|
|
18
|
+
|
|
9
19
|
```bash
|
|
10
20
|
npx @trieungoctam/speckit@latest init --enterprise --ide cursor
|
|
11
21
|
npx @trieungoctam/speckit@latest doctor --deep
|
|
@@ -131,6 +141,7 @@ Use when multiple stories exist and the next task is not obvious.
|
|
|
131
141
|
|
|
132
142
|
```bash
|
|
133
143
|
speckit sync
|
|
144
|
+
speckit graph setup
|
|
134
145
|
speckit sprint plan
|
|
135
146
|
speckit sprint next --json
|
|
136
147
|
speckit graph triage --json
|
|
@@ -141,6 +152,7 @@ speckit graph insights --json
|
|
|
141
152
|
Best practices:
|
|
142
153
|
|
|
143
154
|
- Run `sync` before any graph command.
|
|
155
|
+
- Run `graph setup` on new machines to print Beads Viewer install commands, check `bv`, and prepare `.beads/beads.jsonl`.
|
|
144
156
|
- Keep graph commands robot-safe. Use Speckit wrappers instead of interactive graph commands.
|
|
145
157
|
- Treat graph output as prioritization input, not automatic permission to implement.
|
|
146
158
|
- Re-run `sprint plan` when story status or dependencies change.
|
package/docs/workflow-model.md
CHANGED
|
@@ -70,3 +70,5 @@ Long-running agent work must keep durable state outside chat history:
|
|
|
70
70
|
## Beads Viewer Automation
|
|
71
71
|
|
|
72
72
|
`speckit sync` prepares both Speckit sync metadata and a Beads Viewer-compatible `.beads/beads.jsonl` mirror. `speckit graph triage|plan|insights` refreshes that mirror before invoking `bv --robot-*` from the project root, then falls back to local JSON if Beads Viewer is unavailable or still fails.
|
|
73
|
+
|
|
74
|
+
Run `speckit graph setup` on a new machine to print Beads Viewer install commands, check `br`/`bd`/`bv`, and prepare `.beads/beads.jsonl`.
|