forge-delegate 1.0.5 → 1.0.7
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.mjs +11 -6
- package/package.json +1 -1
- package/server.mjs +32 -3
- package/skills/delegate-work/SKILL.md +24 -1
package/cli.mjs
CHANGED
|
@@ -48,15 +48,20 @@ function installClaudeSkill(scope, projectDir) {
|
|
|
48
48
|
console.log(` \u2713 delegate-work skill (${dest})`);
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
// `claude mcp` writes .mcp.json relative to its own cwd, so a project-scope install
|
|
52
|
+
// must run from projectDir — otherwise it lands in whatever directory setup was
|
|
53
|
+
// invoked from, and installClaudeSkill (which does honour projectDir) disagrees
|
|
54
|
+
// with it.
|
|
55
|
+
function registerClaude(launch, scope, projectDir) {
|
|
56
|
+
const opts = scope === "project" ? { cwd: projectDir } : {};
|
|
52
57
|
try {
|
|
53
|
-
execSync(`claude mcp remove --scope ${scope} forge-delegate`, { stdio: "ignore" });
|
|
58
|
+
execSync(`claude mcp remove --scope ${scope} forge-delegate`, { ...opts, stdio: "ignore" });
|
|
54
59
|
} catch {}
|
|
55
60
|
try {
|
|
56
|
-
execSync(`claude mcp remove forge-delegate`, { stdio: "ignore" });
|
|
61
|
+
execSync(`claude mcp remove forge-delegate`, { ...opts, stdio: "ignore" });
|
|
57
62
|
} catch {}
|
|
58
|
-
execSync(`claude mcp add --scope ${scope} forge-delegate -- ${launch}`, { stdio: "inherit" });
|
|
59
|
-
console.log(` ✓ Claude Code (scope=${scope})`);
|
|
63
|
+
execSync(`claude mcp add --scope ${scope} forge-delegate -- ${launch}`, { ...opts, stdio: "inherit" });
|
|
64
|
+
console.log(` ✓ Claude Code (scope=${scope}${scope === "project" ? `, ${projectDir}` : ""})`);
|
|
60
65
|
}
|
|
61
66
|
|
|
62
67
|
function codexConfigPath(scope, projectDir) {
|
|
@@ -139,7 +144,7 @@ async function setup() {
|
|
|
139
144
|
for (const target of targets) {
|
|
140
145
|
try {
|
|
141
146
|
if (target === "claude") {
|
|
142
|
-
registerClaude(launch, scope);
|
|
147
|
+
registerClaude(launch, scope, projectDir);
|
|
143
148
|
if (!flags["no-skill"]) installClaudeSkill(scope, projectDir);
|
|
144
149
|
}
|
|
145
150
|
else if (target === "codex") registerCodex(launchArr, scope, projectDir);
|
package/package.json
CHANGED
package/server.mjs
CHANGED
|
@@ -27,6 +27,33 @@ const RUNS_DIR = join(homedir(), ".forge-delegate", "runs");
|
|
|
27
27
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
28
28
|
const VERSION = JSON.parse(readFileSync(join(here, "package.json"), "utf8")).version;
|
|
29
29
|
|
|
30
|
+
// The server auto-updates (npx re-resolves latest on each spawn) but the installed
|
|
31
|
+
// skill is a file on disk that only `setup` rewrites — so a published skill change
|
|
32
|
+
// goes unnoticed. Compare the two and say so, rather than running stale in silence.
|
|
33
|
+
function skillStatus() {
|
|
34
|
+
const src = join(here, "skills", "delegate-work", "SKILL.md");
|
|
35
|
+
if (!existsSync(src)) return null;
|
|
36
|
+
const dests = [
|
|
37
|
+
join(homedir(), ".claude", "skills", "delegate-work", "SKILL.md"),
|
|
38
|
+
join(process.cwd(), ".claude", "skills", "delegate-work", "SKILL.md"),
|
|
39
|
+
];
|
|
40
|
+
const installed = dests.filter(existsSync);
|
|
41
|
+
if (!installed.length) return { state: "missing", detail: "not installed" };
|
|
42
|
+
const want = readFileSync(src, "utf8");
|
|
43
|
+
const stale = installed.filter((d) => readFileSync(d, "utf8") !== want);
|
|
44
|
+
return stale.length
|
|
45
|
+
? { state: "stale", detail: `out of date: ${stale.join(", ")}` }
|
|
46
|
+
: { state: "ok", detail: "up to date" };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const SKILL_STATUS = skillStatus();
|
|
50
|
+
if (SKILL_STATUS && SKILL_STATUS.state !== "ok") {
|
|
51
|
+
// stderr only — stdout is the JSON-RPC channel.
|
|
52
|
+
process.stderr.write(
|
|
53
|
+
`forge-delegate: delegate-work skill ${SKILL_STATUS.detail}. Run: npx -y forge-delegate setup\n`
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
30
57
|
const INSTRUCTIONS = `forge-delegate hands coding work to cheap external models running as full agents. They read the project and write the code in their own loop, so the work never passes through your context. Spend your context on judgment; delegate the typing.
|
|
31
58
|
|
|
32
59
|
DELEGATE BY DEFAULT — do not hand-write these yourself:
|
|
@@ -37,8 +64,9 @@ DELEGATE BY DEFAULT — do not hand-write these yourself:
|
|
|
37
64
|
- Ports and translations between languages, frameworks, or file formats.
|
|
38
65
|
- The same edit repeated across 3 or more files.
|
|
39
66
|
- Reading a large file or directory to answer one narrow question — delegate the reading, keep your context clean.
|
|
67
|
+
- The survey half of an audit ("does this follow X standards", "is this secure", "where is the tech debt", "how does X work"). Delegate the gathering, keep the verdict: ask for a structured digest with a file path behind every claim, then judge it yourself. A claim with no path is not a finding.
|
|
40
68
|
|
|
41
|
-
KEEP FOR YOURSELF: architecture, debugging an unknown root cause, security-sensitive code, anything where being wrong is expensive, and the
|
|
69
|
+
KEEP FOR YOURSELF: architecture, debugging an unknown root cause, security-sensitive code, anything where being wrong is expensive, and the verdict on whatever comes back. Delegation does not transfer responsibility for the result.
|
|
42
70
|
|
|
43
71
|
Routing:
|
|
44
72
|
- One-shot question, no file access needed -> ask_model.
|
|
@@ -162,7 +190,7 @@ server.tool(
|
|
|
162
190
|
|
|
163
191
|
server.tool(
|
|
164
192
|
"delegate",
|
|
165
|
-
"USE THIS INSTEAD OF WRITING THE CODE YOURSELF when the task is: tests for code that already exists; a mechanical refactor (rename, signature change, import rewrite, API migration); fixing lint/type/build errors; boilerplate or scaffolding (CRUD endpoints, config, schemas, adapters, fixtures); a port between languages or frameworks; the same edit repeated across 3 or more files;
|
|
193
|
+
"USE THIS INSTEAD OF WRITING THE CODE YOURSELF when the task is: tests for code that already exists; a mechanical refactor (rename, signature change, import rewrite, API migration); fixing lint/type/build errors; boilerplate or scaffolding (CRUD endpoints, config, schemas, adapters, fixtures); a port between languages or frameworks; the same edit repeated across 3 or more files; reading a large file/directory to answer one narrow question; or the survey half of an audit (delegate the gathering, keep the verdict — demand a file path behind every claim). Hands the task to another AI model running as a full agent via local opencode: it reads your project, explores, and writes concrete code in its own tool loop — none of which enters your context. Keep architecture, unknown-root-cause debugging, and security-sensitive code for yourself, and always review what comes back. Runs INLINE by default (result returned when done; Claude Code auto-backgrounds calls past 2 minutes). Pass background:true to run detached and get a job id instantly, then poll check_delegation — use that for parallel fan-out or hosts that block on long calls. Pass continue_session (returned by a previous delegation) to keep the same agent session instead of re-exploring. Never paste file contents into task: name the paths and let the agent read them. model/directory/agent/autoApprove default from config — omit them.",
|
|
166
194
|
{
|
|
167
195
|
model: z.string().optional().describe("provider/model format, e.g. opencode/mimo-v2.5-free (defaults to config defaultModel)"),
|
|
168
196
|
task: z.string(),
|
|
@@ -243,7 +271,8 @@ server.tool(
|
|
|
243
271
|
const { profiles, ...rest } = cfg;
|
|
244
272
|
const lines = Object.entries(rest).map(([k, v]) => ` ${k}: ${v ?? "(unset)"}`);
|
|
245
273
|
const prof = Object.entries(profiles).map(([k, v]) => ` ${k}: ${JSON.stringify(v)}`).join("\n") || " (none)";
|
|
246
|
-
|
|
274
|
+
const skill = SKILL_STATUS ? `\nskill (delegate-work): ${SKILL_STATUS.detail}${SKILL_STATUS.state === "ok" ? "" : " — run: npx -y forge-delegate setup"}` : "";
|
|
275
|
+
return { content: [{ type: "text", text: `config: ${configPath()}\n${lines.join("\n")}\nprofiles:\n${prof}${skill}` }] };
|
|
247
276
|
}
|
|
248
277
|
);
|
|
249
278
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: delegate-work
|
|
3
|
-
description: Hand a coding task to a cheap external model via forge-delegate instead of writing it yourself. Load BEFORE starting work that is high-volume and low-judgment - writing tests for code that already exists, mechanical refactors (renames, signature changes, import rewrites, API migrations), fixing lint/type/build errors, boilerplate and scaffolding (CRUD endpoints, config files, schemas, adapters, fixtures), porting code between languages or frameworks, the same edit repeated across 3 or more files, or reading a large file or directory to answer one narrow question. Triggers on - "write tests for", "add tests", "rename X to Y everywhere", "refactor", "migrate", "port this to", "fix the lint errors", "fix the type errors", "scaffold", "boilerplate", "do the same for the other files".
|
|
3
|
+
description: Hand a coding task to a cheap external model via forge-delegate instead of writing it yourself. Load BEFORE starting work that is high-volume and low-judgment - writing tests for code that already exists, mechanical refactors (renames, signature changes, import rewrites, API migrations), fixing lint/type/build errors, boilerplate and scaffolding (CRUD endpoints, config files, schemas, adapters, fixtures), porting code between languages or frameworks, the same edit repeated across 3 or more files, or reading a large file or directory to answer one narrow question. ALSO load for audit and survey questions - "does my codebase follow X", "audit", "review the architecture", "is this idiomatic", "where is the tech debt", "is this secure", "explore the codebase", "how does X work", "find where" - where the reading is wide but the judgment is narrow: delegate the survey, keep the verdict. Triggers on - "write tests for", "add tests", "rename X to Y everywhere", "refactor", "migrate", "port this to", "fix the lint errors", "fix the type errors", "scaffold", "boilerplate", "do the same for the other files".
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Delegating work to a cheap model
|
|
@@ -30,6 +30,28 @@ answer is already known, and the work is typing it out across files.
|
|
|
30
30
|
Delegating does not transfer responsibility. Review what comes back before you
|
|
31
31
|
report it as done.
|
|
32
32
|
|
|
33
|
+
## Delegate the survey, keep the verdict
|
|
34
|
+
|
|
35
|
+
An audit looks like judgment work, so it reads as "keep" — but only the *verdict* is
|
|
36
|
+
judgment. The input gathering is mechanical, wide, and the single most expensive
|
|
37
|
+
thing you can do to your own context. Split them:
|
|
38
|
+
|
|
39
|
+
1. **Delegate the survey.** Ask for a structured digest, not an opinion:
|
|
40
|
+
"Report which framework this repo uses. List every routing and data-fetching
|
|
41
|
+
entry point: path, 3-line summary. Paths only, no assessment."
|
|
42
|
+
2. **Keep the verdict.** Judge the digest yourself. You are now reading a page
|
|
43
|
+
instead of a repo, and the expensive-if-wrong part never left your hands.
|
|
44
|
+
|
|
45
|
+
This covers "does this follow X standards", "is this secure", "where is the tech
|
|
46
|
+
debt", "how does X work", "explore the codebase" — broad read, narrow judgment.
|
|
47
|
+
|
|
48
|
+
**Demand paths as evidence.** A survey's worth depends on the cheap model reporting
|
|
49
|
+
*absence* honestly, and "there is no Next.js here" is exactly the answer a weak model
|
|
50
|
+
is least likely to give — it will produce a plausible audit of a framework you do not
|
|
51
|
+
use rather than contradict the question's premise. Require a file path for every
|
|
52
|
+
claim. A claim with no path attached is not a finding; spot-check two of them before
|
|
53
|
+
you trust the rest.
|
|
54
|
+
|
|
33
55
|
## Do it
|
|
34
56
|
|
|
35
57
|
1. Do the judgment part yourself first — decide the interface, write the first
|
|
@@ -58,4 +80,5 @@ second opinion — use `ask_model` instead; it is a direct API call with no agen
|
|
|
58
80
|
- Don't delegate a task you cannot describe precisely. Vague task, vague diff.
|
|
59
81
|
- Don't delegate and walk away. Unreviewed delegated code is worse than no code.
|
|
60
82
|
- Don't paste large files into the task text.
|
|
83
|
+
- Don't accept a survey finding with no file path behind it.
|
|
61
84
|
- Don't override `model` upward because a task "seems hard" — split it instead.
|