worclaude 2.0.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -3
- package/package.json +1 -1
- package/src/commands/delete.js +6 -9
- package/src/commands/diff.js +4 -5
- package/src/commands/doctor.js +159 -41
- package/src/commands/init.js +128 -102
- package/src/commands/status.js +4 -5
- package/src/commands/upgrade.js +6 -10
- package/src/core/config.js +11 -0
- package/src/utils/display.js +0 -9
- package/templates/agents/optional/quality/security-reviewer.md +3 -0
- package/templates/agents/universal/plan-reviewer.md +1 -0
- package/templates/agents/universal/test-writer.md +2 -0
- package/templates/agents/universal/verify-app.md +5 -0
- package/templates/core/memory-md.md +37 -0
- package/templates/skills/universal/claude-md-maintenance.md +23 -0
- package/templates/skills/universal/context-management.md +24 -0
- package/templates/skills/universal/coordinator-mode.md +20 -0
- package/templates/skills/universal/git-conventions.md +1 -0
- package/templates/skills/universal/planning-with-files.md +1 -0
- package/templates/skills/universal/prompt-engineering.md +1 -0
- package/templates/skills/universal/review-and-handoff.md +1 -0
- package/templates/skills/universal/security-checklist.md +1 -0
- package/templates/skills/universal/subagent-usage.md +1 -0
- package/templates/skills/universal/testing.md +1 -0
- package/templates/skills/universal/verification.md +1 -0
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
[Full Documentation](https://sefaertunc.github.io/Worclaude/) · [Interactive Demo](https://sefaertunc.github.io/Worclaude/demo/) · [npm](https://www.npmjs.com/package/worclaude)
|
|
12
12
|
|
|
13
|
-
Worclaude scaffolds a complete Claude Code workflow into any project in seconds. It implements all [tips by Boris Cherny](https://www.howborisusesclaudecode.com/) — the creator of Claude Code at Anthropic — as a reusable, upgradable scaffold. One `init` command gives you 25 agents, 16 slash commands,
|
|
13
|
+
Worclaude scaffolds a complete Claude Code workflow into any project in seconds. It implements all [tips by Boris Cherny](https://www.howborisusesclaudecode.com/) — the creator of Claude Code at Anthropic — as a reusable, upgradable scaffold. One `init` command gives you 25 agents, 16 slash commands, 15 skills, hooks, permissions, and a CLAUDE.md template tuned for your tech stack. Whether you're starting fresh or adding structure to an existing project, Worclaude handles the setup so you can focus on building.
|
|
14
14
|
|
|
15
15
|
---
|
|
16
16
|
|
|
@@ -26,9 +26,9 @@ Worclaude scaffolds a complete Claude Code workflow into any project in seconds.
|
|
|
26
26
|
**Slash Commands (16)**
|
|
27
27
|
`/start` `/end` `/commit-push-pr` `/review-plan` `/techdebt` `/verify` `/compact-safe` `/status` `/update-claude-md` `/setup` `/sync` `/conflict-resolver` `/review-changes` `/build-fix` `/refactor-clean` `/test-coverage`
|
|
28
28
|
|
|
29
|
-
**Skills (
|
|
29
|
+
**Skills (15)**
|
|
30
30
|
|
|
31
|
-
-
|
|
31
|
+
- 11 universal knowledge files (testing, git conventions, context management, security, coordinator mode, and more)
|
|
32
32
|
- 3 project-specific templates filled in by `/setup`
|
|
33
33
|
- 1 generated agent routing guide (dynamically built from your agent selection)
|
|
34
34
|
|
|
@@ -48,6 +48,45 @@ Worclaude scaffolds a complete Claude Code workflow into any project in seconds.
|
|
|
48
48
|
|
|
49
49
|
---
|
|
50
50
|
|
|
51
|
+
## What's New in v2.0.0
|
|
52
|
+
|
|
53
|
+
v2.0.0 is a major integration release. Skills and agents now register with Claude Code's runtime systems — they show up in `/skills` and `/agents`, not just as files on disk.
|
|
54
|
+
|
|
55
|
+
**Claude Code Runtime Integration**
|
|
56
|
+
|
|
57
|
+
- Skills use directory format (`skill-name/SKILL.md`) and register with `/skills`
|
|
58
|
+
- Agents include `description` frontmatter and register with `/agents`
|
|
59
|
+
- Run `worclaude doctor` to verify everything is wired up correctly
|
|
60
|
+
|
|
61
|
+
**Conditional Skills**
|
|
62
|
+
|
|
63
|
+
- 6 skills activate only when relevant files are touched (testing, security, frontend, backend, verification, project-patterns)
|
|
64
|
+
- 8 skills stay always-loaded for cross-cutting guidance
|
|
65
|
+
- Saves context window budget by keeping domain-specific guidance out of unrelated work
|
|
66
|
+
|
|
67
|
+
**Agent Enhancements**
|
|
68
|
+
|
|
69
|
+
- Read-only agents blocked from file modifications via `disallowedTools`
|
|
70
|
+
- Background execution for long-running agents (verify-app, build-validator, e2e-runner)
|
|
71
|
+
- Turn limits (`maxTurns`) prevent runaway token consumption
|
|
72
|
+
- Persistent memory for agents that learn across sessions (test-writer, security-reviewer, doc-writer)
|
|
73
|
+
|
|
74
|
+
**New Content**
|
|
75
|
+
|
|
76
|
+
- Coordinator-mode skill for multi-agent orchestration patterns
|
|
77
|
+
- Optional MEMORY.md template for Claude Code's memory system
|
|
78
|
+
- Enhanced verify-app agent with structured verdicts and adversarial probe requirements
|
|
79
|
+
- Per-tech-stack permission presets (16 languages)
|
|
80
|
+
|
|
81
|
+
**Upgrade Migration**
|
|
82
|
+
|
|
83
|
+
- `worclaude upgrade` auto-migrates v1.x projects: flat skills → directory format, agents get required frontmatter
|
|
84
|
+
- `worclaude doctor` detects old formats and missing fields
|
|
85
|
+
|
|
86
|
+
See the [Claude Code Integration guide](https://sefaertunc.github.io/Worclaude/guide/claude-code-integration) for technical details.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
51
90
|
## Quick Start
|
|
52
91
|
|
|
53
92
|
```bash
|
package/package.json
CHANGED
package/src/commands/delete.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import inquirer from 'inquirer';
|
|
3
3
|
import ora from 'ora';
|
|
4
|
-
import {
|
|
4
|
+
import { requireWorkflowMeta } from '../core/config.js';
|
|
5
5
|
import { createBackup } from '../core/backup.js';
|
|
6
6
|
import {
|
|
7
7
|
classifyClaudeFiles,
|
|
@@ -16,16 +16,13 @@ export async function deleteCommand() {
|
|
|
16
16
|
const projectRoot = process.cwd();
|
|
17
17
|
|
|
18
18
|
// Pre-flight: ensure worclaude is installed
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
display.info('Run `worclaude init` to set up
|
|
19
|
+
const { meta, error } = await requireWorkflowMeta(projectRoot);
|
|
20
|
+
if (error === 'not-installed') {
|
|
21
|
+
display.info('Workflow is not installed. Run `worclaude init` to set up.');
|
|
22
22
|
return;
|
|
23
23
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
if (!meta) {
|
|
27
|
-
display.error('workflow-meta.json is corrupted or unreadable.');
|
|
28
|
-
display.info('You may need to manually remove the .claude/ directory.');
|
|
24
|
+
if (error === 'corrupted') {
|
|
25
|
+
display.error('workflow-meta.json is corrupted. Run `worclaude init` to reinstall.');
|
|
29
26
|
return;
|
|
30
27
|
}
|
|
31
28
|
|
package/src/commands/diff.js
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { requireWorkflowMeta, getPackageVersion } from '../core/config.js';
|
|
2
2
|
import { categorizeFiles } from '../core/file-categorizer.js';
|
|
3
3
|
import * as display from '../utils/display.js';
|
|
4
4
|
|
|
5
5
|
export async function diffCommand() {
|
|
6
6
|
const projectRoot = process.cwd();
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
const { meta, error } = await requireWorkflowMeta(projectRoot);
|
|
9
|
+
if (error === 'not-installed') {
|
|
9
10
|
display.info('Workflow is not installed. Run `worclaude init` to set up.');
|
|
10
11
|
return;
|
|
11
12
|
}
|
|
12
|
-
|
|
13
|
-
const meta = await readWorkflowMeta(projectRoot);
|
|
14
|
-
if (!meta) {
|
|
13
|
+
if (error === 'corrupted') {
|
|
15
14
|
display.error('workflow-meta.json is corrupted. Run `worclaude init` to reinstall.');
|
|
16
15
|
return;
|
|
17
16
|
}
|
package/src/commands/doctor.js
CHANGED
|
@@ -177,59 +177,57 @@ async function checkAgents(projectRoot, meta) {
|
|
|
177
177
|
return results;
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
-
async function
|
|
180
|
+
async function readAgentFrontmatters(projectRoot) {
|
|
181
181
|
const agentsDir = path.join(projectRoot, '.claude', 'agents');
|
|
182
|
-
const results = [];
|
|
183
|
-
|
|
184
182
|
try {
|
|
185
183
|
const entries = await fs.readdir(agentsDir, { withFileTypes: true });
|
|
186
184
|
const mdFiles = entries.filter((e) => e.isFile() && e.name.endsWith('.md'));
|
|
187
|
-
|
|
185
|
+
const agents = [];
|
|
188
186
|
for (const file of mdFiles) {
|
|
189
|
-
const
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
`agents/${file.name}`,
|
|
199
|
-
'No YAML frontmatter — agent is invisible to Claude Code'
|
|
200
|
-
)
|
|
201
|
-
);
|
|
202
|
-
continue;
|
|
203
|
-
}
|
|
187
|
+
const content = await readFile(path.join(agentsDir, file.name));
|
|
188
|
+
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
189
|
+
agents.push({ name: file.name, frontmatter: match ? match[1] : null });
|
|
190
|
+
}
|
|
191
|
+
return agents;
|
|
192
|
+
} catch {
|
|
193
|
+
return [];
|
|
194
|
+
}
|
|
195
|
+
}
|
|
204
196
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
FAIL,
|
|
217
|
-
`agents/${file.name}`,
|
|
218
|
-
'Missing required "description" field — agent is invisible to Claude Code\'s /agents and routing'
|
|
219
|
-
)
|
|
220
|
-
);
|
|
221
|
-
}
|
|
197
|
+
async function checkAgentDescription(projectRoot) {
|
|
198
|
+
const agents = await readAgentFrontmatters(projectRoot);
|
|
199
|
+
if (agents.length === 0) return [];
|
|
200
|
+
|
|
201
|
+
const results = [];
|
|
202
|
+
for (const { name, frontmatter } of agents) {
|
|
203
|
+
if (!frontmatter) {
|
|
204
|
+
results.push(
|
|
205
|
+
result(FAIL, `agents/${name}`, 'No YAML frontmatter — agent is invisible to Claude Code')
|
|
206
|
+
);
|
|
207
|
+
continue;
|
|
222
208
|
}
|
|
223
209
|
|
|
224
|
-
|
|
210
|
+
const hasName = /^name:\s*.+/m.test(frontmatter);
|
|
211
|
+
const hasDescription = /^description:\s*.+/m.test(frontmatter);
|
|
212
|
+
|
|
213
|
+
if (!hasName) {
|
|
214
|
+
results.push(result(FAIL, `agents/${name}`, 'Missing required "name" field in frontmatter'));
|
|
215
|
+
} else if (!hasDescription) {
|
|
225
216
|
results.push(
|
|
226
|
-
result(
|
|
217
|
+
result(
|
|
218
|
+
FAIL,
|
|
219
|
+
`agents/${name}`,
|
|
220
|
+
'Missing required "description" field — agent is invisible to Claude Code\'s /agents and routing'
|
|
221
|
+
)
|
|
227
222
|
);
|
|
228
223
|
}
|
|
229
|
-
} catch {
|
|
230
|
-
// agents/ doesn't exist — covered by existing component checks
|
|
231
224
|
}
|
|
232
225
|
|
|
226
|
+
if (results.length === 0) {
|
|
227
|
+
results.push(
|
|
228
|
+
result(PASS, `agents/ frontmatter (${agents.length} agents have required fields)`, null)
|
|
229
|
+
);
|
|
230
|
+
}
|
|
233
231
|
return results;
|
|
234
232
|
}
|
|
235
233
|
|
|
@@ -385,6 +383,124 @@ async function checkDocSpecs(projectRoot) {
|
|
|
385
383
|
return results;
|
|
386
384
|
}
|
|
387
385
|
|
|
386
|
+
const AGENT_OPTIONAL_FIELDS = [
|
|
387
|
+
'model',
|
|
388
|
+
'isolation',
|
|
389
|
+
'maxTurns',
|
|
390
|
+
'disallowedTools',
|
|
391
|
+
'background',
|
|
392
|
+
'memory',
|
|
393
|
+
'skills',
|
|
394
|
+
'initialPrompt',
|
|
395
|
+
'criticalSystemReminder',
|
|
396
|
+
'omitClaudeMd',
|
|
397
|
+
];
|
|
398
|
+
|
|
399
|
+
async function checkAgentCompleteness(projectRoot) {
|
|
400
|
+
const agents = await readAgentFrontmatters(projectRoot);
|
|
401
|
+
const withFrontmatter = agents.filter((a) => a.frontmatter);
|
|
402
|
+
if (withFrontmatter.length === 0) return [];
|
|
403
|
+
|
|
404
|
+
let totalFields = 0;
|
|
405
|
+
const suggestions = [];
|
|
406
|
+
|
|
407
|
+
for (const { name, frontmatter } of withFrontmatter) {
|
|
408
|
+
let fieldCount = 0;
|
|
409
|
+
for (const field of AGENT_OPTIONAL_FIELDS) {
|
|
410
|
+
if (new RegExp(`^${field}:`, 'm').test(frontmatter)) fieldCount++;
|
|
411
|
+
}
|
|
412
|
+
totalFields += fieldCount;
|
|
413
|
+
|
|
414
|
+
const hasDisallowed = /^disallowedTools:/m.test(frontmatter);
|
|
415
|
+
const hasReminder = /^criticalSystemReminder:/m.test(frontmatter);
|
|
416
|
+
if (hasDisallowed && !hasReminder) {
|
|
417
|
+
suggestions.push(`${name}: read-only agent could benefit from criticalSystemReminder`);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
const totalPossible = withFrontmatter.length * AGENT_OPTIONAL_FIELDS.length;
|
|
422
|
+
const pct = Math.round((totalFields / totalPossible) * 100);
|
|
423
|
+
const results = [];
|
|
424
|
+
|
|
425
|
+
if (pct >= 50) {
|
|
426
|
+
results.push(
|
|
427
|
+
result(
|
|
428
|
+
PASS,
|
|
429
|
+
`Agent enrichment: ${pct}% optional fields used across ${withFrontmatter.length} agents`,
|
|
430
|
+
null
|
|
431
|
+
)
|
|
432
|
+
);
|
|
433
|
+
} else {
|
|
434
|
+
results.push(
|
|
435
|
+
result(
|
|
436
|
+
WARN,
|
|
437
|
+
`Agent enrichment: ${pct}% optional fields used across ${withFrontmatter.length} agents`,
|
|
438
|
+
'Run `worclaude upgrade` to add model, maxTurns, skills, and other metadata'
|
|
439
|
+
)
|
|
440
|
+
);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
for (const s of suggestions) {
|
|
444
|
+
results.push(result(WARN, s, null));
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
return results;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
async function checkClaudeMdSections(projectRoot) {
|
|
451
|
+
const claudeMdPath = path.join(projectRoot, 'CLAUDE.md');
|
|
452
|
+
const SECTION_THRESHOLD = 20000; // Only analyze sections if file > 20KB
|
|
453
|
+
const results = [];
|
|
454
|
+
|
|
455
|
+
try {
|
|
456
|
+
const content = await readFile(claudeMdPath);
|
|
457
|
+
if (content.length < SECTION_THRESHOLD) return results;
|
|
458
|
+
|
|
459
|
+
// Split into ## sections
|
|
460
|
+
const sections = [];
|
|
461
|
+
const lines = content.split('\n');
|
|
462
|
+
let currentHeading = '(top-level)';
|
|
463
|
+
let currentLines = [];
|
|
464
|
+
|
|
465
|
+
for (const line of lines) {
|
|
466
|
+
const headingMatch = line.match(/^##\s+(.+)/);
|
|
467
|
+
if (headingMatch) {
|
|
468
|
+
if (currentLines.length > 0) {
|
|
469
|
+
sections.push({ heading: currentHeading, size: currentLines.join('\n').length });
|
|
470
|
+
}
|
|
471
|
+
currentHeading = headingMatch[1];
|
|
472
|
+
currentLines = [];
|
|
473
|
+
} else {
|
|
474
|
+
currentLines.push(line);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
if (currentLines.length > 0) {
|
|
478
|
+
sections.push({ heading: currentHeading, size: currentLines.join('\n').length });
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// Sort by size, suggest extracting the top 3 sections > 2KB
|
|
482
|
+
const large = sections.filter((s) => s.size > 2000).sort((a, b) => b.size - a.size);
|
|
483
|
+
|
|
484
|
+
if (large.length > 0) {
|
|
485
|
+
const top = large.slice(0, 3);
|
|
486
|
+
const sectionList = top
|
|
487
|
+
.map((s) => `"${s.heading}" (${(s.size / 1024).toFixed(1)}KB)`)
|
|
488
|
+
.join(', ');
|
|
489
|
+
results.push(
|
|
490
|
+
result(
|
|
491
|
+
WARN,
|
|
492
|
+
`CLAUDE.md has large sections: ${sectionList}`,
|
|
493
|
+
'Consider extracting to conditional skills with paths frontmatter to save context budget'
|
|
494
|
+
)
|
|
495
|
+
);
|
|
496
|
+
}
|
|
497
|
+
} catch {
|
|
498
|
+
// Already covered by checkClaudeMd
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
return results;
|
|
502
|
+
}
|
|
503
|
+
|
|
388
504
|
async function checkPendingReviewFiles(projectRoot) {
|
|
389
505
|
const pending = [];
|
|
390
506
|
try {
|
|
@@ -429,6 +545,7 @@ export async function doctorCommand() {
|
|
|
429
545
|
|
|
430
546
|
printResult(await checkClaudeMd(projectRoot));
|
|
431
547
|
for (const r of await checkClaudeMdSize(projectRoot)) printResult(r);
|
|
548
|
+
for (const r of await checkClaudeMdSections(projectRoot)) printResult(r);
|
|
432
549
|
printResult(await checkSettingsJson(projectRoot));
|
|
433
550
|
printResult(await checkSessions(projectRoot));
|
|
434
551
|
display.newline();
|
|
@@ -440,6 +557,7 @@ export async function doctorCommand() {
|
|
|
440
557
|
for (const r of await checkCommands(projectRoot)) printResult(r);
|
|
441
558
|
for (const r of await checkSkills(projectRoot)) printResult(r);
|
|
442
559
|
for (const r of await checkSkillFormat(projectRoot)) printResult(r);
|
|
560
|
+
for (const r of await checkAgentCompleteness(projectRoot)) printResult(r);
|
|
443
561
|
display.newline();
|
|
444
562
|
|
|
445
563
|
// Docs
|
|
@@ -455,7 +573,7 @@ export async function doctorCommand() {
|
|
|
455
573
|
|
|
456
574
|
// Summary
|
|
457
575
|
if (metaResult.status === FAIL) {
|
|
458
|
-
display.
|
|
576
|
+
display.info('Workflow is not installed. Run `worclaude init` to set up.');
|
|
459
577
|
} else {
|
|
460
578
|
display.success('Doctor complete. Review any warnings above.');
|
|
461
579
|
}
|
package/src/commands/init.js
CHANGED
|
@@ -31,111 +31,137 @@ import { buildAgentRoutingSkill } from '../generators/agent-routing.js';
|
|
|
31
31
|
|
|
32
32
|
// --- Helper functions ---
|
|
33
33
|
|
|
34
|
+
const LANGUAGE_COMMANDS = {
|
|
35
|
+
python: {
|
|
36
|
+
heading: 'Python',
|
|
37
|
+
commands: [
|
|
38
|
+
'python -m pytest # Run tests',
|
|
39
|
+
'ruff check . # Lint',
|
|
40
|
+
'ruff format . # Format',
|
|
41
|
+
],
|
|
42
|
+
},
|
|
43
|
+
node: {
|
|
44
|
+
heading: 'Node.js / TypeScript',
|
|
45
|
+
commands: [
|
|
46
|
+
'npm test # Run tests',
|
|
47
|
+
'npx eslint . # Lint',
|
|
48
|
+
'npx prettier --write . # Format',
|
|
49
|
+
],
|
|
50
|
+
},
|
|
51
|
+
java: {
|
|
52
|
+
heading: 'Java',
|
|
53
|
+
commands: [
|
|
54
|
+
'mvn test # Run tests',
|
|
55
|
+
'mvn checkstyle:check # Lint',
|
|
56
|
+
'mvn spotless:apply # Format',
|
|
57
|
+
],
|
|
58
|
+
},
|
|
59
|
+
csharp: {
|
|
60
|
+
heading: 'C# / .NET',
|
|
61
|
+
commands: [
|
|
62
|
+
'dotnet test # Run tests',
|
|
63
|
+
'dotnet format --verify-no-changes # Lint',
|
|
64
|
+
'dotnet format # Format',
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
cpp: {
|
|
68
|
+
heading: 'C / C++',
|
|
69
|
+
commands: [
|
|
70
|
+
'cmake --build build && ctest # Build & test',
|
|
71
|
+
'clang-tidy src/*.cpp # Lint',
|
|
72
|
+
'clang-format -i src/*.[ch]pp # Format',
|
|
73
|
+
],
|
|
74
|
+
},
|
|
75
|
+
go: {
|
|
76
|
+
heading: 'Go',
|
|
77
|
+
commands: [
|
|
78
|
+
'go test ./... # Run tests',
|
|
79
|
+
'golangci-lint run # Lint',
|
|
80
|
+
'gofmt -w . # Format',
|
|
81
|
+
],
|
|
82
|
+
},
|
|
83
|
+
php: {
|
|
84
|
+
heading: 'PHP',
|
|
85
|
+
commands: [
|
|
86
|
+
'vendor/bin/phpunit # Run tests',
|
|
87
|
+
'vendor/bin/phpstan analyse # Lint',
|
|
88
|
+
'vendor/bin/php-cs-fixer fix . # Format',
|
|
89
|
+
],
|
|
90
|
+
},
|
|
91
|
+
ruby: {
|
|
92
|
+
heading: 'Ruby',
|
|
93
|
+
commands: [
|
|
94
|
+
'bundle exec rspec # Run tests',
|
|
95
|
+
'rubocop # Lint',
|
|
96
|
+
'rubocop -A # Format',
|
|
97
|
+
],
|
|
98
|
+
},
|
|
99
|
+
kotlin: {
|
|
100
|
+
heading: 'Kotlin',
|
|
101
|
+
commands: [
|
|
102
|
+
'gradle test # Run tests',
|
|
103
|
+
'detekt # Lint',
|
|
104
|
+
'ktlint -F # Format',
|
|
105
|
+
],
|
|
106
|
+
},
|
|
107
|
+
swift: {
|
|
108
|
+
heading: 'Swift',
|
|
109
|
+
commands: [
|
|
110
|
+
'swift test # Run tests',
|
|
111
|
+
'swiftlint # Lint',
|
|
112
|
+
'swift-format format -r . -i # Format',
|
|
113
|
+
],
|
|
114
|
+
},
|
|
115
|
+
rust: {
|
|
116
|
+
heading: 'Rust',
|
|
117
|
+
commands: [
|
|
118
|
+
'cargo test # Run tests',
|
|
119
|
+
'cargo clippy # Lint',
|
|
120
|
+
'cargo fmt # Format',
|
|
121
|
+
],
|
|
122
|
+
},
|
|
123
|
+
dart: {
|
|
124
|
+
heading: 'Dart / Flutter',
|
|
125
|
+
commands: [
|
|
126
|
+
'dart test # Run tests',
|
|
127
|
+
'dart analyze # Lint',
|
|
128
|
+
'dart format . # Format',
|
|
129
|
+
],
|
|
130
|
+
},
|
|
131
|
+
scala: {
|
|
132
|
+
heading: 'Scala',
|
|
133
|
+
commands: [
|
|
134
|
+
'sbt test # Run tests',
|
|
135
|
+
'sbt scalafix # Lint',
|
|
136
|
+
'scalafmt # Format',
|
|
137
|
+
],
|
|
138
|
+
},
|
|
139
|
+
elixir: {
|
|
140
|
+
heading: 'Elixir',
|
|
141
|
+
commands: [
|
|
142
|
+
'mix test # Run tests',
|
|
143
|
+
'mix credo # Lint',
|
|
144
|
+
'mix format # Format',
|
|
145
|
+
],
|
|
146
|
+
},
|
|
147
|
+
zig: {
|
|
148
|
+
heading: 'Zig',
|
|
149
|
+
commands: [
|
|
150
|
+
'zig build test # Run tests',
|
|
151
|
+
'zig build # Build (lint via compiler)',
|
|
152
|
+
'zig fmt . # Format',
|
|
153
|
+
],
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
|
|
34
157
|
function buildCommandsBlock(languages, useDocker) {
|
|
35
158
|
const lines = ['```bash'];
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
lines.push('ruff check . # Lint');
|
|
40
|
-
lines.push('ruff format . # Format');
|
|
41
|
-
}
|
|
42
|
-
if (languages.includes('node')) {
|
|
43
|
-
if (lines.length > 1) lines.push('');
|
|
44
|
-
lines.push('# Node.js / TypeScript');
|
|
45
|
-
lines.push('npm test # Run tests');
|
|
46
|
-
lines.push('npx eslint . # Lint');
|
|
47
|
-
lines.push('npx prettier --write . # Format');
|
|
48
|
-
}
|
|
49
|
-
if (languages.includes('java')) {
|
|
50
|
-
if (lines.length > 1) lines.push('');
|
|
51
|
-
lines.push('# Java');
|
|
52
|
-
lines.push('mvn test # Run tests');
|
|
53
|
-
lines.push('mvn checkstyle:check # Lint');
|
|
54
|
-
lines.push('mvn spotless:apply # Format');
|
|
55
|
-
}
|
|
56
|
-
if (languages.includes('csharp')) {
|
|
57
|
-
if (lines.length > 1) lines.push('');
|
|
58
|
-
lines.push('# C# / .NET');
|
|
59
|
-
lines.push('dotnet test # Run tests');
|
|
60
|
-
lines.push('dotnet format --verify-no-changes # Lint');
|
|
61
|
-
lines.push('dotnet format # Format');
|
|
62
|
-
}
|
|
63
|
-
if (languages.includes('cpp')) {
|
|
64
|
-
if (lines.length > 1) lines.push('');
|
|
65
|
-
lines.push('# C / C++');
|
|
66
|
-
lines.push('cmake --build build && ctest # Build & test');
|
|
67
|
-
lines.push('clang-tidy src/*.cpp # Lint');
|
|
68
|
-
lines.push('clang-format -i src/*.[ch]pp # Format');
|
|
69
|
-
}
|
|
70
|
-
if (languages.includes('go')) {
|
|
71
|
-
if (lines.length > 1) lines.push('');
|
|
72
|
-
lines.push('# Go');
|
|
73
|
-
lines.push('go test ./... # Run tests');
|
|
74
|
-
lines.push('golangci-lint run # Lint');
|
|
75
|
-
lines.push('gofmt -w . # Format');
|
|
76
|
-
}
|
|
77
|
-
if (languages.includes('php')) {
|
|
78
|
-
if (lines.length > 1) lines.push('');
|
|
79
|
-
lines.push('# PHP');
|
|
80
|
-
lines.push('vendor/bin/phpunit # Run tests');
|
|
81
|
-
lines.push('vendor/bin/phpstan analyse # Lint');
|
|
82
|
-
lines.push('vendor/bin/php-cs-fixer fix . # Format');
|
|
83
|
-
}
|
|
84
|
-
if (languages.includes('ruby')) {
|
|
85
|
-
if (lines.length > 1) lines.push('');
|
|
86
|
-
lines.push('# Ruby');
|
|
87
|
-
lines.push('bundle exec rspec # Run tests');
|
|
88
|
-
lines.push('rubocop # Lint');
|
|
89
|
-
lines.push('rubocop -A # Format');
|
|
90
|
-
}
|
|
91
|
-
if (languages.includes('kotlin')) {
|
|
92
|
-
if (lines.length > 1) lines.push('');
|
|
93
|
-
lines.push('# Kotlin');
|
|
94
|
-
lines.push('gradle test # Run tests');
|
|
95
|
-
lines.push('detekt # Lint');
|
|
96
|
-
lines.push('ktlint -F # Format');
|
|
97
|
-
}
|
|
98
|
-
if (languages.includes('swift')) {
|
|
99
|
-
if (lines.length > 1) lines.push('');
|
|
100
|
-
lines.push('# Swift');
|
|
101
|
-
lines.push('swift test # Run tests');
|
|
102
|
-
lines.push('swiftlint # Lint');
|
|
103
|
-
lines.push('swift-format format -r . -i # Format');
|
|
104
|
-
}
|
|
105
|
-
if (languages.includes('rust')) {
|
|
106
|
-
if (lines.length > 1) lines.push('');
|
|
107
|
-
lines.push('# Rust');
|
|
108
|
-
lines.push('cargo test # Run tests');
|
|
109
|
-
lines.push('cargo clippy # Lint');
|
|
110
|
-
lines.push('cargo fmt # Format');
|
|
111
|
-
}
|
|
112
|
-
if (languages.includes('dart')) {
|
|
113
|
-
if (lines.length > 1) lines.push('');
|
|
114
|
-
lines.push('# Dart / Flutter');
|
|
115
|
-
lines.push('dart test # Run tests');
|
|
116
|
-
lines.push('dart analyze # Lint');
|
|
117
|
-
lines.push('dart format . # Format');
|
|
118
|
-
}
|
|
119
|
-
if (languages.includes('scala')) {
|
|
120
|
-
if (lines.length > 1) lines.push('');
|
|
121
|
-
lines.push('# Scala');
|
|
122
|
-
lines.push('sbt test # Run tests');
|
|
123
|
-
lines.push('sbt scalafix # Lint');
|
|
124
|
-
lines.push('scalafmt # Format');
|
|
125
|
-
}
|
|
126
|
-
if (languages.includes('elixir')) {
|
|
127
|
-
if (lines.length > 1) lines.push('');
|
|
128
|
-
lines.push('# Elixir');
|
|
129
|
-
lines.push('mix test # Run tests');
|
|
130
|
-
lines.push('mix credo # Lint');
|
|
131
|
-
lines.push('mix format # Format');
|
|
132
|
-
}
|
|
133
|
-
if (languages.includes('zig')) {
|
|
159
|
+
for (const lang of languages) {
|
|
160
|
+
const entry = LANGUAGE_COMMANDS[lang];
|
|
161
|
+
if (!entry) continue;
|
|
134
162
|
if (lines.length > 1) lines.push('');
|
|
135
|
-
lines.push(
|
|
136
|
-
lines.push(
|
|
137
|
-
lines.push('zig build # Build (lint via compiler)');
|
|
138
|
-
lines.push('zig fmt . # Format');
|
|
163
|
+
lines.push(`# ${entry.heading}`);
|
|
164
|
+
lines.push(...entry.commands);
|
|
139
165
|
}
|
|
140
166
|
if (useDocker) {
|
|
141
167
|
if (lines.length > 1) lines.push('');
|
package/src/commands/status.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
import {
|
|
2
|
+
import { requireWorkflowMeta, getPackageVersion } from '../core/config.js';
|
|
3
3
|
import { hashFile } from '../utils/hash.js';
|
|
4
4
|
import { fileExists, readFile, listFilesRecursive } from '../utils/file.js';
|
|
5
5
|
import { getLatestNpmVersion } from '../utils/npm.js';
|
|
@@ -15,13 +15,12 @@ function countByPrefix(fileHashes, prefix) {
|
|
|
15
15
|
export async function statusCommand() {
|
|
16
16
|
const projectRoot = process.cwd();
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
const { meta, error } = await requireWorkflowMeta(projectRoot);
|
|
19
|
+
if (error === 'not-installed') {
|
|
19
20
|
display.info('Workflow is not installed. Run `worclaude init` to set up.');
|
|
20
21
|
return;
|
|
21
22
|
}
|
|
22
|
-
|
|
23
|
-
const meta = await readWorkflowMeta(projectRoot);
|
|
24
|
-
if (!meta) {
|
|
23
|
+
if (error === 'corrupted') {
|
|
25
24
|
display.error('workflow-meta.json is corrupted. Run `worclaude init` to reinstall.');
|
|
26
25
|
return;
|
|
27
26
|
}
|
package/src/commands/upgrade.js
CHANGED
|
@@ -4,8 +4,7 @@ import inquirer from 'inquirer';
|
|
|
4
4
|
import ora from 'ora';
|
|
5
5
|
import {
|
|
6
6
|
computeFileHashes,
|
|
7
|
-
|
|
8
|
-
workflowMetaExists,
|
|
7
|
+
requireWorkflowMeta,
|
|
9
8
|
writeWorkflowMeta,
|
|
10
9
|
getPackageVersion,
|
|
11
10
|
} from '../core/config.js';
|
|
@@ -70,16 +69,13 @@ export async function upgradeCommand() {
|
|
|
70
69
|
}
|
|
71
70
|
|
|
72
71
|
// 2. Check prerequisite
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
display.info('Run `worclaude init` to set up
|
|
72
|
+
const { meta, error } = await requireWorkflowMeta(projectRoot);
|
|
73
|
+
if (error === 'not-installed') {
|
|
74
|
+
display.info('Workflow is not installed. Run `worclaude init` to set up.');
|
|
76
75
|
return;
|
|
77
76
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
if (!meta) {
|
|
81
|
-
display.error('workflow-meta.json is corrupted or invalid.');
|
|
82
|
-
display.info('Run `worclaude init` to reinstall (a backup will be created first).');
|
|
77
|
+
if (error === 'corrupted') {
|
|
78
|
+
display.error('workflow-meta.json is corrupted. Run `worclaude init` to reinstall.');
|
|
83
79
|
return;
|
|
84
80
|
}
|
|
85
81
|
|
package/src/core/config.js
CHANGED
|
@@ -59,6 +59,17 @@ export async function writeWorkflowMeta(projectRoot, meta) {
|
|
|
59
59
|
await writeFile(metaPath, JSON.stringify(meta, null, 2));
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
export async function requireWorkflowMeta(projectRoot) {
|
|
63
|
+
if (!(await workflowMetaExists(projectRoot))) {
|
|
64
|
+
return { meta: null, error: 'not-installed' };
|
|
65
|
+
}
|
|
66
|
+
const meta = await readWorkflowMeta(projectRoot);
|
|
67
|
+
if (!meta) {
|
|
68
|
+
return { meta: null, error: 'corrupted' };
|
|
69
|
+
}
|
|
70
|
+
return { meta, error: null };
|
|
71
|
+
}
|
|
72
|
+
|
|
62
73
|
export async function computeFileHashes(projectRoot) {
|
|
63
74
|
const claudeDir = path.join(projectRoot, '.claude');
|
|
64
75
|
const allFiles = await listFilesRecursive(claudeDir);
|
package/src/utils/display.js
CHANGED
|
@@ -64,15 +64,6 @@ export const MODEL_BADGES = {
|
|
|
64
64
|
haiku: badges.haiku,
|
|
65
65
|
};
|
|
66
66
|
|
|
67
|
-
export const CATEGORY_BADGES = {
|
|
68
|
-
Backend: badges.backend,
|
|
69
|
-
Frontend: badges.frontend,
|
|
70
|
-
DevOps: badges.devops,
|
|
71
|
-
Quality: badges.quality,
|
|
72
|
-
Documentation: badges.docs,
|
|
73
|
-
'Data / AI': badges.dataai,
|
|
74
|
-
};
|
|
75
|
-
|
|
76
67
|
export const STACK_BADGES = {
|
|
77
68
|
Python: badges.python,
|
|
78
69
|
'Node.js / TypeScript': badges.node,
|
|
@@ -11,6 +11,9 @@ disallowedTools:
|
|
|
11
11
|
maxTurns: 40
|
|
12
12
|
omitClaudeMd: true
|
|
13
13
|
memory: project
|
|
14
|
+
skills:
|
|
15
|
+
- security-checklist
|
|
16
|
+
criticalSystemReminder: "CRITICAL: You CANNOT edit files. Report vulnerabilities with remediation guidance only."
|
|
14
17
|
---
|
|
15
18
|
|
|
16
19
|
You are a senior application security engineer performing a code
|
|
@@ -5,6 +5,8 @@ model: sonnet
|
|
|
5
5
|
isolation: worktree
|
|
6
6
|
background: true
|
|
7
7
|
maxTurns: 50
|
|
8
|
+
initialPrompt: "/start"
|
|
9
|
+
criticalSystemReminder: "CRITICAL: You are verification-only. Do NOT edit or fix code. Report findings with exact reproduction steps."
|
|
8
10
|
---
|
|
9
11
|
|
|
10
12
|
You are a verification specialist. You test the actual running
|
|
@@ -110,6 +112,9 @@ You will feel the urge to skip checks. These are the excuses — recognize them:
|
|
|
110
112
|
- **Config/Infrastructure**: validate syntax → dry-run where possible → check env vars
|
|
111
113
|
- **Bug fixes**: reproduce original bug → verify fix → run regression tests
|
|
112
114
|
- **Refactoring**: existing test suite must pass unchanged → diff public API surface
|
|
115
|
+
- **Mobile (iOS/Android)**: clean build → install on simulator/emulator → dump accessibility/UI tree, tap by coords, re-dump to verify → check crash logs (logcat / device console)
|
|
116
|
+
- **Database migrations**: run migration up → verify schema matches intent → run migration down (reversibility) → test against existing data, not just empty DB
|
|
117
|
+
- **Data/ML pipeline**: run with sample input → verify output shape/schema/types → test empty input and NaN/null handling → check row counts in vs out for silent data loss
|
|
113
118
|
|
|
114
119
|
## Before Issuing PASS
|
|
115
120
|
|
|
@@ -7,23 +7,51 @@
|
|
|
7
7
|
## User
|
|
8
8
|
|
|
9
9
|
<!-- Role, preferences, expertise — helps Claude tailor responses -->
|
|
10
|
+
<!-- Example: - [Backend lead](user_role.md) — 8 years Python, new to this frontend -->
|
|
10
11
|
|
|
11
12
|
## Feedback
|
|
12
13
|
|
|
13
14
|
<!-- What to do and what to avoid — both corrections AND confirmed approaches -->
|
|
14
15
|
<!-- Format: rule, then **Why:** and **How to apply:** -->
|
|
16
|
+
<!-- Example: - [No mocks in integration tests](feedback_testing.md) — burned by mock/prod divergence -->
|
|
15
17
|
|
|
16
18
|
## Project
|
|
17
19
|
|
|
18
20
|
<!-- Ongoing work, goals, deadlines — convert relative dates to absolute -->
|
|
19
21
|
<!-- Format: fact/decision, then **Why:** and **How to apply:** -->
|
|
22
|
+
<!-- Example: - [Merge freeze 2026-03-05](project_release.md) — mobile team cutting release branch -->
|
|
20
23
|
|
|
21
24
|
## Reference
|
|
22
25
|
|
|
23
26
|
<!-- Pointers to external systems — Linear boards, Slack channels, dashboards -->
|
|
27
|
+
<!-- Example: - [Pipeline bugs](reference_linear.md) — tracked in Linear project "INGEST" -->
|
|
24
28
|
|
|
25
29
|
---
|
|
26
30
|
|
|
31
|
+
## Memory File Format
|
|
32
|
+
|
|
33
|
+
Each memory file in `.claude/memory/` uses this frontmatter:
|
|
34
|
+
|
|
35
|
+
```markdown
|
|
36
|
+
---
|
|
37
|
+
name: descriptive-name
|
|
38
|
+
description: one-line summary used to decide relevance in future sessions
|
|
39
|
+
type: user | feedback | project | reference
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
Content here. For feedback/project types, structure as:
|
|
43
|
+
Rule or fact.
|
|
44
|
+
**Why:** the reason or context.
|
|
45
|
+
**How to apply:** when and where this guidance applies.
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Drift and Verification
|
|
49
|
+
|
|
50
|
+
- Memory records become stale over time. Before acting on a memory, verify it against the current state of the codebase.
|
|
51
|
+
- If a memory names a file path, check the file still exists. If it names a function or flag, grep for it.
|
|
52
|
+
- If a recalled memory conflicts with current information, trust what you observe now — update or remove the stale memory.
|
|
53
|
+
- "The memory says X exists" is not the same as "X exists now."
|
|
54
|
+
|
|
27
55
|
## What NOT to save here
|
|
28
56
|
|
|
29
57
|
- Code patterns, architecture, file paths — derivable from current project state
|
|
@@ -31,3 +59,12 @@
|
|
|
31
59
|
- Debugging solutions — the fix is in the code, the context is in the commit message
|
|
32
60
|
- Anything already in CLAUDE.md
|
|
33
61
|
- Ephemeral task details — current conversation context, in-progress work
|
|
62
|
+
|
|
63
|
+
These exclusions apply even when explicitly asked to save. If asked to save a PR list or activity summary, ask what was *surprising* or *non-obvious* about it — that is the part worth keeping.
|
|
64
|
+
|
|
65
|
+
## Memory vs Plans vs Tasks
|
|
66
|
+
|
|
67
|
+
Memory is for information useful across conversations. Don't use it for:
|
|
68
|
+
- **Plans** — use a plan file or plan mode for implementation strategies within a session
|
|
69
|
+
- **Tasks** — use the task system for tracking work steps within a session
|
|
70
|
+
- **Session state** — current conversation context belongs in the conversation, not memory
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: "How Claude writes rules for itself, when to update CLAUDE.md, keeping it lean and effective"
|
|
3
3
|
when_to_use: "When considering updates to CLAUDE.md, when the same mistake has happened twice, when CLAUDE.md is getting too long"
|
|
4
|
+
version: "1.0.0"
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
# CLAUDE.md Maintenance
|
|
@@ -99,6 +100,28 @@ The /update-claude-md command helps at session end:
|
|
|
99
100
|
Always review proposed changes before applying. Not every mistake needs a rule.
|
|
100
101
|
Only add rules for recurring problems.
|
|
101
102
|
|
|
103
|
+
## The @include Directive
|
|
104
|
+
|
|
105
|
+
When CLAUDE.md grows beyond the 50-line target, use `@include` to split content
|
|
106
|
+
into separate files while keeping it loadable:
|
|
107
|
+
|
|
108
|
+
```markdown
|
|
109
|
+
# CLAUDE.md
|
|
110
|
+
## Key Files
|
|
111
|
+
@./docs/conventions.md
|
|
112
|
+
@./docs/api-standards.md
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
- `@./relative` — relative to the file containing the directive
|
|
116
|
+
- `@~/path` — relative to home directory
|
|
117
|
+
- `@/absolute` — absolute path
|
|
118
|
+
- Works in CLAUDE.md, .claude/CLAUDE.md, .claude/rules/*.md, and CLAUDE.local.md
|
|
119
|
+
- Does NOT work inside code blocks (only in leaf text nodes)
|
|
120
|
+
- Non-existent files are silently ignored; circular references are prevented
|
|
121
|
+
|
|
122
|
+
This is the recommended alternative to cramming everything into CLAUDE.md.
|
|
123
|
+
Each included file still consumes context budget, so use judiciously.
|
|
124
|
+
|
|
102
125
|
## Gotchas
|
|
103
126
|
|
|
104
127
|
- CLAUDE.md is read as system context, not as a document. Write it as instructions,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: "Context budget awareness, when to compact, when to clear, subagent offloading"
|
|
3
3
|
when_to_use: "When context is running low, before compaction decisions, when deciding whether to use subagents for context hygiene"
|
|
4
|
+
version: "1.0.0"
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
# Context Management
|
|
@@ -117,6 +118,29 @@ WORCLAUDE_HOOK_PROFILE=strict claude
|
|
|
117
118
|
The default is `standard` if the variable is not set. You don't need to do
|
|
118
119
|
anything for normal development — the default just works.
|
|
119
120
|
|
|
121
|
+
## Token Budgets (Reference)
|
|
122
|
+
|
|
123
|
+
Approximate values from Claude Code v2.1.88 source (March 2026). These may change between releases.
|
|
124
|
+
|
|
125
|
+
| Resource | Budget |
|
|
126
|
+
|---|---|
|
|
127
|
+
| Context window (default) | 200,000 tokens |
|
|
128
|
+
| Context window (Opus 4.6 / Sonnet 4.6 with 1M) | 1,000,000 tokens |
|
|
129
|
+
| Max output tokens (Sonnet 4.6) | 32,000 default, 128,000 upper limit |
|
|
130
|
+
| Max output tokens (Opus 4.6) | 64,000 default, 128,000 upper limit |
|
|
131
|
+
| Tool presence overhead | ~500 tokens (added when any tools are enabled) |
|
|
132
|
+
| Post-compact file restore | 5 files max, 50,000 token budget, 5,000 per file |
|
|
133
|
+
| Post-compact skills restore | 25,000 token budget, 5,000 per skill |
|
|
134
|
+
| Compact summary output | 20,000 tokens max |
|
|
135
|
+
| CLAUDE.md total budget | ~40,000 characters across all loaded instruction files |
|
|
136
|
+
| MEMORY.md | 200 lines / 25,000 bytes |
|
|
137
|
+
|
|
138
|
+
Practical takeaways:
|
|
139
|
+
- After compaction, only 5 files are restored at 5k tokens each. Structure your work
|
|
140
|
+
so the most important files are recently read.
|
|
141
|
+
- Skills over 5k tokens get truncated after compaction. Keep skills focused.
|
|
142
|
+
- The 70% rule still applies — these numbers help you estimate when you'll hit it.
|
|
143
|
+
|
|
120
144
|
## Gotchas
|
|
121
145
|
|
|
122
146
|
- Compacting doesn't free as much context as you think. If you've read 20 large files,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: 'Multi-agent orchestration patterns: when to use coordinator mode, worker prompts, parallel execution'
|
|
3
3
|
when_to_use: 'When working with multiple agents or terminals in parallel, or when deciding how to break a large task into coordinated sub-tasks'
|
|
4
|
+
version: "1.0.0"
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
# Coordinator Mode
|
|
@@ -20,6 +21,25 @@ Don't use coordinator patterns when:
|
|
|
20
21
|
- Steps are strictly sequential with no parallelism
|
|
21
22
|
- The overhead of coordination exceeds the work itself
|
|
22
23
|
|
|
24
|
+
## Phase-Based Workflow
|
|
25
|
+
|
|
26
|
+
Most coordinated tasks follow four phases:
|
|
27
|
+
|
|
28
|
+
| Phase | Who | Purpose |
|
|
29
|
+
|-------|-----|---------|
|
|
30
|
+
| Research | Workers (parallel) | Investigate codebase, find files, understand problem |
|
|
31
|
+
| Synthesis | **You** (coordinator) | Read findings, understand the problem, craft implementation specs |
|
|
32
|
+
| Implementation | Workers | Make targeted changes per spec, commit |
|
|
33
|
+
| Verification | Workers | Test changes work, try to break them |
|
|
34
|
+
|
|
35
|
+
The synthesis phase is the coordinator's most important job. When workers report
|
|
36
|
+
research findings, **you must understand them before directing follow-up work**.
|
|
37
|
+
Read the findings. Identify the approach. Then write a prompt that proves you
|
|
38
|
+
understood by including specific file paths, line numbers, and exactly what to change.
|
|
39
|
+
|
|
40
|
+
Never write "based on your findings" or "based on the research." These phrases
|
|
41
|
+
delegate understanding to the worker instead of doing it yourself.
|
|
42
|
+
|
|
23
43
|
## Worker Prompt Best Practices
|
|
24
44
|
|
|
25
45
|
Workers cannot see your conversation. Every prompt must be self-contained:
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: "Branch naming, commit message format, PR workflow, worktree conventions, versioning policy"
|
|
3
3
|
when_to_use: "When creating branches, writing commit messages, creating PRs, or making versioning decisions"
|
|
4
|
+
version: "1.0.0"
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
# Git Conventions
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: "How to structure implementation plans as files, progressive implementation, plan review process"
|
|
3
3
|
when_to_use: "When starting a multi-step task that needs a written plan, or when reviewing an existing implementation plan"
|
|
4
|
+
version: "1.0.0"
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
# Planning with Files
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: "OWASP-based security checklist any agent can reference when reviewing or writing code"
|
|
3
3
|
when_to_use: "When writing code that handles user input, authentication, authorization, file uploads, or external data"
|
|
4
|
+
version: "1.0.0"
|
|
4
5
|
paths:
|
|
5
6
|
- "**/auth/**"
|
|
6
7
|
- "**/security/**"
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: "When to use subagents, how many, context hygiene, worktree isolation patterns"
|
|
3
3
|
when_to_use: "When deciding whether to spawn a subagent, choosing between parallel and sequential execution, or giving subagent instructions"
|
|
4
|
+
version: "1.0.0"
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
# Subagent Usage
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: "Test philosophy, coverage strategy, test-first patterns, what to test and what not to"
|
|
3
3
|
when_to_use: "When writing, modifying, or reviewing tests, or when making decisions about test strategy and coverage"
|
|
4
|
+
version: "1.0.0"
|
|
4
5
|
paths:
|
|
5
6
|
- "test/**"
|
|
6
7
|
- "tests/**"
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: "Domain-specific verification beyond tests, closing the feedback loop for web, API, CLI, data"
|
|
3
3
|
when_to_use: "When verifying that implemented changes work correctly, after running automated tests, before committing"
|
|
4
|
+
version: "1.0.0"
|
|
4
5
|
paths:
|
|
5
6
|
- "test/**"
|
|
6
7
|
- "tests/**"
|