@claudetools/tools 0.8.2 → 0.8.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/cli.js +41 -0
- package/dist/context/deduplication.d.ts +72 -0
- package/dist/context/deduplication.js +77 -0
- package/dist/context/deduplication.test.d.ts +6 -0
- package/dist/context/deduplication.test.js +84 -0
- package/dist/context/emergency-eviction.d.ts +73 -0
- package/dist/context/emergency-eviction.example.d.ts +13 -0
- package/dist/context/emergency-eviction.example.js +94 -0
- package/dist/context/emergency-eviction.js +226 -0
- package/dist/context/eviction-engine.d.ts +76 -0
- package/dist/context/eviction-engine.example.d.ts +7 -0
- package/dist/context/eviction-engine.example.js +144 -0
- package/dist/context/eviction-engine.js +176 -0
- package/dist/context/example-usage.d.ts +1 -0
- package/dist/context/example-usage.js +128 -0
- package/dist/context/exchange-summariser.d.ts +80 -0
- package/dist/context/exchange-summariser.js +261 -0
- package/dist/context/health-monitor.d.ts +97 -0
- package/dist/context/health-monitor.example.d.ts +1 -0
- package/dist/context/health-monitor.example.js +164 -0
- package/dist/context/health-monitor.js +210 -0
- package/dist/context/importance-scorer.d.ts +94 -0
- package/dist/context/importance-scorer.example.d.ts +1 -0
- package/dist/context/importance-scorer.example.js +140 -0
- package/dist/context/importance-scorer.js +187 -0
- package/dist/context/index.d.ts +9 -0
- package/dist/context/index.js +16 -0
- package/dist/context/session-helper.d.ts +10 -0
- package/dist/context/session-helper.js +51 -0
- package/dist/context/session-store.d.ts +94 -0
- package/dist/context/session-store.js +286 -0
- package/dist/context/usage-estimator.d.ts +131 -0
- package/dist/context/usage-estimator.js +260 -0
- package/dist/context/usage-estimator.test.d.ts +1 -0
- package/dist/context/usage-estimator.test.js +208 -0
- package/dist/context-cli.d.ts +16 -0
- package/dist/context-cli.js +309 -0
- package/dist/evaluation/build-dataset.d.ts +1 -0
- package/dist/evaluation/build-dataset.js +135 -0
- package/dist/evaluation/threshold-eval.d.ts +63 -0
- package/dist/evaluation/threshold-eval.js +250 -0
- package/dist/handlers/codedna-handlers.d.ts +2 -2
- package/dist/handlers/tool-handlers.js +126 -165
- package/dist/helpers/api-client.d.ts +5 -1
- package/dist/helpers/api-client.js +3 -1
- package/dist/helpers/compact-formatter.d.ts +51 -0
- package/dist/helpers/compact-formatter.js +130 -0
- package/dist/helpers/engagement-tracker.d.ts +10 -0
- package/dist/helpers/engagement-tracker.js +61 -0
- package/dist/helpers/error-tracking.js +1 -1
- package/dist/helpers/session-validation.d.ts +76 -0
- package/dist/helpers/session-validation.js +221 -0
- package/dist/helpers/usage-analytics.js +1 -1
- package/dist/hooks/index.d.ts +4 -0
- package/dist/hooks/index.js +6 -0
- package/dist/hooks/post-tool-use-hook-cli.d.ts +2 -0
- package/dist/hooks/post-tool-use-hook-cli.js +34 -0
- package/dist/hooks/post-tool-use.d.ts +67 -0
- package/dist/hooks/post-tool-use.js +234 -0
- package/dist/hooks/stop-hook-cli.d.ts +2 -0
- package/dist/hooks/stop-hook-cli.js +34 -0
- package/dist/hooks/stop.d.ts +64 -0
- package/dist/hooks/stop.js +192 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2 -0
- package/dist/logger.d.ts +1 -1
- package/dist/logger.js +4 -0
- package/dist/resources.js +3 -0
- package/dist/setup.js +206 -2
- package/dist/templates/claude-md.d.ts +1 -1
- package/dist/templates/claude-md.js +23 -35
- package/dist/templates/worker-prompt.js +35 -202
- package/dist/tools.js +26 -20
- package/package.json +6 -2
package/dist/setup.js
CHANGED
|
@@ -747,11 +747,22 @@ fi
|
|
|
747
747
|
# Escape the query for JSON (handle quotes and newlines)
|
|
748
748
|
ESCAPED_QUERY=$(echo "$USER_QUERY" | head -c 500 | jq -Rs '.')
|
|
749
749
|
|
|
750
|
+
# Get session state for query-aware budget allocation (if SESSION_ID available)
|
|
751
|
+
SESSION_STATE_JSON='{}'
|
|
752
|
+
if [ -n "$SESSION_ID" ]; then
|
|
753
|
+
# Try to get session state from SessionStore
|
|
754
|
+
TOOLS_DIR="$HOME/.claudetools/node_modules/@claudetools/tools"
|
|
755
|
+
if [ -f "$TOOLS_DIR/dist/context/session-helper.js" ]; then
|
|
756
|
+
SESSION_STATE_JSON=$(node "$TOOLS_DIR/dist/context/session-helper.js" "$SESSION_ID" 2>/dev/null || echo '{}')
|
|
757
|
+
fi
|
|
758
|
+
fi
|
|
759
|
+
|
|
750
760
|
# Inject context with semantic search based on the user's prompt
|
|
761
|
+
# Include session_state if available for dynamic budget calculation
|
|
751
762
|
RESULT=$(curl -s --max-time 2 -X POST "$API_URL/api/v1/context/inject" \\
|
|
752
763
|
-H "Authorization: Bearer $API_KEY" \\
|
|
753
764
|
-H "Content-Type: application/json" \\
|
|
754
|
-
-d "{\\"query\\": $ESCAPED_QUERY, \\"project_id\\": \\"$PROJECT_ID\\", \\"cwd\\": \\"$CWD\\"}" \\
|
|
765
|
+
-d "{\\"query\\": $ESCAPED_QUERY, \\"project_id\\": \\"$PROJECT_ID\\", \\"cwd\\": \\"$CWD\\", \\"session_state\\": $SESSION_STATE_JSON}" \\
|
|
755
766
|
2>/dev/null)
|
|
756
767
|
|
|
757
768
|
# Output context as additionalContext JSON for Claude Code
|
|
@@ -1330,6 +1341,170 @@ export async function runUninstall() {
|
|
|
1330
1341
|
console.log('\n' + chalk.green('ClaudeTools removed from Claude Code.'));
|
|
1331
1342
|
console.log(chalk.dim('Your ~/.claudetools/ config and data are preserved.\n'));
|
|
1332
1343
|
}
|
|
1344
|
+
async function runOnboarding(apiUrl, apiKey, projectId, projectName) {
|
|
1345
|
+
header('Project Onboarding');
|
|
1346
|
+
info('Answer a few questions to help Claude understand your project better.');
|
|
1347
|
+
console.log(chalk.dim('This creates memory facts that provide context in future sessions.\n'));
|
|
1348
|
+
const spinner = ora('Starting onboarding session...').start();
|
|
1349
|
+
try {
|
|
1350
|
+
// Start onboarding session
|
|
1351
|
+
const startResponse = await fetch(`${apiUrl}/api/v1/onboarding/start`, {
|
|
1352
|
+
method: 'POST',
|
|
1353
|
+
headers: {
|
|
1354
|
+
'Content-Type': 'application/json',
|
|
1355
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
1356
|
+
},
|
|
1357
|
+
body: JSON.stringify({ project_id: projectId }),
|
|
1358
|
+
});
|
|
1359
|
+
if (!startResponse.ok) {
|
|
1360
|
+
spinner.fail('Could not start onboarding');
|
|
1361
|
+
const errorData = await startResponse.json().catch(() => ({}));
|
|
1362
|
+
error(errorData.error || `HTTP ${startResponse.status}`);
|
|
1363
|
+
return;
|
|
1364
|
+
}
|
|
1365
|
+
const startData = await startResponse.json();
|
|
1366
|
+
if (!startData.success || !startData.data) {
|
|
1367
|
+
spinner.fail('Failed to start onboarding');
|
|
1368
|
+
return;
|
|
1369
|
+
}
|
|
1370
|
+
spinner.succeed('Onboarding session started');
|
|
1371
|
+
const sessionId = startData.data.session_id;
|
|
1372
|
+
let questions = startData.data.questions;
|
|
1373
|
+
let state = startData.data.state;
|
|
1374
|
+
let questionCount = 0;
|
|
1375
|
+
const maxQuestions = 8; // Limit to avoid fatigue
|
|
1376
|
+
// Interactive question loop
|
|
1377
|
+
while (questions.length > 0 && questionCount < maxQuestions) {
|
|
1378
|
+
const question = questions[0];
|
|
1379
|
+
questionCount++;
|
|
1380
|
+
console.log('');
|
|
1381
|
+
console.log(chalk.cyan(`Question ${questionCount}`) + (question.category ? chalk.dim(` [${question.category}]`) : ''));
|
|
1382
|
+
console.log(chalk.bold(question.question));
|
|
1383
|
+
let answer;
|
|
1384
|
+
if (question.options && question.options.length > 0) {
|
|
1385
|
+
// Multiple choice question
|
|
1386
|
+
const { selected } = await prompts({
|
|
1387
|
+
type: 'select',
|
|
1388
|
+
name: 'selected',
|
|
1389
|
+
message: 'Select an option:',
|
|
1390
|
+
choices: [
|
|
1391
|
+
...question.options.map(opt => ({ title: opt, value: opt })),
|
|
1392
|
+
{ title: 'Skip this question', value: '__skip__' },
|
|
1393
|
+
],
|
|
1394
|
+
});
|
|
1395
|
+
if (selected === '__skip__' || !selected) {
|
|
1396
|
+
questions.shift();
|
|
1397
|
+
continue;
|
|
1398
|
+
}
|
|
1399
|
+
answer = selected;
|
|
1400
|
+
}
|
|
1401
|
+
else {
|
|
1402
|
+
// Free text question
|
|
1403
|
+
const { response } = await prompts({
|
|
1404
|
+
type: 'text',
|
|
1405
|
+
name: 'response',
|
|
1406
|
+
message: '>',
|
|
1407
|
+
validate: (v) => v.length > 0 || 'Please enter a response (or type "skip" to skip)',
|
|
1408
|
+
});
|
|
1409
|
+
if (!response || response.toLowerCase() === 'skip') {
|
|
1410
|
+
questions.shift();
|
|
1411
|
+
continue;
|
|
1412
|
+
}
|
|
1413
|
+
answer = response;
|
|
1414
|
+
}
|
|
1415
|
+
// Submit answer
|
|
1416
|
+
const answerSpinner = ora('Processing...').start();
|
|
1417
|
+
try {
|
|
1418
|
+
const answerResponse = await fetch(`${apiUrl}/api/v1/onboarding/answer`, {
|
|
1419
|
+
method: 'POST',
|
|
1420
|
+
headers: {
|
|
1421
|
+
'Content-Type': 'application/json',
|
|
1422
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
1423
|
+
},
|
|
1424
|
+
body: JSON.stringify({
|
|
1425
|
+
session_id: sessionId,
|
|
1426
|
+
question_id: question.id,
|
|
1427
|
+
answer,
|
|
1428
|
+
}),
|
|
1429
|
+
});
|
|
1430
|
+
if (answerResponse.ok) {
|
|
1431
|
+
const answerData = await answerResponse.json();
|
|
1432
|
+
if (answerData.success && answerData.data) {
|
|
1433
|
+
const factsCount = answerData.data.facts_extracted || 0;
|
|
1434
|
+
if (factsCount > 0) {
|
|
1435
|
+
answerSpinner.succeed(`Recorded (${factsCount} fact${factsCount > 1 ? 's' : ''} extracted)`);
|
|
1436
|
+
}
|
|
1437
|
+
else {
|
|
1438
|
+
answerSpinner.succeed('Recorded');
|
|
1439
|
+
}
|
|
1440
|
+
// Update questions and state
|
|
1441
|
+
if (answerData.data.next_questions) {
|
|
1442
|
+
questions = answerData.data.next_questions;
|
|
1443
|
+
}
|
|
1444
|
+
else {
|
|
1445
|
+
questions.shift();
|
|
1446
|
+
}
|
|
1447
|
+
if (answerData.data.state) {
|
|
1448
|
+
state = answerData.data.state;
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
else {
|
|
1452
|
+
answerSpinner.warn('Answer recorded (no facts extracted)');
|
|
1453
|
+
questions.shift();
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
1456
|
+
else {
|
|
1457
|
+
answerSpinner.fail('Could not submit answer');
|
|
1458
|
+
questions.shift();
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
catch {
|
|
1462
|
+
answerSpinner.fail('Network error');
|
|
1463
|
+
questions.shift();
|
|
1464
|
+
}
|
|
1465
|
+
// Check if we should stop
|
|
1466
|
+
if (state.phase === 'confirmation' || state.phase === 'done') {
|
|
1467
|
+
break;
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
1470
|
+
// Complete onboarding
|
|
1471
|
+
console.log('');
|
|
1472
|
+
const completeSpinner = ora('Completing onboarding...').start();
|
|
1473
|
+
try {
|
|
1474
|
+
const completeResponse = await fetch(`${apiUrl}/api/v1/onboarding/complete`, {
|
|
1475
|
+
method: 'POST',
|
|
1476
|
+
headers: {
|
|
1477
|
+
'Content-Type': 'application/json',
|
|
1478
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
1479
|
+
},
|
|
1480
|
+
body: JSON.stringify({
|
|
1481
|
+
session_id: sessionId,
|
|
1482
|
+
project_id: projectId,
|
|
1483
|
+
}),
|
|
1484
|
+
});
|
|
1485
|
+
if (completeResponse.ok) {
|
|
1486
|
+
const completeData = await completeResponse.json();
|
|
1487
|
+
if (completeData.success && completeData.data) {
|
|
1488
|
+
const totalFacts = completeData.data.facts_extracted || 0;
|
|
1489
|
+
completeSpinner.succeed(`Onboarding complete! ${totalFacts} facts stored in memory.`);
|
|
1490
|
+
}
|
|
1491
|
+
else {
|
|
1492
|
+
completeSpinner.succeed('Onboarding complete!');
|
|
1493
|
+
}
|
|
1494
|
+
}
|
|
1495
|
+
else {
|
|
1496
|
+
completeSpinner.warn('Onboarding session saved (completion had issues)');
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
catch {
|
|
1500
|
+
completeSpinner.warn('Could not finalize onboarding');
|
|
1501
|
+
}
|
|
1502
|
+
}
|
|
1503
|
+
catch (err) {
|
|
1504
|
+
spinner.fail('Onboarding failed');
|
|
1505
|
+
error(err instanceof Error ? err.message : String(err));
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1333
1508
|
// -----------------------------------------------------------------------------
|
|
1334
1509
|
// Project Init
|
|
1335
1510
|
// -----------------------------------------------------------------------------
|
|
@@ -1491,12 +1666,41 @@ export async function runInit() {
|
|
|
1491
1666
|
const newContent = existingContent.trimEnd() + '\n' + projectContent;
|
|
1492
1667
|
writeFileSync(projectClaudeMd, newContent);
|
|
1493
1668
|
success('Created .claude/CLAUDE.md');
|
|
1669
|
+
// Ensure hooks are installed and configured
|
|
1670
|
+
// (User might have run init without setup, or hooks might have been deleted)
|
|
1671
|
+
header('Hook Configuration');
|
|
1672
|
+
try {
|
|
1673
|
+
await installHooks();
|
|
1674
|
+
await configureSettings();
|
|
1675
|
+
info('Hooks configured successfully');
|
|
1676
|
+
}
|
|
1677
|
+
catch (err) {
|
|
1678
|
+
// Non-fatal - just warn
|
|
1679
|
+
console.log(chalk.yellow('⚠ Warning: Could not configure hooks. Run "claudetools --setup" to fix.'));
|
|
1680
|
+
}
|
|
1494
1681
|
// Summary
|
|
1495
1682
|
console.log('\n' + chalk.green(' Project initialized!\n'));
|
|
1496
1683
|
console.log(' ' + chalk.bold('Project:') + ` ${projectName}`);
|
|
1497
1684
|
console.log(' ' + chalk.bold('ID:') + ` ${projectId}`);
|
|
1498
1685
|
console.log(' ' + chalk.bold('Config:') + ` ${projectClaudeMd}\n`);
|
|
1499
|
-
|
|
1686
|
+
// Offer onboarding
|
|
1687
|
+
if (config.apiKey) {
|
|
1688
|
+
const { runOnboard } = await prompts({
|
|
1689
|
+
type: 'confirm',
|
|
1690
|
+
name: 'runOnboard',
|
|
1691
|
+
message: 'Run project onboarding? (Helps Claude understand your project)',
|
|
1692
|
+
initial: true,
|
|
1693
|
+
});
|
|
1694
|
+
if (runOnboard) {
|
|
1695
|
+
await runOnboarding(config.apiUrl || DEFAULT_CONFIG.apiUrl, config.apiKey, projectId, projectName);
|
|
1696
|
+
}
|
|
1697
|
+
else {
|
|
1698
|
+
console.log(chalk.dim('\n You can run onboarding later with: claudetools onboard\n'));
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
else {
|
|
1702
|
+
console.log(chalk.dim(' Memory tools are now configured for this project.\n'));
|
|
1703
|
+
}
|
|
1500
1704
|
}
|
|
1501
1705
|
// -----------------------------------------------------------------------------
|
|
1502
1706
|
// Cleanup Command (standalone)
|
|
@@ -5,7 +5,7 @@ export declare const PROJECT_SECTION_END = "<!-- CLAUDETOOLS:PROJECT:END -->";
|
|
|
5
5
|
/**
|
|
6
6
|
* Global CLAUDE.md content - added to ~/.claude/CLAUDE.md
|
|
7
7
|
*/
|
|
8
|
-
export declare const GLOBAL_TEMPLATE = "\n<!-- CLAUDETOOLS:START -->\n# ClaudeTools Memory System\n\nYou have access to a persistent memory system via
|
|
8
|
+
export declare const GLOBAL_TEMPLATE = "\n<!-- CLAUDETOOLS:START -->\n# ClaudeTools Memory System\n\nYou have access to a persistent memory system. **Context is AUTO-INJECTED via hooks** - you rarely need to call memory tools explicitly.\n\n## \u26A0\uFE0F IMPORTANT: Hooks vs MCP Tools\n\n**AUTOMATIC (via hooks - zero context cost):**\n- Context injection \u2192 `user-prompt-submit` hook runs on every message\n- Fact extraction \u2192 `post-tool-use` hook extracts from your work\n- Session context \u2192 `session-start` hook provides initial context\n\n**EXPLICIT (MCP tools - costs context):**\n- `memory_store_fact` \u2192 Store a specific fact you learned\n- `task_plan` / `task_start` / `task_complete` \u2192 Task management\n\n**DO NOT CALL these tools routinely (context already injected):**\n- `memory_search` - only if you need DIFFERENT search params\n- `memory_inject` - only if you need to refresh for a different query\n- `memory_get_context` - only for debugging\n- `memory_index` - only for debugging\n\n## Storing Facts (DO use this)\n```\nmemory_store_fact(\n entity1: \"UserService\",\n relationship: \"USES\",\n entity2: \"bcrypt\",\n context: \"Password hashing uses bcrypt with 12 rounds\"\n)\n```\nStore important facts when you learn something concrete. The `post-tool-use` hook also extracts facts automatically.\n\n## Task Management\n\n### Creating Work Plans with Auto-Dispatch\n```\ntask_plan(\n goal: \"Add user authentication\",\n epic_title: \"User Auth System\",\n tasks: [...]\n)\n```\nBreak down complex work into tracked tasks. **Tasks are automatically set to `ready` status.**\n\nAfter `task_plan` completes, you will receive Task tool invocations to spawn parallel agents.\n**Execute ALL Task tool calls in a SINGLE message** to enable parallel execution.\n\n### Parallel Agent Workflow\n1. User describes work needed\n2. Call `task_plan_draft` to present the plan\n3. User says \"go\" to approve\n4. Call `task_plan` - tasks created in `ready` status\n5. Execute the provided Task tool calls in ONE message\n6. Agents work in parallel, each calling `task_complete` when done\n\n### Manual Task Start (Sequential)\n```\ntask_start(task_id: \"task_xxx\")\n```\nClaim a task before working on it. Use for sequential execution.\n\n### Completing Tasks\n```\ntask_complete(task_id: \"task_xxx\", summary: \"Implemented JWT auth with refresh tokens\")\n```\nMark tasks done with a summary of work completed. **Always call this when a task is finished.**\n\n## Codebase Intelligence\n\n### Start with codebase_map() - ALWAYS\n```\ncodebase_map() # FIRST TOOL when exploring unfamiliar code\n```\n**When to use:** Starting a new task, exploring unfamiliar code, understanding project structure, finding entry points.\n\nThe map shows:\n- Project structure and key directories\n- Entry points and their exports\n- Framework detection (React, Express, etc.)\n- Key symbols and their locations\n\n**Use codebase_map BEFORE using Grep/Glob** - it gives you the lay of the land so you know where to look.\n\n### Then use targeted tools\n```\ncodebase_find(\"UserService\") # Find specific symbols/files\ncodebase_context(\"src/auth.ts\") # Get file dependencies\nanalyze_impact(\"validateToken\") # See what changing a function affects\n```\n\n## CodeDNA: Generate Code, Save 99% Tokens\n\n**When creating APIs/CRUD operations:** Call `codedna_generate_api` instead of writing code manually.\n\n```\ncodedna_generate_api({\n spec: \"User(email:string:unique, password:string:hashed, age:integer:min(18))\",\n framework: \"express\",\n options: { auth: true, validation: true, tests: true }\n})\n```\n\n**Generates 6 production files** (models, controllers, routes, validators, auth, tests) in ~5 seconds.\n**Saves:** 30,000 tokens \u2192 200 tokens (99% reduction)\n\n## Best Practices\n\n1. **Trust auto-injection** - Context is injected automatically, don't call memory_search\n2. **Store decisions** - Use `memory_store_fact` for architectural choices\n3. **Use task tracking** - Break complex work into tasks\n4. **Use CodeDNA for APIs** - Generate instead of write (99% token savings)\n5. **Minimize tool calls** - Every MCP call costs context tokens\n<!-- CLAUDETOOLS:END -->\n";
|
|
9
9
|
/**
|
|
10
10
|
* Project-level CLAUDE.md content - added to .claude/CLAUDE.md
|
|
11
11
|
*/
|
|
@@ -14,20 +14,26 @@ export const GLOBAL_TEMPLATE = `
|
|
|
14
14
|
${SECTION_START}
|
|
15
15
|
# ClaudeTools Memory System
|
|
16
16
|
|
|
17
|
-
You have access to a persistent memory system via
|
|
17
|
+
You have access to a persistent memory system. **Context is AUTO-INJECTED via hooks** - you rarely need to call memory tools explicitly.
|
|
18
18
|
|
|
19
|
-
##
|
|
19
|
+
## ⚠️ IMPORTANT: Hooks vs MCP Tools
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
21
|
+
**AUTOMATIC (via hooks - zero context cost):**
|
|
22
|
+
- Context injection → \`user-prompt-submit\` hook runs on every message
|
|
23
|
+
- Fact extraction → \`post-tool-use\` hook extracts from your work
|
|
24
|
+
- Session context → \`session-start\` hook provides initial context
|
|
25
|
+
|
|
26
|
+
**EXPLICIT (MCP tools - costs context):**
|
|
27
|
+
- \`memory_store_fact\` → Store a specific fact you learned
|
|
28
|
+
- \`task_plan\` / \`task_start\` / \`task_complete\` → Task management
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
**DO NOT CALL these tools routinely (context already injected):**
|
|
31
|
+
- \`memory_search\` - only if you need DIFFERENT search params
|
|
32
|
+
- \`memory_inject\` - only if you need to refresh for a different query
|
|
33
|
+
- \`memory_get_context\` - only for debugging
|
|
34
|
+
- \`memory_index\` - only for debugging
|
|
35
|
+
|
|
36
|
+
## Storing Facts (DO use this)
|
|
31
37
|
\`\`\`
|
|
32
38
|
memory_store_fact(
|
|
33
39
|
entity1: "UserService",
|
|
@@ -36,14 +42,7 @@ memory_store_fact(
|
|
|
36
42
|
context: "Password hashing uses bcrypt with 12 rounds"
|
|
37
43
|
)
|
|
38
44
|
\`\`\`
|
|
39
|
-
Store important facts
|
|
40
|
-
- Architectural decisions
|
|
41
|
-
- Code patterns and conventions
|
|
42
|
-
- Dependencies and relationships
|
|
43
|
-
- User preferences learned during conversation
|
|
44
|
-
|
|
45
|
-
### Context Injection
|
|
46
|
-
Context is automatically injected at the start of each session based on the current project. Check \`~/.claudetools/session-context.md\` for project-specific context.
|
|
45
|
+
Store important facts when you learn something concrete. The \`post-tool-use\` hook also extracts facts automatically.
|
|
47
46
|
|
|
48
47
|
## Task Management
|
|
49
48
|
|
|
@@ -120,10 +119,11 @@ codedna_generate_api({
|
|
|
120
119
|
|
|
121
120
|
## Best Practices
|
|
122
121
|
|
|
123
|
-
1. **
|
|
124
|
-
2. **Store decisions** -
|
|
122
|
+
1. **Trust auto-injection** - Context is injected automatically, don't call memory_search
|
|
123
|
+
2. **Store decisions** - Use \`memory_store_fact\` for architectural choices
|
|
125
124
|
3. **Use task tracking** - Break complex work into tasks
|
|
126
125
|
4. **Use CodeDNA for APIs** - Generate instead of write (99% token savings)
|
|
126
|
+
5. **Minimize tool calls** - Every MCP call costs context tokens
|
|
127
127
|
${SECTION_END}
|
|
128
128
|
`;
|
|
129
129
|
/**
|
|
@@ -134,31 +134,19 @@ export function getProjectTemplate(projectId, projectName) {
|
|
|
134
134
|
${SECTION_START}
|
|
135
135
|
# Project: ${projectName}
|
|
136
136
|
|
|
137
|
-
This project is registered with ClaudeTools Memory.
|
|
138
|
-
|
|
139
137
|
**Project ID:** \`${projectId}\`
|
|
140
138
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
Use memory tools to search and store project-specific context:
|
|
139
|
+
Context is **auto-injected** via hooks. Only use \`memory_store_fact\` to store new facts:
|
|
144
140
|
|
|
145
141
|
\`\`\`
|
|
146
|
-
# Search this project's memory
|
|
147
|
-
memory_search(query: "your search", project_id: "${projectId}")
|
|
148
|
-
|
|
149
|
-
# Store a project fact
|
|
150
142
|
memory_store_fact(
|
|
151
143
|
entity1: "ComponentName",
|
|
152
144
|
relationship: "IMPLEMENTS",
|
|
153
145
|
entity2: "PatternName",
|
|
154
|
-
context: "
|
|
146
|
+
context: "Why this decision was made",
|
|
155
147
|
project_id: "${projectId}"
|
|
156
148
|
)
|
|
157
149
|
\`\`\`
|
|
158
|
-
|
|
159
|
-
## Session Context
|
|
160
|
-
|
|
161
|
-
Project-specific context is injected automatically. Check \`~/.claudetools/session-context.md\` for current context.
|
|
162
150
|
${SECTION_END}
|
|
163
151
|
`;
|
|
164
152
|
}
|
|
@@ -67,136 +67,42 @@ function buildIdentitySection(worker) {
|
|
|
67
67
|
function buildBehavioralSection(taskId) {
|
|
68
68
|
return `<!-- Layer 2: Behavioral Guidelines -->
|
|
69
69
|
<behavioral_guidelines>
|
|
70
|
-
<
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
→ Saves 95-99% tokens vs manual coding
|
|
84
|
-
→ Generates production-ready code with validation, auth, tests
|
|
85
|
-
|
|
86
|
-
ONLY write code manually when:
|
|
87
|
-
- Logic is too complex for generation
|
|
88
|
-
- Modifying existing code (not creating new)
|
|
89
|
-
- Custom business rules that can't be templated
|
|
90
|
-
</behavior>
|
|
91
|
-
|
|
92
|
-
<behavior id="tool_first" priority="MANDATORY">
|
|
93
|
-
BEFORE writing code, use available tools:
|
|
94
|
-
|
|
95
|
-
1. codebase_map: START HERE - Get project overview
|
|
96
|
-
→ Understand project structure and key entry points
|
|
97
|
-
→ Identify frameworks and patterns in use
|
|
98
|
-
→ Find relevant directories before diving in
|
|
99
|
-
→ Use BEFORE Grep/Glob for unfamiliar code
|
|
100
|
-
|
|
101
|
-
2. memory_search: Check for existing patterns and decisions
|
|
102
|
-
→ "How was authentication implemented?"
|
|
103
|
-
→ "What patterns are used for X?"
|
|
104
|
-
|
|
105
|
-
3. codebase_find: Find specific symbols/files
|
|
106
|
-
→ Search for existing code to extend/adapt
|
|
107
|
-
|
|
108
|
-
4. codebase_context: Understand file dependencies
|
|
109
|
-
→ See what a file imports/exports
|
|
110
|
-
|
|
111
|
-
5. docs_get: Retrieve cached documentation
|
|
112
|
-
→ Get up-to-date API references
|
|
113
|
-
</behavior>
|
|
114
|
-
|
|
115
|
-
<behavior id="minimal_changes" priority="IMPORTANT">
|
|
116
|
-
Make ONLY the changes required for this task.
|
|
117
|
-
NEVER:
|
|
118
|
-
- Refactor unrelated code
|
|
119
|
-
- Add features not requested
|
|
120
|
-
- Over-engineer solutions
|
|
121
|
-
- Add unnecessary abstractions
|
|
122
|
-
</behavior>
|
|
123
|
-
</core_behaviors>
|
|
70
|
+
<behavior id="codedna_first" priority="MANDATORY">
|
|
71
|
+
BEFORE writing code: codedna_list_generators() → check if task matches generator
|
|
72
|
+
Entity DSL: "User(email:string:unique, password:string:hashed)"
|
|
73
|
+
Only write manually for: complex logic, modifications, custom business rules
|
|
74
|
+
</behavior>
|
|
75
|
+
|
|
76
|
+
<behavior id="tool_first" priority="MANDATORY">
|
|
77
|
+
Tool precedence: codebase_map → memory_search → codebase_find → docs_get
|
|
78
|
+
</behavior>
|
|
79
|
+
|
|
80
|
+
<behavior id="minimal_changes" priority="IMPORTANT">
|
|
81
|
+
Make ONLY task-required changes. No refactoring, features, or abstractions.
|
|
82
|
+
</behavior>
|
|
124
83
|
</behavioral_guidelines>`;
|
|
125
84
|
}
|
|
126
85
|
function buildStandardsSection() {
|
|
127
86
|
return `<!-- Layer 3: Standards & Best Practices -->
|
|
128
87
|
<standards>
|
|
129
88
|
<code_quality>
|
|
130
|
-
|
|
131
|
-
- Prefer explicit over implicit
|
|
132
|
-
- Validate inputs at system boundaries
|
|
133
|
-
- Handle errors with clear messages
|
|
89
|
+
Australian English. Explicit over implicit. Validate boundaries. Clear errors.
|
|
134
90
|
</code_quality>
|
|
135
91
|
|
|
136
|
-
<formatting>
|
|
137
|
-
- Use Australian English in comments and messages
|
|
138
|
-
- Follow existing code style in the project
|
|
139
|
-
- Include file paths with line numbers in references
|
|
140
|
-
</formatting>
|
|
141
|
-
|
|
142
92
|
<memory_usage priority="CRITICAL">
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
- Project discoveries: Anti-patterns found, bugs fixed, patterns discovered
|
|
147
|
-
- User preferences: Workflows, communication styles learned through interaction
|
|
148
|
-
- Architectural decisions WHY: Reasoning behind choices, rejected alternatives
|
|
149
|
-
- Solutions that worked: Specific implementations with context
|
|
150
|
-
|
|
151
|
-
❌ DON'T STORE (generic documentation):
|
|
152
|
-
- Tool behavior: How the tool system works (already in API docs)
|
|
153
|
-
- Universal knowledge: Programming concepts, language features
|
|
154
|
-
- Temporary state: Current task status, session-specific data
|
|
155
|
-
|
|
156
|
-
Rule of thumb: "Would I need to rediscover this in 3 months?"
|
|
157
|
-
→ YES = store it (learned pattern, specific to this context)
|
|
158
|
-
→ NO = don't store it (universal knowledge, temporary state)
|
|
93
|
+
Store: project discoveries, user preferences, decision rationale, working solutions
|
|
94
|
+
Don't store: tool behavior, universal knowledge, temporary state
|
|
95
|
+
Rule: "Would I rediscover this in 3 months?" → YES = store
|
|
159
96
|
</memory_usage>
|
|
160
97
|
|
|
161
98
|
<documentation_files priority="MANDATORY">
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
- docs/ → Project documentation, guides, specs
|
|
166
|
-
- docs/research/ → Research notes, analysis, investigations
|
|
167
|
-
- docs/decisions/ → Architecture Decision Records (ADRs)
|
|
168
|
-
- CHANGELOG.md → Only in project root
|
|
169
|
-
- README.md → Only in project root or package roots
|
|
170
|
-
|
|
171
|
-
NAMING CONVENTIONS:
|
|
172
|
-
- Use lowercase with hyphens: user-authentication-guide.md
|
|
173
|
-
- NEVER use spaces or underscores in filenames
|
|
174
|
-
- Include date prefix for time-sensitive docs: YYYY-MM-DD-topic.md
|
|
175
|
-
Example: 2025-12-05-api-migration-plan.md
|
|
176
|
-
- Research docs: YYYY-MM-DD-research-topic.md
|
|
177
|
-
- Decision records: NNNN-decision-title.md (e.g., 0001-use-jwt-auth.md)
|
|
178
|
-
|
|
179
|
-
ANTI-PATTERNS (NEVER DO):
|
|
180
|
-
- Creating PLAN.md, NOTES.md, TODO.md in project root
|
|
181
|
-
- Random capitalised filenames like IMPLEMENTATION_GUIDE.md
|
|
182
|
-
- Nested docs in src/ or lib/ directories
|
|
183
|
-
- Multiple README files outside package roots
|
|
184
|
-
- Temporary docs without dates (impossible to clean up later)
|
|
185
|
-
|
|
186
|
-
BEFORE CREATING ANY .md FILE:
|
|
187
|
-
1. Check if docs/ directory exists - create if needed
|
|
188
|
-
2. Determine correct subdirectory (research/, decisions/, etc.)
|
|
189
|
-
3. Use proper naming convention with date if temporal
|
|
190
|
-
4. Ask user if uncertain about placement
|
|
99
|
+
Structure: docs/research/, docs/decisions/, README.md/CHANGELOG.md in root only
|
|
100
|
+
Naming: lowercase-with-hyphens.md, YYYY-MM-DD-topic.md for temporal docs
|
|
101
|
+
Never: PLAN.md/NOTES.md in root, random caps, nested in src/, undated temp files
|
|
191
102
|
</documentation_files>
|
|
192
103
|
|
|
193
104
|
<completion_summary>
|
|
194
|
-
|
|
195
|
-
- Implementation: What you built/changed
|
|
196
|
-
- Files: List of modified files with paths
|
|
197
|
-
- Decisions: Any architectural choices made
|
|
198
|
-
- Testing: How changes were verified
|
|
199
|
-
- Notes: Caveats, limitations, follow-up needed
|
|
105
|
+
Include: implementation, files modified, decisions, testing, notes
|
|
200
106
|
</completion_summary>
|
|
201
107
|
</standards>`;
|
|
202
108
|
}
|
|
@@ -204,31 +110,10 @@ function buildDomainSection(worker) {
|
|
|
204
110
|
return `<!-- Layer 4: Domain Knowledge -->
|
|
205
111
|
<domain_knowledge>
|
|
206
112
|
<codedna_capabilities>
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
4. Match detected framework to generator capabilities
|
|
212
|
-
5. If no match, ASK the user which framework to use
|
|
213
|
-
|
|
214
|
-
ENTITY DSL FORMAT:
|
|
215
|
-
EntityName(field:type:constraint, field:type:constraint, ...)
|
|
216
|
-
|
|
217
|
-
TYPES:
|
|
218
|
-
- string, integer, decimal, boolean, datetime
|
|
219
|
-
- ref(EntityName) - foreign key reference
|
|
220
|
-
- enum(val1|val2|val3) - enumeration
|
|
221
|
-
|
|
222
|
-
CONSTRAINTS:
|
|
223
|
-
- unique, required, min(n), max(n), hashed, default(value)
|
|
224
|
-
- UI hints: textarea, switch, radio (for form rendering)
|
|
225
|
-
|
|
226
|
-
WORKFLOW:
|
|
227
|
-
1. codedna_list_generators() → discover capabilities
|
|
228
|
-
2. codedna_validate_spec(spec) → validate DSL syntax
|
|
229
|
-
3. codedna_generate_*(spec, framework, options) → generate code
|
|
230
|
-
|
|
231
|
-
DO NOT assume frameworks exist - always discover via codedna_list_generators
|
|
113
|
+
Discovery: codedna_list_generators() → detect framework → validate spec → generate
|
|
114
|
+
DSL: EntityName(field:type:constraint, ...)
|
|
115
|
+
Types: string, integer, decimal, boolean, datetime, ref(Entity), enum(a|b)
|
|
116
|
+
Constraints: unique, required, min(n), max(n), hashed, default(v), textarea, switch
|
|
232
117
|
</codedna_capabilities>
|
|
233
118
|
|
|
234
119
|
<worker_expertise>
|
|
@@ -239,26 +124,9 @@ function buildDomainSection(worker) {
|
|
|
239
124
|
function buildCrossCuttingSection() {
|
|
240
125
|
return `<!-- Layer 5: Cross-Cutting Concerns -->
|
|
241
126
|
<cross_cutting_concerns>
|
|
242
|
-
<error_handling>
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
- Log errors with sufficient context for debugging
|
|
246
|
-
- Provide actionable guidance to users
|
|
247
|
-
</error_handling>
|
|
248
|
-
|
|
249
|
-
<security>
|
|
250
|
-
CRITICAL: Follow OWASP Top 10 guidelines
|
|
251
|
-
- Never expose sensitive data (API keys, passwords, tokens)
|
|
252
|
-
- Sanitize all user inputs
|
|
253
|
-
- Use parameterized queries (never string concat for SQL)
|
|
254
|
-
- Apply principle of least privilege
|
|
255
|
-
</security>
|
|
256
|
-
|
|
257
|
-
<performance>
|
|
258
|
-
- Don't optimise prematurely
|
|
259
|
-
- Consider token efficiency in prompts
|
|
260
|
-
- Use CodeDNA for boilerplate (saves 95%+ tokens)
|
|
261
|
-
</performance>
|
|
127
|
+
<error_handling>Validate boundaries. Fail fast. Clear messages. Actionable guidance.</error_handling>
|
|
128
|
+
<security>OWASP Top 10. No exposed secrets. Sanitize inputs. Parameterized queries. Least privilege.</security>
|
|
129
|
+
<performance>No premature optimization. Token efficiency. CodeDNA for boilerplate.</performance>
|
|
262
130
|
</cross_cutting_concerns>`;
|
|
263
131
|
}
|
|
264
132
|
function buildTaskSection(task, epicContext) {
|
|
@@ -309,54 +177,19 @@ function buildSiblingSection(siblingTasks) {
|
|
|
309
177
|
function buildProtocolSection(taskId) {
|
|
310
178
|
return `<!-- Protocol -->
|
|
311
179
|
<protocol>
|
|
312
|
-
<step number="1"
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
</step>
|
|
316
|
-
|
|
317
|
-
<step number="2" action="CHECK_CODEDNA">
|
|
318
|
-
IF task involves creating entities/APIs:
|
|
319
|
-
→ Look for Entity DSL in task description
|
|
320
|
-
→ Call codedna_generate_api with the spec
|
|
321
|
-
→ Review generated code, make adjustments if needed
|
|
322
|
-
|
|
323
|
-
IF task is modification/complex logic:
|
|
324
|
-
→ Use memory_search and codebase_find first
|
|
325
|
-
→ Write code manually only when necessary
|
|
326
|
-
</step>
|
|
327
|
-
|
|
328
|
-
<step number="3" action="IMPLEMENT">
|
|
329
|
-
Complete the requirements described in the task.
|
|
330
|
-
Make minimal changes. Don't over-engineer.
|
|
331
|
-
</step>
|
|
332
|
-
|
|
333
|
-
<step number="4" action="COMPLETE">
|
|
334
|
-
Call: task_complete(task_id="${taskId}", summary="detailed summary")
|
|
335
|
-
|
|
336
|
-
Include in summary:
|
|
337
|
-
- What you implemented
|
|
338
|
-
- Files created/modified
|
|
339
|
-
- Decisions made
|
|
340
|
-
- How you verified it works
|
|
341
|
-
</step>
|
|
180
|
+
<step number="1">task_start(task_id="${taskId}")</step>
|
|
181
|
+
<step number="2">Check CodeDNA for entities/APIs, else use tools (memory_search, codebase_find)</step>
|
|
182
|
+
<step number="3">Implement requirements. Minimal changes.</step>
|
|
183
|
+
<step number="4">task_complete(task_id="${taskId}", summary="impl, files, decisions, testing")</step>
|
|
342
184
|
|
|
343
185
|
<error_handling>
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
1. Log error:
|
|
347
|
-
task_add_context(task_id="${taskId}", context_type="work_log",
|
|
348
|
-
content="ERROR: description", added_by="your-agent-id")
|
|
349
|
-
|
|
350
|
-
2. Release task:
|
|
351
|
-
task_release(task_id="${taskId}", agent_id="your-agent-id",
|
|
352
|
-
new_status="blocked", work_log="summary of issue")
|
|
353
|
-
|
|
354
|
-
Do NOT mark incomplete work as complete.
|
|
186
|
+
Blocking issues: task_add_context + task_release(status="blocked")
|
|
187
|
+
Never mark incomplete work as complete.
|
|
355
188
|
</error_handling>
|
|
356
189
|
</protocol>
|
|
357
190
|
|
|
358
191
|
---
|
|
359
|
-
**Begin work now.
|
|
192
|
+
**Begin work now. Call task_start first!**`;
|
|
360
193
|
}
|
|
361
194
|
/**
|
|
362
195
|
* Build a minimal prompt for simple tasks
|