monomind 1.6.9 → 1.7.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/.claude/commands/monomind-createtask.md +73 -111
- package/.claude/commands/monomind-do.md +227 -115
- package/.claude/commands/monomind-idea.md +29 -103
- package/.claude/commands/monomind-improve.md +28 -100
- package/.claude/helpers/graphify-freshen.cjs +12 -97
- package/.claude/helpers/hook-handler.cjs +16 -0
- package/.claude/helpers/statusline.cjs +89 -65
- package/.claude/settings.local.json +2 -1
- package/.claude/skills/monomind-task-engine/SKILL.md +358 -0
- package/package.json +1 -1
- package/packages/@monomind/cli/dist/src/commands/doctor.js +72 -10
- package/packages/@monomind/cli/dist/src/init/executor.js +152 -24
- package/packages/@monomind/cli/dist/src/init/shared-instructions-generator.d.ts +38 -0
- package/packages/@monomind/cli/dist/src/init/shared-instructions-generator.js +571 -0
- package/packages/@monomind/cli/dist/src/init/types.d.ts +1 -1
- package/packages/@monomind/cli/dist/src/mcp-tools/graphify-tools.d.ts +4 -4
- package/packages/@monomind/cli/dist/src/mcp-tools/graphify-tools.js +84 -60
- package/packages/@monomind/cli/package.json +1 -1
|
@@ -11,6 +11,7 @@ import { dirname } from 'path';
|
|
|
11
11
|
const __filename = fileURLToPath(import.meta.url);
|
|
12
12
|
const __dirname = dirname(__filename);
|
|
13
13
|
import { detectPlatform, DEFAULT_INIT_OPTIONS } from './types.js';
|
|
14
|
+
import { writeSharedInstructions } from './shared-instructions-generator.js';
|
|
14
15
|
import { generateSettingsJson, generateSettings } from './settings-generator.js';
|
|
15
16
|
import { generateMCPJson } from './mcp-generator.js';
|
|
16
17
|
import { generateStatuslineScript } from './statusline-generator.js';
|
|
@@ -66,7 +67,7 @@ const SKILLS_MAP = {
|
|
|
66
67
|
const COMMANDS_MAP = {
|
|
67
68
|
core: [
|
|
68
69
|
'monomind-help.md', 'monomind-swarm.md', 'monomind-memory.md',
|
|
69
|
-
'monomind-do.md', 'monomind-idea.md', 'monomind-createtask.md', 'monomind-repeat.md',
|
|
70
|
+
'monomind-do.md', 'monomind-idea.md', 'monomind-improve.md', 'monomind-createtask.md', 'monomind-repeat.md',
|
|
70
71
|
'mastermind.md', 'list-agents.md', 'use-agent.md',
|
|
71
72
|
'metrics.md', 'tokens.md', 'browse.md', 'sparc.md', 'ts.md',
|
|
72
73
|
],
|
|
@@ -281,12 +282,18 @@ export async function executeInit(options) {
|
|
|
281
282
|
if (options.components.claudeMd) {
|
|
282
283
|
await writeClaudeMd(targetDir, options, result);
|
|
283
284
|
}
|
|
285
|
+
// Generate .agents/shared_instructions.md + seed project memory
|
|
286
|
+
writeSharedInstructions(targetDir, options.force, result);
|
|
284
287
|
// Count enabled hooks
|
|
285
288
|
result.summary.hooksEnabled = countEnabledHooks(options);
|
|
286
289
|
// Build knowledge graph in background (non-blocking)
|
|
287
290
|
if (options.components.graphify) {
|
|
288
291
|
await initKnowledgeGraph(targetDir, result);
|
|
289
292
|
}
|
|
293
|
+
// Start daemon with background workers (non-blocking)
|
|
294
|
+
await startDaemonBackground(targetDir, result);
|
|
295
|
+
// Run doctor auto-fix (non-blocking, best-effort)
|
|
296
|
+
await runDoctorFix(targetDir, result);
|
|
290
297
|
}
|
|
291
298
|
catch (error) {
|
|
292
299
|
result.success = false;
|
|
@@ -295,39 +302,129 @@ export async function executeInit(options) {
|
|
|
295
302
|
return result;
|
|
296
303
|
}
|
|
297
304
|
/**
|
|
298
|
-
*
|
|
299
|
-
*
|
|
300
|
-
|
|
305
|
+
* Ensure graphify (Python knowledge graph engine) is installed.
|
|
306
|
+
* Tries uv first, falls back to pip. Non-fatal if neither works.
|
|
307
|
+
*/
|
|
308
|
+
async function ensureGraphifyInstalled(result) {
|
|
309
|
+
const { execSync } = await import('child_process');
|
|
310
|
+
try {
|
|
311
|
+
execSync('graphify --help', { encoding: 'utf8', stdio: 'ignore' });
|
|
312
|
+
return true;
|
|
313
|
+
}
|
|
314
|
+
catch {
|
|
315
|
+
const installers = ['uv tool install graphifyy', 'pip install graphifyy'];
|
|
316
|
+
for (const cmd of installers) {
|
|
317
|
+
try {
|
|
318
|
+
execSync(cmd, { encoding: 'utf8', stdio: 'ignore', timeout: 120000 });
|
|
319
|
+
result.created.files.push('graphify (installed via ' + cmd.split(' ')[0] + ')');
|
|
320
|
+
return true;
|
|
321
|
+
}
|
|
322
|
+
catch { /* try next */ }
|
|
323
|
+
}
|
|
324
|
+
result.skipped.push('graphify: could not auto-install (run: uv tool install graphifyy)');
|
|
325
|
+
return false;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Initialize graphify fully: install skill, git hooks, build graph, install watch.
|
|
330
|
+
* Fire-and-forget for the graph build — init does not wait for it to complete.
|
|
331
|
+
* Non-fatal: if graphify is unavailable the step is simply skipped.
|
|
301
332
|
*/
|
|
302
333
|
async function initKnowledgeGraph(targetDir, result) {
|
|
334
|
+
const installed = await ensureGraphifyInstalled(result);
|
|
335
|
+
if (!installed)
|
|
336
|
+
return;
|
|
337
|
+
const { execSync, spawn } = await import('child_process');
|
|
338
|
+
const { mkdirSync } = await import('fs');
|
|
339
|
+
const outputDir = path.join(targetDir, '.monomind', 'graph');
|
|
340
|
+
mkdirSync(outputDir, { recursive: true });
|
|
341
|
+
// 1. Install graphify skill into Claude Code config
|
|
303
342
|
try {
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
stdio: ['pipe', 'ignore', 'ignore'],
|
|
343
|
+
execSync('graphify claude install', { cwd: targetDir, stdio: 'ignore', timeout: 10000 });
|
|
344
|
+
result.created.files.push('graphify claude skill (installed)');
|
|
345
|
+
}
|
|
346
|
+
catch { /* non-fatal */ }
|
|
347
|
+
// 2. Install git hooks (auto-rebuild on commit)
|
|
348
|
+
try {
|
|
349
|
+
execSync('graphify hook install', { cwd: targetDir, stdio: 'ignore', timeout: 10000 });
|
|
350
|
+
result.created.files.push('graphify git hooks (post-commit, post-checkout)');
|
|
351
|
+
}
|
|
352
|
+
catch { /* non-fatal */ }
|
|
353
|
+
// 3. Build knowledge graph in background (fire-and-forget)
|
|
354
|
+
try {
|
|
355
|
+
const child = spawn('graphify', ['update', targetDir], {
|
|
356
|
+
stdio: 'ignore',
|
|
319
357
|
detached: true,
|
|
320
358
|
cwd: targetDir,
|
|
321
359
|
});
|
|
322
|
-
// Write the script to stdin then close so node processes it.
|
|
323
|
-
child.stdin?.write(script);
|
|
324
|
-
child.stdin?.end();
|
|
325
360
|
child.unref();
|
|
326
361
|
result.created.files.push('.monomind/graph/ (knowledge graph building in background)');
|
|
327
362
|
}
|
|
328
363
|
catch (_err) {
|
|
329
|
-
|
|
330
|
-
|
|
364
|
+
result.skipped.push('knowledge graph: graphify update failed');
|
|
365
|
+
}
|
|
366
|
+
// 4. Start graphify watch daemon (live graph updates on file save)
|
|
367
|
+
try {
|
|
368
|
+
const watchChild = spawn('graphify', ['watch', targetDir], {
|
|
369
|
+
stdio: 'ignore',
|
|
370
|
+
detached: true,
|
|
371
|
+
cwd: targetDir,
|
|
372
|
+
});
|
|
373
|
+
watchChild.unref();
|
|
374
|
+
// Store PID so it can be stopped later
|
|
375
|
+
const { writeFileSync } = await import('fs');
|
|
376
|
+
const pidPath = path.join(outputDir, 'watch.pid');
|
|
377
|
+
writeFileSync(pidPath, String(watchChild.pid));
|
|
378
|
+
result.created.files.push('graphify watch (live graph updates on file save)');
|
|
379
|
+
}
|
|
380
|
+
catch { /* non-fatal */ }
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Start the monomind daemon with background workers.
|
|
384
|
+
* Non-fatal: if daemon fails to start, init continues.
|
|
385
|
+
*/
|
|
386
|
+
async function startDaemonBackground(targetDir, result) {
|
|
387
|
+
try {
|
|
388
|
+
const { execSync } = await import('child_process');
|
|
389
|
+
// Check if daemon is already running
|
|
390
|
+
const pidFile = path.join(targetDir, '.monomind', 'daemon.pid');
|
|
391
|
+
const { existsSync, readFileSync } = await import('fs');
|
|
392
|
+
if (existsSync(pidFile)) {
|
|
393
|
+
const pid = parseInt(readFileSync(pidFile, 'utf8').trim(), 10);
|
|
394
|
+
try {
|
|
395
|
+
process.kill(pid, 0);
|
|
396
|
+
result.skipped.push('daemon: already running (PID ' + pid + ')');
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
catch { /* stale PID, continue */ }
|
|
400
|
+
}
|
|
401
|
+
execSync('npx monomind@latest daemon start --background', {
|
|
402
|
+
cwd: targetDir,
|
|
403
|
+
stdio: 'ignore',
|
|
404
|
+
timeout: 15000,
|
|
405
|
+
});
|
|
406
|
+
result.created.files.push('monomind daemon (background workers started)');
|
|
407
|
+
}
|
|
408
|
+
catch {
|
|
409
|
+
result.skipped.push('daemon: could not auto-start (run: monomind daemon start)');
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Run doctor --install to auto-fix any remaining issues.
|
|
414
|
+
* Non-fatal: best-effort health check and auto-install.
|
|
415
|
+
*/
|
|
416
|
+
async function runDoctorFix(targetDir, result) {
|
|
417
|
+
try {
|
|
418
|
+
const { execSync } = await import('child_process');
|
|
419
|
+
execSync('npx monomind@latest doctor --install', {
|
|
420
|
+
cwd: targetDir,
|
|
421
|
+
stdio: 'ignore',
|
|
422
|
+
timeout: 120000,
|
|
423
|
+
});
|
|
424
|
+
result.created.files.push('doctor --install (health check + auto-fix)');
|
|
425
|
+
}
|
|
426
|
+
catch {
|
|
427
|
+
result.skipped.push('doctor: auto-fix skipped (run: monomind doctor --install)');
|
|
331
428
|
}
|
|
332
429
|
}
|
|
333
430
|
/**
|
|
@@ -1811,6 +1908,37 @@ async function writeClaudeMd(targetDir, options, result) {
|
|
|
1811
1908
|
catch {
|
|
1812
1909
|
// Non-critical — global CLAUDE.md is best-effort
|
|
1813
1910
|
}
|
|
1911
|
+
// Also inject the token-display hook into ~/.claude/settings.json
|
|
1912
|
+
const globalSettingsPath = path.join(globalClaudeDir, 'settings.json');
|
|
1913
|
+
try {
|
|
1914
|
+
if (!fs.existsSync(globalClaudeDir)) {
|
|
1915
|
+
fs.mkdirSync(globalClaudeDir, { recursive: true });
|
|
1916
|
+
}
|
|
1917
|
+
let globalSettings = {};
|
|
1918
|
+
if (fs.existsSync(globalSettingsPath)) {
|
|
1919
|
+
try {
|
|
1920
|
+
globalSettings = JSON.parse(fs.readFileSync(globalSettingsPath, 'utf-8'));
|
|
1921
|
+
}
|
|
1922
|
+
catch { /* malformed JSON — start fresh */ }
|
|
1923
|
+
}
|
|
1924
|
+
// Inject SessionStart token hook if not already present
|
|
1925
|
+
const hooks = globalSettings.hooks ?? {};
|
|
1926
|
+
const sessionStartHooks = hooks['SessionStart'] ?? [];
|
|
1927
|
+
const tokenHookCommand = 'npx --yes monomind@latest tokens today';
|
|
1928
|
+
const alreadyPresent = sessionStartHooks.some(entry => Array.isArray(entry.hooks) && entry.hooks.some(h => h.command === tokenHookCommand));
|
|
1929
|
+
if (!alreadyPresent) {
|
|
1930
|
+
sessionStartHooks.push({
|
|
1931
|
+
hooks: [{ type: 'command', command: tokenHookCommand, timeout: 10000 }],
|
|
1932
|
+
});
|
|
1933
|
+
hooks['SessionStart'] = sessionStartHooks;
|
|
1934
|
+
globalSettings.hooks = hooks;
|
|
1935
|
+
fs.writeFileSync(globalSettingsPath, JSON.stringify(globalSettings, null, 2), 'utf-8');
|
|
1936
|
+
result.created.files.push('~/.claude/settings.json (added token hook)');
|
|
1937
|
+
}
|
|
1938
|
+
}
|
|
1939
|
+
catch {
|
|
1940
|
+
// Non-critical — global settings hook is best-effort
|
|
1941
|
+
}
|
|
1814
1942
|
}
|
|
1815
1943
|
}
|
|
1816
1944
|
/**
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Instructions Generator
|
|
3
|
+
*
|
|
4
|
+
* Auto-detects project profile and generates:
|
|
5
|
+
* 1. .agents/shared_instructions.md — prepended to every agent prompt
|
|
6
|
+
* 2. Memory seeds — pre-loaded into AgentDB so agents start with project best practices
|
|
7
|
+
*/
|
|
8
|
+
import type { InitResult } from './types.js';
|
|
9
|
+
export interface ProjectProfile {
|
|
10
|
+
name: string;
|
|
11
|
+
description: string;
|
|
12
|
+
language: 'typescript' | 'javascript' | 'python' | 'go' | 'rust' | 'unknown';
|
|
13
|
+
framework: string[];
|
|
14
|
+
packageManager: 'pnpm' | 'npm' | 'yarn' | 'bun' | 'cargo' | 'poetry' | 'uv' | 'pip' | 'unknown';
|
|
15
|
+
testFramework: string[];
|
|
16
|
+
buildTool: string[];
|
|
17
|
+
isMonorepo: boolean;
|
|
18
|
+
monorepoTool: string;
|
|
19
|
+
database: string[];
|
|
20
|
+
hasDocker: boolean;
|
|
21
|
+
hasCi: boolean;
|
|
22
|
+
ciTool: string;
|
|
23
|
+
maxFileLines: number | null;
|
|
24
|
+
srcDir: string;
|
|
25
|
+
testDir: string;
|
|
26
|
+
version: string;
|
|
27
|
+
isPublicNpm: boolean;
|
|
28
|
+
}
|
|
29
|
+
export declare function detectProjectProfile(cwd: string): ProjectProfile;
|
|
30
|
+
export declare function generateSharedInstructions(profile: ProjectProfile): string;
|
|
31
|
+
export interface MemorySeed {
|
|
32
|
+
key: string;
|
|
33
|
+
value: string;
|
|
34
|
+
namespace: string;
|
|
35
|
+
}
|
|
36
|
+
export declare function generateMemorySeeds(profile: ProjectProfile): MemorySeed[];
|
|
37
|
+
export declare function writeSharedInstructions(cwd: string, force: boolean, result: InitResult): void;
|
|
38
|
+
//# sourceMappingURL=shared-instructions-generator.d.ts.map
|