forge-cc 0.1.3 → 0.1.5
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 +47 -8
- package/dist/setup/templates.d.ts +14 -0
- package/dist/setup/templates.js +133 -0
- package/dist/setup/templates.js.map +1 -0
- package/hooks/version-check.js +78 -0
- package/package.json +1 -1
- package/skills/forge-setup.md +157 -0
- package/skills/forge-update.md +72 -0
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ Pre-PR verification harness and development workflow tool for Claude Code agents
|
|
|
8
8
|
|
|
9
9
|
- **Verification gates** -- runs TypeScript type-checking, linting, tests, visual screenshots, runtime endpoint validation, and PRD acceptance criteria checks against your project before you commit.
|
|
10
10
|
- **Mechanical enforcement** -- Claude Code PreToolUse hook and git pre-commit hook block commits that haven't passed verification. No discipline required; the machine enforces it.
|
|
11
|
-
- **Workflow skills** -- `/forge:triage` turns brain dumps into Linear projects, `/forge:spec` interviews you and generates a PRD with milestones, `/forge:go` executes milestones with wave-based agent teams.
|
|
11
|
+
- **Workflow skills** -- `/forge:triage` turns brain dumps into Linear projects, `/forge:spec` interviews you and generates a PRD with milestones, `/forge:go` executes milestones with wave-based agent teams, `/forge:setup` scaffolds new projects, `/forge:update` keeps forge-cc current.
|
|
12
12
|
- **Linear lifecycle** -- programmatic status transitions through Backlog, Planned, In Progress, In Review, and Done. Every skill keeps Linear in sync automatically.
|
|
13
13
|
|
|
14
14
|
## Quick Start
|
|
@@ -149,6 +149,32 @@ Add to your `.claude/settings.json`:
|
|
|
149
149
|
}
|
|
150
150
|
```
|
|
151
151
|
|
|
152
|
+
### Version Check Hook
|
|
153
|
+
|
|
154
|
+
Optional session hook that checks for forge-cc updates when Claude Code starts a task. Prints a one-line notice to stderr if a newer version is available. Never blocks execution.
|
|
155
|
+
|
|
156
|
+
Add to `.claude/settings.local.json`:
|
|
157
|
+
|
|
158
|
+
```json
|
|
159
|
+
{
|
|
160
|
+
"hooks": {
|
|
161
|
+
"PreToolUse": [
|
|
162
|
+
{
|
|
163
|
+
"matcher": "Task",
|
|
164
|
+
"hooks": [
|
|
165
|
+
{
|
|
166
|
+
"type": "command",
|
|
167
|
+
"command": "node node_modules/forge-cc/hooks/version-check.js"
|
|
168
|
+
}
|
|
169
|
+
]
|
|
170
|
+
}
|
|
171
|
+
]
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
`/forge:setup` installs this hook automatically.
|
|
177
|
+
|
|
152
178
|
### Git Pre-Commit Hook
|
|
153
179
|
|
|
154
180
|
Standard git hook for non-Claude-Code environments. Same four checks as the PreToolUse hook.
|
|
@@ -208,6 +234,18 @@ Execute the next pending milestone from your PRD with wave-based agent teams. Ea
|
|
|
208
234
|
|
|
209
235
|
**Flow:** Orient (read state) -> pre-flight checks -> execute waves -> verify -> update state -> (optional) create PR.
|
|
210
236
|
|
|
237
|
+
### `/forge:setup` -- Initialize or Refresh a Project
|
|
238
|
+
|
|
239
|
+
Bootstrap a new project with forge-cc scaffolding (`.forge.json`, `CLAUDE.md`, planning docs, hooks), or refresh an existing project's files to the latest templates while preserving your learned rules and lessons.
|
|
240
|
+
|
|
241
|
+
**Flow:** Detect project -> choose mode (Fresh/Refresh) -> configure gates -> create files -> patch global config -> install hooks -> summary.
|
|
242
|
+
|
|
243
|
+
### `/forge:update` -- Update Forge
|
|
244
|
+
|
|
245
|
+
Check for newer versions of forge-cc and install the latest. After updating, suggests running `/forge:setup` in Refresh mode to pick up new templates.
|
|
246
|
+
|
|
247
|
+
**Flow:** Check versions -> compare -> update via npm -> post-update check.
|
|
248
|
+
|
|
211
249
|
## Linear Integration
|
|
212
250
|
|
|
213
251
|
forge-cc manages the full Linear project lifecycle:
|
|
@@ -226,12 +264,12 @@ For a new developer joining the team:
|
|
|
226
264
|
|
|
227
265
|
1. **Clone the repo** that uses forge-cc.
|
|
228
266
|
2. **Install dependencies:** `npm install` (forge-cc should be in `devDependencies`).
|
|
229
|
-
3. **Run
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
267
|
+
3. **Run `/forge:setup`** -- scaffolds `.forge.json`, `CLAUDE.md`, planning docs, and installs hooks automatically. Or set up manually:
|
|
268
|
+
- `npx forge verify` to confirm your environment.
|
|
269
|
+
- Add the PreToolUse hook to `.claude/settings.json` (see Enforcement section).
|
|
270
|
+
- Create `.forge.json` if auto-detected gates don't match.
|
|
233
271
|
|
|
234
|
-
|
|
272
|
+
The gates run the same commands your CI does, so if `npx forge verify` passes locally, CI will pass too.
|
|
235
273
|
|
|
236
274
|
## Project Structure
|
|
237
275
|
|
|
@@ -249,8 +287,9 @@ forge-cc/
|
|
|
249
287
|
state/ # Session state reader/writer (STATE.md, ROADMAP.md)
|
|
250
288
|
spec/ # Spec interview engine + PRD generation
|
|
251
289
|
go/ # Execution engine + verify loop + PR creation
|
|
252
|
-
|
|
253
|
-
|
|
290
|
+
setup/ # Setup templates for project scaffolding
|
|
291
|
+
skills/ # Claude Code skill definitions (/forge:triage, /forge:spec, /forge:go, /forge:setup, /forge:update)
|
|
292
|
+
hooks/ # Installable hook files (PreToolUse, version-check)
|
|
254
293
|
tests/ # Test suite (vitest)
|
|
255
294
|
.forge.json # Default configuration
|
|
256
295
|
```
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface SetupContext {
|
|
2
|
+
projectName: string;
|
|
3
|
+
techStack: string;
|
|
4
|
+
description: string;
|
|
5
|
+
gates: string[];
|
|
6
|
+
date: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function forgeConfigTemplate(ctx: SetupContext): string;
|
|
9
|
+
export declare function claudeMdTemplate(ctx: SetupContext): string;
|
|
10
|
+
export declare function stateMdTemplate(ctx: SetupContext): string;
|
|
11
|
+
export declare function roadmapMdTemplate(ctx: SetupContext): string;
|
|
12
|
+
export declare function lessonsMdTemplate(ctx: SetupContext): string;
|
|
13
|
+
export declare function globalClaudeMdTemplate(): string;
|
|
14
|
+
export declare function gitignoreForgeLines(): string;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
// ── Setup Templates ─────────────────────────────────────────────────
|
|
2
|
+
// String template functions used by /forge:setup to scaffold project files.
|
|
3
|
+
// ── .forge.json ─────────────────────────────────────────────────────
|
|
4
|
+
export function forgeConfigTemplate(ctx) {
|
|
5
|
+
const config = {
|
|
6
|
+
gates: ctx.gates,
|
|
7
|
+
maxIterations: 5,
|
|
8
|
+
};
|
|
9
|
+
return JSON.stringify(config, null, 2) + "\n";
|
|
10
|
+
}
|
|
11
|
+
// ── Project CLAUDE.md ───────────────────────────────────────────────
|
|
12
|
+
export function claudeMdTemplate(ctx) {
|
|
13
|
+
const gatesList = ctx.gates.map((g) => `\`${g}\``).join(", ");
|
|
14
|
+
return `# ${ctx.projectName} — Claude Code Instructions
|
|
15
|
+
|
|
16
|
+
## What This Is
|
|
17
|
+
${ctx.description}
|
|
18
|
+
|
|
19
|
+
**Tech:** ${ctx.techStack}
|
|
20
|
+
|
|
21
|
+
## Quick Reference
|
|
22
|
+
|
|
23
|
+
| Action | Command |
|
|
24
|
+
|--------|---------|
|
|
25
|
+
| Run verification | \`npx forge verify\` |
|
|
26
|
+
| Run specific gates | \`npx forge verify --gate ${ctx.gates.join(",")}\` |
|
|
27
|
+
| Check status | \`npx forge status\` |
|
|
28
|
+
| Build | \`npm run build\` |
|
|
29
|
+
| Test | \`npm test\` |
|
|
30
|
+
|
|
31
|
+
## Code Map
|
|
32
|
+
|
|
33
|
+
\`\`\`
|
|
34
|
+
src/
|
|
35
|
+
(add your project structure here)
|
|
36
|
+
\`\`\`
|
|
37
|
+
|
|
38
|
+
## Key Docs
|
|
39
|
+
|
|
40
|
+
| File | Purpose |
|
|
41
|
+
|------|---------|
|
|
42
|
+
| \`.planning/STATE.md\` | Current session state (<80 lines) |
|
|
43
|
+
| \`.planning/ROADMAP.md\` | Milestone progress tracker |
|
|
44
|
+
| \`tasks/lessons.md\` | Lessons learned (max 10 active) |
|
|
45
|
+
|
|
46
|
+
## Session Protocol
|
|
47
|
+
- **On start:** Read CLAUDE.md → .planning/STATE.md → .planning/ROADMAP.md → tasks/lessons.md
|
|
48
|
+
- **When lost:** Re-read planning docs, don't guess from stale context
|
|
49
|
+
|
|
50
|
+
## Session Protocol END (Mandatory)
|
|
51
|
+
1. \`.planning/STATE.md\` — replace, don't append
|
|
52
|
+
2. \`.planning/ROADMAP.md\` — check off completed milestones
|
|
53
|
+
3. \`tasks/lessons.md\` — add/refine lessons (max 10, promote when full)
|
|
54
|
+
4. Commit doc updates to the feature branch
|
|
55
|
+
|
|
56
|
+
## Execution Rules
|
|
57
|
+
- **Plan before building.** Read the PRD before touching code.
|
|
58
|
+
- **Verify everything.** Run \`npx forge verify\` after changes land.
|
|
59
|
+
- **All changes via PR.** Never commit directly to main.
|
|
60
|
+
- **Branch naming:** \`feat/short-description\` or \`fix/short-description\`
|
|
61
|
+
|
|
62
|
+
## Verification Gates
|
|
63
|
+
Active gates: ${gatesList}
|
|
64
|
+
|
|
65
|
+
## Learned Rules
|
|
66
|
+
(none yet)
|
|
67
|
+
`;
|
|
68
|
+
}
|
|
69
|
+
// ── .planning/STATE.md ──────────────────────────────────────────────
|
|
70
|
+
export function stateMdTemplate(ctx) {
|
|
71
|
+
return `# State — ${ctx.projectName}
|
|
72
|
+
|
|
73
|
+
## Current Status
|
|
74
|
+
- **Phase:** Setup complete
|
|
75
|
+
- **Active project:** None
|
|
76
|
+
- **Branch:** main
|
|
77
|
+
|
|
78
|
+
## What Was Done
|
|
79
|
+
- Initialized forge-cc scaffolding (${ctx.date})
|
|
80
|
+
- Created .forge.json, CLAUDE.md, planning docs
|
|
81
|
+
|
|
82
|
+
## Next Actions
|
|
83
|
+
- Run \`/forge:spec\` to create a PRD for the first feature
|
|
84
|
+
`;
|
|
85
|
+
}
|
|
86
|
+
// ── .planning/ROADMAP.md ────────────────────────────────────────────
|
|
87
|
+
export function roadmapMdTemplate(ctx) {
|
|
88
|
+
return `# Roadmap — ${ctx.projectName}
|
|
89
|
+
|
|
90
|
+
## Projects
|
|
91
|
+
|
|
92
|
+
| Project | Status | PRD | Milestones |
|
|
93
|
+
|---------|--------|-----|------------|
|
|
94
|
+
| (none yet) | — | — | — |
|
|
95
|
+
|
|
96
|
+
## Completed
|
|
97
|
+
(none yet)
|
|
98
|
+
`;
|
|
99
|
+
}
|
|
100
|
+
// ── tasks/lessons.md ────────────────────────────────────────────────
|
|
101
|
+
export function lessonsMdTemplate(ctx) {
|
|
102
|
+
return `# Lessons Learned — ${ctx.projectName}
|
|
103
|
+
|
|
104
|
+
<!-- Max 10 active one-liners. Format: - **[topic]** The rule -->
|
|
105
|
+
<!-- When full, promote the most battle-tested to CLAUDE.md ## Learned Rules -->
|
|
106
|
+
|
|
107
|
+
(none yet)
|
|
108
|
+
`;
|
|
109
|
+
}
|
|
110
|
+
// ── ~/.claude/CLAUDE.md (global, for fresh installs) ────────────────
|
|
111
|
+
export function globalClaudeMdTemplate() {
|
|
112
|
+
return `# Global Claude Code Instructions
|
|
113
|
+
|
|
114
|
+
## How to Work
|
|
115
|
+
- **Follow instructions exactly.** Skills, CLAUDE.md rules, and workflow steps are tested — execute every step as written, including all AskUserQuestion prompts.
|
|
116
|
+
- **Default to action.** Don't ask for confirmation. Plan internally, execute, verify.
|
|
117
|
+
- **Iterate on failure.** Fix what breaks. Only stop to ask when truly blocked on missing credentials, ambiguous business requirements, or destructive actions on shared infrastructure.
|
|
118
|
+
- **Use agent teams** for non-trivial work (3+ files or 3+ steps).
|
|
119
|
+
|
|
120
|
+
## Verification
|
|
121
|
+
- Never mark complete without proving it works.
|
|
122
|
+
- Build and tests must pass. Run them.
|
|
123
|
+
|
|
124
|
+
## Principles
|
|
125
|
+
- Simple changes only. Find root causes. Touch only what's necessary.
|
|
126
|
+
`;
|
|
127
|
+
}
|
|
128
|
+
// ── .gitignore lines ────────────────────────────────────────────────
|
|
129
|
+
export function gitignoreForgeLines() {
|
|
130
|
+
return `.forge/
|
|
131
|
+
`;
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=templates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/setup/templates.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,4EAA4E;AAU5E,uEAAuE;AAEvE,MAAM,UAAU,mBAAmB,CAAC,GAAiB;IACnD,MAAM,MAAM,GAAG;QACb,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,aAAa,EAAE,CAAC;KACjB,CAAC;IACF,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;AAChD,CAAC;AAED,uEAAuE;AAEvE,MAAM,UAAU,gBAAgB,CAAC,GAAiB;IAChD,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAE9D,OAAO,KAAK,GAAG,CAAC,WAAW;;;EAG3B,GAAG,CAAC,WAAW;;YAEL,GAAG,CAAC,SAAS;;;;;;;mDAO0B,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gBAqCtD,SAAS;;;;CAIxB,CAAC;AACF,CAAC;AAED,uEAAuE;AAEvE,MAAM,UAAU,eAAe,CAAC,GAAiB;IAC/C,OAAO,aAAa,GAAG,CAAC,WAAW;;;;;;;;sCAQC,GAAG,CAAC,IAAI;;;;;CAK7C,CAAC;AACF,CAAC;AAED,uEAAuE;AAEvE,MAAM,UAAU,iBAAiB,CAAC,GAAiB;IACjD,OAAO,eAAe,GAAG,CAAC,WAAW;;;;;;;;;;CAUtC,CAAC;AACF,CAAC;AAED,uEAAuE;AAEvE,MAAM,UAAU,iBAAiB,CAAC,GAAiB;IACjD,OAAO,uBAAuB,GAAG,CAAC,WAAW;;;;;;CAM9C,CAAC;AACF,CAAC;AAED,uEAAuE;AAEvE,MAAM,UAAU,sBAAsB;IACpC,OAAO;;;;;;;;;;;;;;CAcR,CAAC;AACF,CAAC;AAED,uEAAuE;AAEvE,MAAM,UAAU,mBAAmB;IACjC,OAAO;CACR,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { execSync } from "node:child_process";
|
|
4
|
+
import { readFileSync } from "node:fs";
|
|
5
|
+
import { join, dirname } from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
|
|
8
|
+
// Read hook input from stdin
|
|
9
|
+
let input = "";
|
|
10
|
+
process.stdin.setEncoding("utf-8");
|
|
11
|
+
process.stdin.on("data", (chunk) => {
|
|
12
|
+
input += chunk;
|
|
13
|
+
});
|
|
14
|
+
process.stdin.on("end", () => {
|
|
15
|
+
try {
|
|
16
|
+
checkForUpdate();
|
|
17
|
+
} catch {
|
|
18
|
+
// Silent failure — never crash, never block
|
|
19
|
+
}
|
|
20
|
+
// Always exit cleanly with no output (allow session to proceed)
|
|
21
|
+
process.exit(0);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
function checkForUpdate() {
|
|
25
|
+
// Get installed version from forge-cc's own package.json
|
|
26
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
27
|
+
const pkgPath = join(__dirname, "..", "package.json");
|
|
28
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
29
|
+
const currentVersion = pkg.version;
|
|
30
|
+
|
|
31
|
+
if (!currentVersion) return;
|
|
32
|
+
|
|
33
|
+
// Query npm registry for latest version (5 second timeout)
|
|
34
|
+
let latestVersion;
|
|
35
|
+
try {
|
|
36
|
+
const result = execSync("npm view forge-cc version --json", {
|
|
37
|
+
encoding: "utf-8",
|
|
38
|
+
timeout: 5000,
|
|
39
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
40
|
+
});
|
|
41
|
+
latestVersion = JSON.parse(result);
|
|
42
|
+
} catch {
|
|
43
|
+
// Offline, npm slow, or package not published yet — skip silently
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (typeof latestVersion !== "string" || !latestVersion) return;
|
|
48
|
+
|
|
49
|
+
// Compare versions using semver-compatible numeric comparison
|
|
50
|
+
if (isOutdated(currentVersion, latestVersion)) {
|
|
51
|
+
process.stderr.write(
|
|
52
|
+
`[forge] Update available: v${currentVersion} → v${latestVersion}. Run /forge:update to upgrade.\n`
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Returns true if `current` is older than `latest`.
|
|
59
|
+
* Splits on ".", compares major/minor/patch numerically.
|
|
60
|
+
*/
|
|
61
|
+
function isOutdated(current, latest) {
|
|
62
|
+
const parseParts = (v) =>
|
|
63
|
+
v
|
|
64
|
+
.replace(/^v/, "")
|
|
65
|
+
.split(".")
|
|
66
|
+
.map((n) => parseInt(n, 10));
|
|
67
|
+
|
|
68
|
+
const cur = parseParts(current);
|
|
69
|
+
const lat = parseParts(latest);
|
|
70
|
+
|
|
71
|
+
for (let i = 0; i < 3; i++) {
|
|
72
|
+
const c = cur[i] || 0;
|
|
73
|
+
const l = lat[i] || 0;
|
|
74
|
+
if (l > c) return true;
|
|
75
|
+
if (c > l) return false;
|
|
76
|
+
}
|
|
77
|
+
return false;
|
|
78
|
+
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# /forge:setup — Initialize or Refresh a Forge Project
|
|
2
|
+
|
|
3
|
+
Bootstrap a new project with forge-cc scaffolding, or refresh an existing project's forge files to the latest templates. Creates `.forge.json`, `CLAUDE.md`, planning docs, and installs hooks.
|
|
4
|
+
|
|
5
|
+
## Instructions
|
|
6
|
+
|
|
7
|
+
Follow these steps exactly. Do not skip confirmation.
|
|
8
|
+
|
|
9
|
+
### Step 1 — Detect Project
|
|
10
|
+
|
|
11
|
+
Check the current directory for existing forge files:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
ls .forge.json CLAUDE.md .planning/STATE.md .planning/ROADMAP.md tasks/lessons.md 2>/dev/null
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Determine which files exist. This determines whether this is a fresh setup or a refresh.
|
|
18
|
+
|
|
19
|
+
- **If `.forge.json` exists:** This is an existing forge project → default to Refresh mode
|
|
20
|
+
- **If `.forge.json` does not exist:** This is a new project → default to Fresh Setup mode
|
|
21
|
+
|
|
22
|
+
### Step 2 — Choose Setup Mode
|
|
23
|
+
|
|
24
|
+
Present the detected mode and ask the user to confirm or override:
|
|
25
|
+
|
|
26
|
+
<AskUserQuestion>
|
|
27
|
+
question: "Detected {existing/new} forge project. Which mode?"
|
|
28
|
+
options:
|
|
29
|
+
- "Fresh Setup — scaffold all forge files from scratch"
|
|
30
|
+
- "Refresh — update existing files to latest templates (preserves Learned Rules and lessons)"
|
|
31
|
+
</AskUserQuestion>
|
|
32
|
+
|
|
33
|
+
**Fresh Setup** will create all files, overwriting any that exist.
|
|
34
|
+
**Refresh** will update templates while preserving:
|
|
35
|
+
- `CLAUDE.md` → keeps `## Learned Rules` section content
|
|
36
|
+
- `tasks/lessons.md` → keeps all existing lessons
|
|
37
|
+
- `.planning/STATE.md` → keeps current state
|
|
38
|
+
- `.planning/ROADMAP.md` → keeps current roadmap
|
|
39
|
+
|
|
40
|
+
### Step 3 — Configure Gates
|
|
41
|
+
|
|
42
|
+
Ask the user which verification gates to enable:
|
|
43
|
+
|
|
44
|
+
<AskUserQuestion>
|
|
45
|
+
question: "Which verification gates should be active?"
|
|
46
|
+
multiSelect: true
|
|
47
|
+
options:
|
|
48
|
+
- "types — TypeScript type checking (tsc --noEmit)"
|
|
49
|
+
- "lint — ESLint / Biome linting"
|
|
50
|
+
- "tests — Vitest / Jest test runner"
|
|
51
|
+
- "visual — Playwright screenshot regression"
|
|
52
|
+
- "runtime — Start the app and check for crashes"
|
|
53
|
+
- "prd — PRD completeness check"
|
|
54
|
+
</AskUserQuestion>
|
|
55
|
+
|
|
56
|
+
Default recommendation: `types`, `lint`, `tests`.
|
|
57
|
+
|
|
58
|
+
Also collect project metadata (skip in Refresh mode if `.forge.json` already has values):
|
|
59
|
+
|
|
60
|
+
<AskUserQuestion>
|
|
61
|
+
question: "Project name?"
|
|
62
|
+
</AskUserQuestion>
|
|
63
|
+
|
|
64
|
+
<AskUserQuestion>
|
|
65
|
+
question: "Tech stack? (e.g., TypeScript, React, Node.js)"
|
|
66
|
+
</AskUserQuestion>
|
|
67
|
+
|
|
68
|
+
<AskUserQuestion>
|
|
69
|
+
question: "One-line project description?"
|
|
70
|
+
</AskUserQuestion>
|
|
71
|
+
|
|
72
|
+
### Step 4 — Create or Update Files
|
|
73
|
+
|
|
74
|
+
Use the template functions from `forge-cc/src/setup/templates.ts` to generate file contents. The templates are:
|
|
75
|
+
|
|
76
|
+
- `forgeConfigTemplate(ctx)` → `.forge.json`
|
|
77
|
+
- `claudeMdTemplate(ctx)` → `CLAUDE.md`
|
|
78
|
+
- `stateMdTemplate(ctx)` → `.planning/STATE.md`
|
|
79
|
+
- `roadmapMdTemplate(ctx)` → `.planning/ROADMAP.md`
|
|
80
|
+
- `lessonsMdTemplate(ctx)` → `tasks/lessons.md`
|
|
81
|
+
- `gitignoreForgeLines()` → lines to append to `.gitignore`
|
|
82
|
+
|
|
83
|
+
**Fresh Setup mode:** Create all files. Create directories `.planning/` and `tasks/` if they don't exist. Append forge lines to `.gitignore` if not already present.
|
|
84
|
+
|
|
85
|
+
**Refresh mode:** Only overwrite `.forge.json` and the structural parts of `CLAUDE.md` (everything except `## Learned Rules`). Do NOT touch `STATE.md`, `ROADMAP.md`, or `lessons.md`.
|
|
86
|
+
|
|
87
|
+
Write the actual files using the Write tool. Do not just print them.
|
|
88
|
+
|
|
89
|
+
### Step 5 — Patch Global Config
|
|
90
|
+
|
|
91
|
+
Check if `~/.claude/CLAUDE.md` exists:
|
|
92
|
+
|
|
93
|
+
- **If it does not exist:** Create it using `globalClaudeMdTemplate()` from the templates.
|
|
94
|
+
- **If it exists:** Leave it alone. Do not overwrite the user's global config.
|
|
95
|
+
|
|
96
|
+
### Step 6 — Install Hooks
|
|
97
|
+
|
|
98
|
+
Check if the user has a `.claude/settings.json` or `.claude/settings.local.json` in the project:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
ls .claude/settings.json .claude/settings.local.json 2>/dev/null
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
If no settings file exists, create `.claude/settings.local.json` with the version-check hook:
|
|
105
|
+
|
|
106
|
+
```json
|
|
107
|
+
{
|
|
108
|
+
"hooks": {
|
|
109
|
+
"PreToolUse": [
|
|
110
|
+
{
|
|
111
|
+
"matcher": "Task",
|
|
112
|
+
"hooks": [
|
|
113
|
+
{
|
|
114
|
+
"type": "command",
|
|
115
|
+
"command": "node node_modules/forge-cc/hooks/version-check.js"
|
|
116
|
+
}
|
|
117
|
+
]
|
|
118
|
+
}
|
|
119
|
+
]
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
If a settings file already exists, inform the user:
|
|
125
|
+
|
|
126
|
+
> Settings file already exists. To add the version-check hook manually, add this to your hooks config:
|
|
127
|
+
> `"command": "node node_modules/forge-cc/hooks/version-check.js"`
|
|
128
|
+
|
|
129
|
+
### Step 7 — Summary
|
|
130
|
+
|
|
131
|
+
Print a summary of everything that was created or updated:
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
## Forge Setup Complete
|
|
135
|
+
|
|
136
|
+
**Mode:** {Fresh Setup / Refresh}
|
|
137
|
+
**Project:** {projectName}
|
|
138
|
+
**Gates:** {comma-separated list}
|
|
139
|
+
|
|
140
|
+
### Files Created/Updated
|
|
141
|
+
- .forge.json ✓
|
|
142
|
+
- CLAUDE.md ✓
|
|
143
|
+
- .planning/STATE.md ✓
|
|
144
|
+
- .planning/ROADMAP.md ✓
|
|
145
|
+
- tasks/lessons.md ✓
|
|
146
|
+
- .gitignore (forge lines) ✓
|
|
147
|
+
- .claude/settings.local.json ✓ (version-check hook)
|
|
148
|
+
|
|
149
|
+
### Next Steps
|
|
150
|
+
1. Review the generated `CLAUDE.md` and customize the Code Map section
|
|
151
|
+
2. Run `npx forge verify` to test your gate configuration
|
|
152
|
+
3. Run `/forge:spec` to create a PRD for your first feature
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
Do NOT commit or push. The user decides when to commit the scaffolded files.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# /forge:update — Update Forge to Latest Version
|
|
2
|
+
|
|
3
|
+
Check for updates and install the latest version of forge-cc.
|
|
4
|
+
|
|
5
|
+
## Instructions
|
|
6
|
+
|
|
7
|
+
### Step 1 — Check Versions
|
|
8
|
+
|
|
9
|
+
Run these commands to get version info:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# Current installed version
|
|
13
|
+
npm list -g forge-cc --json 2>/dev/null | node -e "const d=require('fs').readFileSync('/dev/stdin','utf8');const j=JSON.parse(d);console.log(j.dependencies?.['forge-cc']?.version||'not installed')"
|
|
14
|
+
|
|
15
|
+
# Latest available version
|
|
16
|
+
npm view forge-cc version
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Parse both versions. If the command fails, handle gracefully:
|
|
20
|
+
- If forge-cc is not installed globally: print "forge-cc is not installed globally. Install with: `npm install -g forge-cc`"
|
|
21
|
+
- If npm view fails (offline): print "Could not reach npm registry. Check your internet connection."
|
|
22
|
+
|
|
23
|
+
### Step 2 — Compare and Report
|
|
24
|
+
|
|
25
|
+
Print the version status:
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
## Forge Version Check
|
|
29
|
+
|
|
30
|
+
**Installed:** v{current}
|
|
31
|
+
**Latest:** v{latest}
|
|
32
|
+
**Status:** {Up to date / Update available}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
If already up to date, stop here with: "You're on the latest version."
|
|
36
|
+
|
|
37
|
+
### Step 3 — Update
|
|
38
|
+
|
|
39
|
+
If an update is available, run:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm install -g forge-cc@latest
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Verify the update succeeded:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npm list -g forge-cc --json 2>/dev/null | node -e "const d=require('fs').readFileSync('/dev/stdin','utf8');const j=JSON.parse(d);console.log(j.dependencies?.['forge-cc']?.version||'failed')"
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Step 4 — Post-Update Check
|
|
52
|
+
|
|
53
|
+
After updating, check if the current project's forge files need refreshing:
|
|
54
|
+
|
|
55
|
+
1. Check if `.forge.json` exists in the current directory
|
|
56
|
+
2. If it does (this is a forge project), suggest: "Run `/forge:setup` with Refresh mode to update project files to the latest templates."
|
|
57
|
+
3. If it doesn't, just confirm the update.
|
|
58
|
+
|
|
59
|
+
Print final summary:
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
## Update Complete
|
|
63
|
+
|
|
64
|
+
**Previous:** v{old}
|
|
65
|
+
**Current:** v{new}
|
|
66
|
+
|
|
67
|
+
{If forge project: "Consider running `/forge:setup` (Refresh) to update project files."}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
Do NOT stage, commit, or push anything. This skill only manages the npm package.
|