memtrace-skills 0.7.10
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/commands/doctor.d.ts +16 -0
- package/dist/commands/doctor.js +199 -0
- package/dist/commands/enterprise-install.d.ts +7 -0
- package/dist/commands/enterprise-install.js +129 -0
- package/dist/commands/install.d.ts +9 -0
- package/dist/commands/install.js +104 -0
- package/dist/commands/picker.d.ts +6 -0
- package/dist/commands/picker.js +22 -0
- package/dist/commands/rail-install.d.ts +7 -0
- package/dist/commands/rail-install.js +37 -0
- package/dist/fs-safe.d.ts +21 -0
- package/dist/fs-safe.js +35 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +87 -0
- package/dist/rail-install.d.ts +20 -0
- package/dist/rail-install.js +183 -0
- package/dist/skills.d.ts +17 -0
- package/dist/skills.js +64 -0
- package/dist/transformers/claude.d.ts +71 -0
- package/dist/transformers/claude.js +702 -0
- package/dist/transformers/codex.d.ts +8 -0
- package/dist/transformers/codex.js +294 -0
- package/dist/transformers/cursor.d.ts +7 -0
- package/dist/transformers/cursor.js +124 -0
- package/dist/transformers/gemini.d.ts +3 -0
- package/dist/transformers/gemini.js +78 -0
- package/dist/transformers/hermes.d.ts +5 -0
- package/dist/transformers/hermes.js +136 -0
- package/dist/transformers/index.d.ts +14 -0
- package/dist/transformers/index.js +24 -0
- package/dist/transformers/kiro.d.ts +2 -0
- package/dist/transformers/kiro.js +69 -0
- package/dist/transformers/opencode.d.ts +2 -0
- package/dist/transformers/opencode.js +77 -0
- package/dist/transformers/rail-hooks.d.ts +56 -0
- package/dist/transformers/rail-hooks.js +303 -0
- package/dist/transformers/shared.d.ts +18 -0
- package/dist/transformers/shared.js +129 -0
- package/dist/transformers/types.d.ts +40 -0
- package/dist/transformers/types.js +1 -0
- package/dist/transformers/vscode.d.ts +3 -0
- package/dist/transformers/vscode.js +53 -0
- package/dist/transformers/windsurf.d.ts +3 -0
- package/dist/transformers/windsurf.js +43 -0
- package/dist/utils.d.ts +5 -0
- package/dist/utils.js +22 -0
- package/package.json +50 -0
- package/plugins/memtrace-skills/.claude-plugin/plugin.json +23 -0
- package/plugins/memtrace-skills/references/mcp-parameters.md +302 -0
- package/plugins/memtrace-skills/skills/memtrace-api-topology/SKILL.md +58 -0
- package/plugins/memtrace-skills/skills/memtrace-change-impact-analysis/SKILL.md +75 -0
- package/plugins/memtrace-skills/skills/memtrace-cochange/SKILL.md +71 -0
- package/plugins/memtrace-skills/skills/memtrace-code-review/SKILL.md +41 -0
- package/plugins/memtrace-skills/skills/memtrace-codebase-exploration/SKILL.md +94 -0
- package/plugins/memtrace-skills/skills/memtrace-continuous-memory/SKILL.md +96 -0
- package/plugins/memtrace-skills/skills/memtrace-episode-replay/SKILL.md +94 -0
- package/plugins/memtrace-skills/skills/memtrace-evolution/SKILL.md +128 -0
- package/plugins/memtrace-skills/skills/memtrace-first/SKILL.md +194 -0
- package/plugins/memtrace-skills/skills/memtrace-fleet-coordination/SKILL.md +80 -0
- package/plugins/memtrace-skills/skills/memtrace-fleet-first/SKILL.md +125 -0
- package/plugins/memtrace-skills/skills/memtrace-fleet-publish-intent/SKILL.md +48 -0
- package/plugins/memtrace-skills/skills/memtrace-fleet-record-episode/SKILL.md +44 -0
- package/plugins/memtrace-skills/skills/memtrace-fleet-resolve/SKILL.md +54 -0
- package/plugins/memtrace-skills/skills/memtrace-graph/SKILL.md +67 -0
- package/plugins/memtrace-skills/skills/memtrace-impact/SKILL.md +58 -0
- package/plugins/memtrace-skills/skills/memtrace-incident-investigation/SKILL.md +112 -0
- package/plugins/memtrace-skills/skills/memtrace-index/SKILL.md +65 -0
- package/plugins/memtrace-skills/skills/memtrace-quality/SKILL.md +63 -0
- package/plugins/memtrace-skills/skills/memtrace-refactoring-guide/SKILL.md +103 -0
- package/plugins/memtrace-skills/skills/memtrace-relationships/SKILL.md +67 -0
- package/plugins/memtrace-skills/skills/memtrace-search/SKILL.md +93 -0
- package/plugins/memtrace-skills/skills/memtrace-session-continuity/SKILL.md +93 -0
- package/plugins/memtrace-skills/skills/memtrace-style-fingerprint/SKILL.md +105 -0
- package/skills/commands/memtrace-api-topology.md +65 -0
- package/skills/commands/memtrace-cochange.md +76 -0
- package/skills/commands/memtrace-evolution.md +135 -0
- package/skills/commands/memtrace-fleet-publish-intent.md +51 -0
- package/skills/commands/memtrace-fleet-record-episode.md +48 -0
- package/skills/commands/memtrace-fleet-resolve.md +59 -0
- package/skills/commands/memtrace-graph.md +75 -0
- package/skills/commands/memtrace-impact.md +64 -0
- package/skills/commands/memtrace-index.md +71 -0
- package/skills/commands/memtrace-quality.md +69 -0
- package/skills/commands/memtrace-relationships.md +73 -0
- package/skills/commands/memtrace-search.md +93 -0
- package/skills/workflows/memtrace-change-impact-analysis.md +85 -0
- package/skills/workflows/memtrace-code-review.md +48 -0
- package/skills/workflows/memtrace-codebase-exploration.md +108 -0
- package/skills/workflows/memtrace-continuous-memory.md +104 -0
- package/skills/workflows/memtrace-episode-replay.md +100 -0
- package/skills/workflows/memtrace-first.md +194 -0
- package/skills/workflows/memtrace-fleet-coordination.md +87 -0
- package/skills/workflows/memtrace-fleet-first.md +132 -0
- package/skills/workflows/memtrace-incident-investigation.md +125 -0
- package/skills/workflows/memtrace-refactoring-guide.md +116 -0
- package/skills/workflows/memtrace-session-continuity.md +98 -0
- package/skills/workflows/memtrace-style-fingerprint.md +111 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { runInstall, runUninstall } from './commands/install.js';
|
|
4
|
+
import { runDoctor } from './commands/doctor.js';
|
|
5
|
+
import { runInstallRail, runUninstallRail } from './commands/rail-install.js';
|
|
6
|
+
import { runEnterpriseInstall } from './commands/enterprise-install.js';
|
|
7
|
+
const program = new Command();
|
|
8
|
+
program
|
|
9
|
+
.name('memtrace-skills')
|
|
10
|
+
.description('Install Memtrace skills and MCP for AI coding agents')
|
|
11
|
+
.version('0.1.0');
|
|
12
|
+
function parseOnly(val) {
|
|
13
|
+
return val.split(',').map(s => s.trim()).filter(Boolean);
|
|
14
|
+
}
|
|
15
|
+
program
|
|
16
|
+
.command('install')
|
|
17
|
+
.description('Install memtrace skills and register MCP for selected agents')
|
|
18
|
+
.option('--only <agents>', 'comma-separated agent names (claude,cursor,codex,gemini,windsurf,vscode,hermes,opencode,kiro)', parseOnly)
|
|
19
|
+
.option('--local', 'install into the current project where the selected agent supports project scope', false)
|
|
20
|
+
.option('--global', 'install globally (~/.claude/, ~/.cursor/, ~/.agents/) [default]', false)
|
|
21
|
+
.option('--skip-mcp', 'write skills only, skip MCP server registration', false)
|
|
22
|
+
.option('--repair', 'alias for install — run after fixing a corrupt settings file')
|
|
23
|
+
.option('-y, --yes', 'non-interactive, accept defaults')
|
|
24
|
+
.action(async (opts) => {
|
|
25
|
+
const options = {
|
|
26
|
+
scope: opts.local ? 'local' : 'global',
|
|
27
|
+
only: opts.only,
|
|
28
|
+
skipMcp: opts.skipMcp,
|
|
29
|
+
yes: opts.yes,
|
|
30
|
+
};
|
|
31
|
+
await runInstall(options);
|
|
32
|
+
});
|
|
33
|
+
program
|
|
34
|
+
.command('doctor')
|
|
35
|
+
.description('Check memtrace install health across all agents')
|
|
36
|
+
.action(async () => {
|
|
37
|
+
process.exit(await runDoctor());
|
|
38
|
+
});
|
|
39
|
+
program
|
|
40
|
+
.command('uninstall')
|
|
41
|
+
.description('Remove memtrace skills and MCP registrations')
|
|
42
|
+
.option('--only <agents>', 'comma-separated agent names', parseOnly)
|
|
43
|
+
.option('--local', 'uninstall from the current project', false)
|
|
44
|
+
.action(async (opts) => {
|
|
45
|
+
await runUninstall({
|
|
46
|
+
scope: opts.local ? 'local' : 'global',
|
|
47
|
+
only: opts.only,
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
program
|
|
51
|
+
.command('install-enterprise')
|
|
52
|
+
.description('Configure Memtrace MCP for self-hosted enterprise MemDB (remote mode)')
|
|
53
|
+
.requiredOption('--seed <path>', 'path to enterprise seed.json from your admin bundle')
|
|
54
|
+
.option('--local', 'write MCP config to the current project', false)
|
|
55
|
+
.option('--binary <path>', 'memtrace executable (default: on PATH)')
|
|
56
|
+
.option('-y, --yes', 'non-interactive')
|
|
57
|
+
.action(async (opts) => {
|
|
58
|
+
await runEnterpriseInstall({
|
|
59
|
+
seedPath: opts.seed,
|
|
60
|
+
scope: opts.local ? 'local' : 'global',
|
|
61
|
+
binary: opts.binary,
|
|
62
|
+
yes: opts.yes,
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
program
|
|
66
|
+
.command('install-rail')
|
|
67
|
+
.description('Wire Memtrace Rail discovery hooks for Claude, Cursor, Codex, Gemini, OpenCode')
|
|
68
|
+
.option('--binary <path>', 'memtrace executable (default: on PATH)')
|
|
69
|
+
.option('--local', 'project-scoped paths where supported', false)
|
|
70
|
+
.action(async (opts) => {
|
|
71
|
+
await runInstallRail({
|
|
72
|
+
binary: opts.binary,
|
|
73
|
+
scope: opts.local ? 'local' : 'global',
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
program
|
|
77
|
+
.command('uninstall-rail')
|
|
78
|
+
.description('Remove Memtrace Rail hooks only (not skills/MCP)')
|
|
79
|
+
.option('--local', 'project-scoped paths where supported', false)
|
|
80
|
+
.action(async (opts) => {
|
|
81
|
+
await runUninstallRail({ scope: opts.local ? 'local' : 'global' });
|
|
82
|
+
});
|
|
83
|
+
// Default: `memtrace-skills` with no subcommand → install with defaults (global, all agents)
|
|
84
|
+
program.action(async () => {
|
|
85
|
+
await runInstall({ scope: 'global' });
|
|
86
|
+
});
|
|
87
|
+
program.parse();
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { InstallContext } from './transformers/types.js';
|
|
2
|
+
export interface RailHostResult {
|
|
3
|
+
host: string;
|
|
4
|
+
registered: boolean;
|
|
5
|
+
path?: string;
|
|
6
|
+
skipped?: string;
|
|
7
|
+
}
|
|
8
|
+
/** Hosts with no Rail hook surface yet (MCP/skills only). */
|
|
9
|
+
export declare const RAIL_UNSUPPORTED: ReadonlyArray<{
|
|
10
|
+
host: string;
|
|
11
|
+
reason: string;
|
|
12
|
+
}>;
|
|
13
|
+
/**
|
|
14
|
+
* Wire Rail discovery hooks for Claude, Cursor, Codex, Gemini, and OpenCode.
|
|
15
|
+
* Idempotent. Does not install skills or MCP — hooks only.
|
|
16
|
+
*/
|
|
17
|
+
export declare function installRailHooks(ctx: InstallContext): RailHostResult[];
|
|
18
|
+
/** Remove only Memtrace-owned Rail hook entries (not skills/MCP). */
|
|
19
|
+
export declare function uninstallRailHooks(ctx: InstallContext): RailHostResult[];
|
|
20
|
+
export declare function printRailInstallSummary(results: RailHostResult[], action: 'installed' | 'removed'): void;
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memtrace Rail hook wiring for every host that supports discovery interception.
|
|
3
|
+
* Called from `memtrace rail enable` (via `install-rail` CLI) and from full
|
|
4
|
+
* `memtrace install` (per-transformer, same helpers).
|
|
5
|
+
*/
|
|
6
|
+
import fs from 'fs';
|
|
7
|
+
import os from 'os';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
import { registerRailHookInSettingsAt, removeRailHookFromSettingsAt, } from './transformers/claude.js';
|
|
10
|
+
import { geminiSettingsPath } from './transformers/gemini.js';
|
|
11
|
+
import { registerCursorRailHook, removeCursorRailHook, registerSettingsHook, removeSettingsHook, registerWindsurfRailHook, removeWindsurfRailHook, registerVsCodeRailHook, removeVsCodeRailHook, windsurfHooksPath, vscodeCopilotRailHookPath, CODEX_MATCHER, GEMINI_MATCHER, openCodePluginSource, } from './transformers/rail-hooks.js';
|
|
12
|
+
/** Hosts with no Rail hook surface yet (MCP/skills only). */
|
|
13
|
+
export const RAIL_UNSUPPORTED = [
|
|
14
|
+
{ host: 'hermes', reason: 'Hermes pre_tool_call adapter not wired yet' },
|
|
15
|
+
{ host: 'kiro', reason: 'Kiro IDE hooks omit tool stdin (CLI-only for now)' },
|
|
16
|
+
];
|
|
17
|
+
function codexHooksPath(ctx) {
|
|
18
|
+
const base = ctx.scope === 'global' ? path.join(os.homedir(), '.codex') : path.join(ctx.cwd, '.codex');
|
|
19
|
+
return path.join(base, 'hooks.json');
|
|
20
|
+
}
|
|
21
|
+
function cursorHooksPath(ctx) {
|
|
22
|
+
const base = ctx.scope === 'global' ? os.homedir() : ctx.cwd;
|
|
23
|
+
return path.join(base, '.cursor', 'hooks.json');
|
|
24
|
+
}
|
|
25
|
+
function opencodeConfigDir(ctx) {
|
|
26
|
+
const xdg = process.env.XDG_CONFIG_HOME ?? path.join(os.homedir(), '.config');
|
|
27
|
+
return ctx.scope === 'global' ? path.join(xdg, 'opencode') : path.join(ctx.cwd, '.opencode');
|
|
28
|
+
}
|
|
29
|
+
function opencodeRailPluginPaths(ctx) {
|
|
30
|
+
const base = opencodeConfigDir(ctx);
|
|
31
|
+
return [
|
|
32
|
+
path.join(base, 'plugin', 'memtrace-rail.js'),
|
|
33
|
+
path.join(base, 'plugins', 'memtrace-rail.js'),
|
|
34
|
+
];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Wire Rail discovery hooks for Claude, Cursor, Codex, Gemini, and OpenCode.
|
|
38
|
+
* Idempotent. Does not install skills or MCP — hooks only.
|
|
39
|
+
*/
|
|
40
|
+
export function installRailHooks(ctx) {
|
|
41
|
+
const bin = ctx.memtraceBinary?.trim() ?? '';
|
|
42
|
+
if (!bin) {
|
|
43
|
+
throw new Error('memtrace binary path is required to install Rail hooks');
|
|
44
|
+
}
|
|
45
|
+
const results = [];
|
|
46
|
+
const claudePath = path.join(os.homedir(), '.claude', 'settings.json');
|
|
47
|
+
const claude = registerRailHookInSettingsAt(claudePath, bin);
|
|
48
|
+
results.push({
|
|
49
|
+
host: 'claude',
|
|
50
|
+
registered: claude.registered,
|
|
51
|
+
path: claudePath,
|
|
52
|
+
skipped: claude.registered ? undefined : 'settings.json malformed or unreadable',
|
|
53
|
+
});
|
|
54
|
+
const cursorPath = cursorHooksPath(ctx);
|
|
55
|
+
const cursor = registerCursorRailHook(cursorPath, bin);
|
|
56
|
+
results.push({
|
|
57
|
+
host: 'cursor',
|
|
58
|
+
registered: cursor.registered,
|
|
59
|
+
path: cursorPath,
|
|
60
|
+
skipped: cursor.registered ? undefined : 'hooks.json malformed or unreadable',
|
|
61
|
+
});
|
|
62
|
+
const codexPath = codexHooksPath(ctx);
|
|
63
|
+
const codex = registerSettingsHook(codexPath, bin, 'codex', 'PreToolUse', CODEX_MATCHER);
|
|
64
|
+
results.push({
|
|
65
|
+
host: 'codex',
|
|
66
|
+
registered: codex.registered,
|
|
67
|
+
path: codexPath,
|
|
68
|
+
skipped: codex.registered ? undefined : 'hooks.json malformed or unreadable',
|
|
69
|
+
});
|
|
70
|
+
const geminiPath = geminiSettingsPath(ctx);
|
|
71
|
+
const gemini = registerSettingsHook(geminiPath, bin, 'gemini', 'BeforeTool', GEMINI_MATCHER, {
|
|
72
|
+
enableHooks: true,
|
|
73
|
+
enableMessageBusIntegration: true,
|
|
74
|
+
});
|
|
75
|
+
results.push({
|
|
76
|
+
host: 'gemini',
|
|
77
|
+
registered: gemini.registered,
|
|
78
|
+
path: geminiPath,
|
|
79
|
+
skipped: gemini.registered ? undefined : 'settings.json malformed or unreadable',
|
|
80
|
+
});
|
|
81
|
+
try {
|
|
82
|
+
const src = openCodePluginSource(bin);
|
|
83
|
+
for (const pluginPath of opencodeRailPluginPaths(ctx)) {
|
|
84
|
+
fs.mkdirSync(path.dirname(pluginPath), { recursive: true });
|
|
85
|
+
fs.writeFileSync(pluginPath, src);
|
|
86
|
+
}
|
|
87
|
+
results.push({
|
|
88
|
+
host: 'opencode',
|
|
89
|
+
registered: true,
|
|
90
|
+
path: opencodeRailPluginPaths(ctx)[0],
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
catch (e) {
|
|
94
|
+
results.push({
|
|
95
|
+
host: 'opencode',
|
|
96
|
+
registered: false,
|
|
97
|
+
skipped: e.message,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
const windsurfPath = windsurfHooksPath();
|
|
101
|
+
fs.mkdirSync(path.dirname(windsurfPath), { recursive: true });
|
|
102
|
+
const windsurf = registerWindsurfRailHook(windsurfPath, bin);
|
|
103
|
+
results.push({
|
|
104
|
+
host: 'windsurf',
|
|
105
|
+
registered: windsurf.registered,
|
|
106
|
+
path: windsurfPath,
|
|
107
|
+
skipped: windsurf.registered ? undefined : 'hooks.json malformed or unreadable',
|
|
108
|
+
});
|
|
109
|
+
const vscodePath = vscodeCopilotRailHookPath();
|
|
110
|
+
fs.mkdirSync(path.dirname(vscodePath), { recursive: true });
|
|
111
|
+
const vscode = registerVsCodeRailHook(vscodePath, bin);
|
|
112
|
+
results.push({
|
|
113
|
+
host: 'vscode',
|
|
114
|
+
registered: vscode.registered,
|
|
115
|
+
path: vscodePath,
|
|
116
|
+
skipped: vscode.registered ? undefined : 'hook file malformed or unreadable',
|
|
117
|
+
});
|
|
118
|
+
for (const { host, reason } of RAIL_UNSUPPORTED) {
|
|
119
|
+
results.push({ host, registered: false, skipped: reason });
|
|
120
|
+
}
|
|
121
|
+
return results;
|
|
122
|
+
}
|
|
123
|
+
/** Remove only Memtrace-owned Rail hook entries (not skills/MCP). */
|
|
124
|
+
export function uninstallRailHooks(ctx) {
|
|
125
|
+
const results = [];
|
|
126
|
+
const claudePath = path.join(os.homedir(), '.claude', 'settings.json');
|
|
127
|
+
const claude = removeRailHookFromSettingsAt(claudePath);
|
|
128
|
+
results.push({ host: 'claude', registered: false, path: claudePath, skipped: claude.changed ? undefined : 'no rail hook' });
|
|
129
|
+
const cursorPath = cursorHooksPath(ctx);
|
|
130
|
+
const cursor = removeCursorRailHook(cursorPath);
|
|
131
|
+
results.push({ host: 'cursor', registered: false, path: cursorPath, skipped: cursor.changed ? undefined : 'no rail hook' });
|
|
132
|
+
const codexPath = codexHooksPath(ctx);
|
|
133
|
+
const codex = removeSettingsHook(codexPath, 'PreToolUse');
|
|
134
|
+
results.push({ host: 'codex', registered: false, path: codexPath, skipped: codex.changed ? undefined : 'no rail hook' });
|
|
135
|
+
const geminiPath = geminiSettingsPath(ctx);
|
|
136
|
+
const gemini = removeSettingsHook(geminiPath, 'BeforeTool');
|
|
137
|
+
results.push({ host: 'gemini', registered: false, path: geminiPath, skipped: gemini.changed ? undefined : 'no rail hook' });
|
|
138
|
+
for (const p of opencodeRailPluginPaths(ctx)) {
|
|
139
|
+
try {
|
|
140
|
+
fs.rmSync(p, { force: true });
|
|
141
|
+
}
|
|
142
|
+
catch { /* best effort */ }
|
|
143
|
+
}
|
|
144
|
+
results.push({ host: 'opencode', registered: false });
|
|
145
|
+
const windsurfPath = windsurfHooksPath();
|
|
146
|
+
const windsurf = removeWindsurfRailHook(windsurfPath);
|
|
147
|
+
results.push({
|
|
148
|
+
host: 'windsurf',
|
|
149
|
+
registered: false,
|
|
150
|
+
path: windsurfPath,
|
|
151
|
+
skipped: windsurf.changed ? undefined : 'no rail hook',
|
|
152
|
+
});
|
|
153
|
+
const vscodePath = vscodeCopilotRailHookPath();
|
|
154
|
+
const vscode = removeVsCodeRailHook(vscodePath);
|
|
155
|
+
results.push({
|
|
156
|
+
host: 'vscode',
|
|
157
|
+
registered: false,
|
|
158
|
+
path: vscodePath,
|
|
159
|
+
skipped: vscode.changed ? undefined : 'no rail hook',
|
|
160
|
+
});
|
|
161
|
+
for (const { host, reason } of RAIL_UNSUPPORTED) {
|
|
162
|
+
results.push({ host, registered: false, skipped: reason });
|
|
163
|
+
}
|
|
164
|
+
return results;
|
|
165
|
+
}
|
|
166
|
+
export function printRailInstallSummary(results, action) {
|
|
167
|
+
console.log(`\n Memtrace Rail hooks ${action}:\n`);
|
|
168
|
+
for (const r of results) {
|
|
169
|
+
if (r.registered && action === 'installed') {
|
|
170
|
+
console.log(` \x1b[32m✓\x1b[0m ${r.host}${r.path ? ` → ${r.path}` : ''}`);
|
|
171
|
+
}
|
|
172
|
+
else if (action === 'removed' && r.skipped === undefined) {
|
|
173
|
+
console.log(` \x1b[32m✓\x1b[0m ${r.host} (removed)`);
|
|
174
|
+
}
|
|
175
|
+
else if (r.skipped) {
|
|
176
|
+
console.log(` \x1b[2m–\x1b[0m ${r.host}: ${r.skipped}`);
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
console.log(` \x1b[33m!\x1b[0m ${r.host}: not ${action}${r.path ? ` (${r.path})` : ''}`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
console.log('');
|
|
183
|
+
}
|
package/dist/skills.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface SkillFrontmatter {
|
|
2
|
+
name?: string;
|
|
3
|
+
description: string;
|
|
4
|
+
'allowed-tools'?: string[];
|
|
5
|
+
'user-invocable'?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export interface Skill {
|
|
8
|
+
filename: string;
|
|
9
|
+
category: 'commands' | 'workflows';
|
|
10
|
+
frontmatter: SkillFrontmatter;
|
|
11
|
+
body: string;
|
|
12
|
+
raw: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Load all skills from a skills directory (expects commands/ and workflows/ subdirs).
|
|
16
|
+
*/
|
|
17
|
+
export declare function loadSkills(skillsDir: string): Skill[];
|
package/dist/skills.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
/**
|
|
4
|
+
* Parse YAML-ish frontmatter from a skill markdown file.
|
|
5
|
+
* Handles the subset of YAML used in skill files (no nested objects).
|
|
6
|
+
*/
|
|
7
|
+
function parseFrontmatter(raw) {
|
|
8
|
+
const match = raw.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
9
|
+
if (!match)
|
|
10
|
+
return null;
|
|
11
|
+
const frontmatterRaw = match[1];
|
|
12
|
+
const body = match[2];
|
|
13
|
+
const frontmatter = {};
|
|
14
|
+
// Parse description
|
|
15
|
+
const descMatch = frontmatterRaw.match(/^description:\s*"?(.*?)"?\s*$/m);
|
|
16
|
+
if (descMatch)
|
|
17
|
+
frontmatter.description = descMatch[1];
|
|
18
|
+
// Parse name
|
|
19
|
+
const nameMatch = frontmatterRaw.match(/^name:\s*(.+)$/m);
|
|
20
|
+
if (nameMatch)
|
|
21
|
+
frontmatter.name = nameMatch[1].trim();
|
|
22
|
+
// Parse user-invocable
|
|
23
|
+
const invocableMatch = frontmatterRaw.match(/^user-invocable:\s*(.+)$/m);
|
|
24
|
+
if (invocableMatch)
|
|
25
|
+
frontmatter['user-invocable'] = invocableMatch[1].trim() === 'true';
|
|
26
|
+
// Parse allowed-tools (YAML list)
|
|
27
|
+
const toolsMatch = frontmatterRaw.match(/^allowed-tools:\n((?:\s+-\s+.+\n?)+)/m);
|
|
28
|
+
if (toolsMatch) {
|
|
29
|
+
frontmatter['allowed-tools'] = toolsMatch[1]
|
|
30
|
+
.split('\n')
|
|
31
|
+
.map(line => line.replace(/^\s+-\s+/, '').trim())
|
|
32
|
+
.filter(Boolean);
|
|
33
|
+
}
|
|
34
|
+
return { frontmatter, body };
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Load all skills from a skills directory (expects commands/ and workflows/ subdirs).
|
|
38
|
+
*/
|
|
39
|
+
export function loadSkills(skillsDir) {
|
|
40
|
+
const skills = [];
|
|
41
|
+
for (const category of ['commands', 'workflows']) {
|
|
42
|
+
const categoryDir = path.join(skillsDir, category);
|
|
43
|
+
if (!fs.existsSync(categoryDir))
|
|
44
|
+
continue;
|
|
45
|
+
for (const file of fs.readdirSync(categoryDir)) {
|
|
46
|
+
if (!file.endsWith('.md'))
|
|
47
|
+
continue;
|
|
48
|
+
const raw = fs.readFileSync(path.join(categoryDir, file), 'utf-8');
|
|
49
|
+
const parsed = parseFrontmatter(raw);
|
|
50
|
+
if (!parsed || !parsed.frontmatter.description) {
|
|
51
|
+
console.warn(`Warning: could not parse frontmatter for ${file}, skipping`);
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
skills.push({
|
|
55
|
+
filename: file,
|
|
56
|
+
category,
|
|
57
|
+
frontmatter: parsed.frontmatter,
|
|
58
|
+
body: parsed.body,
|
|
59
|
+
raw,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return skills;
|
|
64
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { Skill } from '../skills.js';
|
|
2
|
+
import { Transformer, TransformResult } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Transform a skill into Claude Code plugin format.
|
|
5
|
+
* Each skill becomes a directory with SKILL.md inside skills/<skill-name>/
|
|
6
|
+
*/
|
|
7
|
+
export declare function transformForClaude(skill: Skill): TransformResult[];
|
|
8
|
+
/**
|
|
9
|
+
* Fallback cache directory when the CLI install didn't create one.
|
|
10
|
+
*/
|
|
11
|
+
export declare function getClaudePluginCacheDir(): string;
|
|
12
|
+
export interface SettingsMutationResult {
|
|
13
|
+
registered: boolean;
|
|
14
|
+
backupPath?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Merge-add the memtrace MCP server into a Claude settings.json file.
|
|
18
|
+
* Never overwrites a malformed file — backs it up and returns registered=false.
|
|
19
|
+
*/
|
|
20
|
+
export declare function registerMcpInSettingsAt(settingsPath: string, memtraceBinary: string): SettingsMutationResult;
|
|
21
|
+
/**
|
|
22
|
+
* Register the Memtrace Rail PreToolUse hook in a Claude settings.json.
|
|
23
|
+
*
|
|
24
|
+
* This is what makes Rail "part of memtrace" rather than a manual install:
|
|
25
|
+
* `memtrace install` wires a PreToolUse hook that pipes every Grep/Glob/Bash
|
|
26
|
+
* attempt through `memtrace route --hook`. The hook defaults to **observe**
|
|
27
|
+
* (zero behavior change) — `MEMTRACE_RAIL=nudge|rail|strict` opts into more.
|
|
28
|
+
* Mode is intentionally NOT baked into the command so the user can change it
|
|
29
|
+
* via env without re-installing.
|
|
30
|
+
*
|
|
31
|
+
* Idempotent: any prior Rail entry (identified by {@link RAIL_HOOK_MARKER}) is
|
|
32
|
+
* replaced, and unrelated PreToolUse hooks are preserved. Never overwrites a
|
|
33
|
+
* malformed file.
|
|
34
|
+
*/
|
|
35
|
+
export declare function registerRailHookInSettingsAt(settingsPath: string, memtraceBinary: string): SettingsMutationResult;
|
|
36
|
+
/**
|
|
37
|
+
* Remove the Memtrace Rail PreToolUse hook from a Claude settings.json.
|
|
38
|
+
* Preserves unrelated hooks; prunes empty containers. Never touches a
|
|
39
|
+
* malformed file.
|
|
40
|
+
*/
|
|
41
|
+
export declare function removeRailHookFromSettingsAt(settingsPath: string): SettingsCleanupResult;
|
|
42
|
+
/**
|
|
43
|
+
* Merge-add plugin + marketplace entries into a Claude settings.json file.
|
|
44
|
+
* Never overwrites a malformed file.
|
|
45
|
+
*/
|
|
46
|
+
export declare function enablePluginInSettingsAt(settingsPath: string): SettingsMutationResult;
|
|
47
|
+
export interface SettingsCleanupResult {
|
|
48
|
+
changed: boolean;
|
|
49
|
+
backupPath?: string;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Remove every Claude settings entry Memtrace may have written across
|
|
53
|
+
* installer versions and Claude marketplace schema changes.
|
|
54
|
+
*/
|
|
55
|
+
export declare function removeClaudeSettingsEntriesAt(settingsPath: string): SettingsCleanupResult;
|
|
56
|
+
/**
|
|
57
|
+
* Full Claude Code plugin installation.
|
|
58
|
+
*
|
|
59
|
+
* 1. Try `claude plugin marketplace add` + `claude plugin install`
|
|
60
|
+
* 2. Fall back to manual: write cache files + update settings.json
|
|
61
|
+
* 3. Register MCP server for memtrace tools
|
|
62
|
+
*/
|
|
63
|
+
export declare function installClaudePlugin(skills: Skill[], memtraceBinaryPath: string): Promise<{
|
|
64
|
+
cacheDir: string;
|
|
65
|
+
skillCount: number;
|
|
66
|
+
}>;
|
|
67
|
+
/**
|
|
68
|
+
* Remove the Claude Code plugin and MCP server registration.
|
|
69
|
+
*/
|
|
70
|
+
export declare function uninstallClaudePlugin(): Promise<void>;
|
|
71
|
+
export declare const claudeTransformer: Transformer;
|