forge-cc 0.1.2 → 0.1.4
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/dist/setup/templates.d.ts +14 -0
- package/dist/setup/templates.js +158 -0
- package/dist/setup/templates.js.map +1 -0
- package/hooks/version-check.js +78 -0
- package/package.json +1 -1
- package/skills/forge-go.md +8 -9
- package/skills/forge-setup.md +157 -0
- package/skills/forge-update.md +72 -0
|
@@ -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,158 @@
|
|
|
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 END (Mandatory)
|
|
47
|
+
1. \`.planning/STATE.md\` — replace, don't append
|
|
48
|
+
2. \`.planning/ROADMAP.md\` — check off completed milestones
|
|
49
|
+
3. \`tasks/lessons.md\` — add/refine lessons (max 10, promote when full)
|
|
50
|
+
4. Commit doc updates to the feature branch
|
|
51
|
+
|
|
52
|
+
## Execution Rules
|
|
53
|
+
- **Plan before building.** Read the PRD before touching code.
|
|
54
|
+
- **Delegate immediately.** 3+ files or 3+ steps → spawn agent team.
|
|
55
|
+
- **Verify everything.** Run \`npx forge verify\` after changes land.
|
|
56
|
+
- **All changes via PR.** Never commit directly to main.
|
|
57
|
+
- **Branch naming:** \`feat/short-description\` or \`fix/short-description\`
|
|
58
|
+
|
|
59
|
+
## Verification Gates
|
|
60
|
+
Active gates: ${gatesList}
|
|
61
|
+
|
|
62
|
+
## Learned Rules
|
|
63
|
+
(none yet)
|
|
64
|
+
`;
|
|
65
|
+
}
|
|
66
|
+
// ── .planning/STATE.md ──────────────────────────────────────────────
|
|
67
|
+
export function stateMdTemplate(ctx) {
|
|
68
|
+
return `# State — ${ctx.projectName}
|
|
69
|
+
|
|
70
|
+
## Current Status
|
|
71
|
+
- **Phase:** Setup complete
|
|
72
|
+
- **Active project:** None
|
|
73
|
+
- **Branch:** main
|
|
74
|
+
|
|
75
|
+
## What Was Done
|
|
76
|
+
- Initialized forge-cc scaffolding (${ctx.date})
|
|
77
|
+
- Created .forge.json, CLAUDE.md, planning docs
|
|
78
|
+
|
|
79
|
+
## Next Actions
|
|
80
|
+
- Run \`/forge:spec\` to create a PRD for the first feature
|
|
81
|
+
`;
|
|
82
|
+
}
|
|
83
|
+
// ── .planning/ROADMAP.md ────────────────────────────────────────────
|
|
84
|
+
export function roadmapMdTemplate(ctx) {
|
|
85
|
+
return `# Roadmap — ${ctx.projectName}
|
|
86
|
+
|
|
87
|
+
## Projects
|
|
88
|
+
|
|
89
|
+
| Project | Status | PRD | Milestones |
|
|
90
|
+
|---------|--------|-----|------------|
|
|
91
|
+
| (none yet) | — | — | — |
|
|
92
|
+
|
|
93
|
+
## Completed
|
|
94
|
+
(none yet)
|
|
95
|
+
`;
|
|
96
|
+
}
|
|
97
|
+
// ── tasks/lessons.md ────────────────────────────────────────────────
|
|
98
|
+
export function lessonsMdTemplate(ctx) {
|
|
99
|
+
return `# Lessons Learned — ${ctx.projectName}
|
|
100
|
+
|
|
101
|
+
<!-- Max 10 active one-liners. Format: - **[topic]** The rule -->
|
|
102
|
+
<!-- When full, promote the most battle-tested to CLAUDE.md ## Learned Rules -->
|
|
103
|
+
|
|
104
|
+
(none yet)
|
|
105
|
+
`;
|
|
106
|
+
}
|
|
107
|
+
// ── ~/.claude/CLAUDE.md (global, for fresh installs) ────────────────
|
|
108
|
+
export function globalClaudeMdTemplate() {
|
|
109
|
+
return `# Global Claude Code Instructions
|
|
110
|
+
|
|
111
|
+
## Autonomous Execution Mode
|
|
112
|
+
|
|
113
|
+
- **Default to action.** Plan internally, execute immediately, verify results.
|
|
114
|
+
- **Use agent teams** for non-trivial work (3+ files or 3+ steps).
|
|
115
|
+
- **Don't ask questions** unless truly blocked on: missing credentials, ambiguous business logic, or destructive actions on shared infrastructure. **Exception:** Always honor AskUserQuestion prompts defined in skills — those are workflow inputs, not questions.
|
|
116
|
+
- **Make mistakes and iterate.** If something breaks, fix it.
|
|
117
|
+
- **Summarize after completion**, not during.
|
|
118
|
+
|
|
119
|
+
## Session Protocol
|
|
120
|
+
|
|
121
|
+
Fresh context per phase. Memory lives in the repo, not the conversation.
|
|
122
|
+
|
|
123
|
+
- **On start:** Read CLAUDE.md → STATE.md → ROADMAP.md → lessons files
|
|
124
|
+
- **On finish (MANDATORY — work is not done without these):**
|
|
125
|
+
1. Update \`.planning/STATE.md\` — replace, don't append, <80 lines
|
|
126
|
+
2. Update \`.planning/ROADMAP.md\` — check off completed items
|
|
127
|
+
3. Update \`tasks/lessons.md\` — max 10 one-liners, promote to CLAUDE.md Learned Rules when full (max 15)
|
|
128
|
+
4. Commit and push doc updates on the feature branch
|
|
129
|
+
5. Write handoff summary
|
|
130
|
+
- **Fresh sessions preferred** over long sessions with context bloat
|
|
131
|
+
- **When lost:** Re-read planning docs rather than guessing from stale context
|
|
132
|
+
|
|
133
|
+
## Verification (Mandatory)
|
|
134
|
+
|
|
135
|
+
- Never mark a task complete without proving it works
|
|
136
|
+
- Build must pass. Tests must pass. No exceptions.
|
|
137
|
+
- Run tests, check logs, demonstrate correctness
|
|
138
|
+
- If verification fails, fix it and re-verify
|
|
139
|
+
|
|
140
|
+
## Lessons System
|
|
141
|
+
|
|
142
|
+
- **\`tasks/lessons.md\`**: max 10 active one-liners
|
|
143
|
+
- **\`CLAUDE.md ## Learned Rules\`**: max 15 permanent one-liners (promoted from lessons.md)
|
|
144
|
+
- **When to write:** After any correction, and when agents hit issues
|
|
145
|
+
|
|
146
|
+
## Core Principles
|
|
147
|
+
|
|
148
|
+
- **Simplicity First:** Make every change as simple as possible.
|
|
149
|
+
- **No Laziness:** Find root causes. No temporary fixes.
|
|
150
|
+
- **Minimal Impact:** Changes should only touch what's necessary.
|
|
151
|
+
`;
|
|
152
|
+
}
|
|
153
|
+
// ── .gitignore lines ────────────────────────────────────────────────
|
|
154
|
+
export function gitignoreForgeLines() {
|
|
155
|
+
return `.forge/
|
|
156
|
+
`;
|
|
157
|
+
}
|
|
158
|
+
//# 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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gBAkCtD,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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0CR,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
package/skills/forge-go.md
CHANGED
|
@@ -6,9 +6,11 @@ Execute milestones from your PRD with wave-based agent teams, self-healing verif
|
|
|
6
6
|
|
|
7
7
|
Follow these steps exactly. The execution engine at `src/go/executor.ts` provides the programmatic logic — this skill drives the agent orchestration.
|
|
8
8
|
|
|
9
|
-
### Step 1 — Orient
|
|
9
|
+
### Step 1 — Orient + Choose Mode
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
**This step has two parts. Complete BOTH before moving to Step 2. Do NOT read any other files, do NOT start pre-flight checks, do NOT read the PRD until both parts are done.**
|
|
12
|
+
|
|
13
|
+
**Part A — Read state (only these 3 files, nothing else):**
|
|
12
14
|
|
|
13
15
|
```
|
|
14
16
|
Read these files in parallel:
|
|
@@ -32,15 +34,12 @@ If all milestones are complete:
|
|
|
32
34
|
|
|
33
35
|
> All milestones complete! Create a PR with `gh pr create` or run `/forge:spec` to start a new project.
|
|
34
36
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
**STOP. Do NOT proceed to Step 2 until this step is complete.**
|
|
37
|
+
**Part B — Ask execution mode (MANDATORY — do this IMMEDIATELY after Part A):**
|
|
38
38
|
|
|
39
|
-
If `--auto` was passed as an argument, set mode to auto and skip the prompt
|
|
39
|
+
If `--auto` was passed as an argument, set mode to auto and skip the prompt.
|
|
40
40
|
|
|
41
|
-
Otherwise
|
|
41
|
+
Otherwise: **your very next tool call MUST be AskUserQuestion.** No file reads, no git commands, no exploration — ask the user first. Use exactly these parameters:
|
|
42
42
|
|
|
43
|
-
Use AskUserQuestion with exactly these parameters:
|
|
44
43
|
- question: "How should this project be executed?"
|
|
45
44
|
- header: "Mode"
|
|
46
45
|
- options:
|
|
@@ -48,7 +47,7 @@ Use AskUserQuestion with exactly these parameters:
|
|
|
48
47
|
- label: "Auto (all milestones)", description: "Chain all remaining milestones with fresh context between each. After each milestone, prints a continuation prompt for the next session."
|
|
49
48
|
- multiSelect: false
|
|
50
49
|
|
|
51
|
-
**Wait for the user's response before continuing.**
|
|
50
|
+
**Wait for the user's response before continuing.** Do not proceed to Step 2 until you have their answer. Store the choice for Step 8 (Route Next).
|
|
52
51
|
|
|
53
52
|
### Step 2 — Pre-flight Checks
|
|
54
53
|
|
|
@@ -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.
|