@k1e1n04/mav 0.1.25 → 0.1.28
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 +7 -2
- package/dist/package.json +1 -1
- package/dist/src/hook-injector.js +41 -2
- package/dist/src/hook-injector.js.map +1 -1
- package/package.json +1 -1
- package/src/hook-injector.ts +50 -2
package/README.md
CHANGED
|
@@ -123,11 +123,16 @@ mav tracks each agent's working directory. When an agent changes directory (e.g.
|
|
|
123
123
|
| `claude-code` | IPC + PostToolUse hook | ✅ Auto-injected via `--settings` |
|
|
124
124
|
| `gemini-cli` | IPC + AfterTool hook | ✅ Auto-injected via `.gemini/settings.local.json` |
|
|
125
125
|
| `codex` | IPC + PostToolUse hook | ✅ Auto-injected via `--profile-v2` |
|
|
126
|
-
| `copilot` |
|
|
126
|
+
| `copilot` | IPC + PostToolUse hook | ✅ Auto-injected via `.github/hooks/*.json` |
|
|
127
|
+
| `cursor` | lsof polling only | ❌ Not supported |
|
|
127
128
|
| Other | lsof polling only | ❌ Not supported |
|
|
128
129
|
|
|
129
|
-
> **
|
|
130
|
+
> **Cursor** and unlisted agents use process polling to track the working directory.
|
|
130
131
|
> Directory changes made in child processes (e.g., git worktrees) may not be detected.
|
|
132
|
+
>
|
|
133
|
+
> **Codex / Copilot / Gemini note:** even when `mav` tracks a session's latest `cwd`, these agents may not keep a persistent shell `cd` across turns in this environment. In practice, they can follow the worktree by running each command with that directory as its `workdir`, rather than by changing their own long-lived terminal state.
|
|
134
|
+
>
|
|
135
|
+
> If you want shell-like directory changes to feel most natural inside the agent session itself, `claude-code` is currently the safest choice.
|
|
131
136
|
|
|
132
137
|
## Keybindings
|
|
133
138
|
|
package/dist/package.json
CHANGED
|
@@ -13,6 +13,8 @@ export function buildHookArgs(agentType, baseArgs, hookCommand, options = {}) {
|
|
|
13
13
|
return buildClaudeCodeHook(baseArgs, hookCommand);
|
|
14
14
|
case 'gemini-cli':
|
|
15
15
|
return buildGeminiHook(baseArgs, hookCommand, options.cwd);
|
|
16
|
+
case 'copilot':
|
|
17
|
+
return buildCopilotHook(baseArgs, hookCommand, options.cwd);
|
|
16
18
|
case 'codex':
|
|
17
19
|
return buildCodexHook(baseArgs, hookCommand);
|
|
18
20
|
default:
|
|
@@ -20,9 +22,24 @@ export function buildHookArgs(agentType, baseArgs, hookCommand, options = {}) {
|
|
|
20
22
|
}
|
|
21
23
|
}
|
|
22
24
|
function buildClaudeCodeHook(baseArgs, hookCommand) {
|
|
23
|
-
const
|
|
25
|
+
const claudeSettingsPath = join(homedir(), '.claude', 'settings.json');
|
|
26
|
+
let existing = {};
|
|
27
|
+
if (existsSync(claudeSettingsPath)) {
|
|
28
|
+
try {
|
|
29
|
+
existing = JSON.parse(readFileSync(claudeSettingsPath, 'utf-8'));
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
// Unreadable/invalid JSON — start from empty
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const existingHooks = (existing.hooks ?? {});
|
|
36
|
+
const existingPostToolUse = (existingHooks.PostToolUse ?? []);
|
|
37
|
+
const merged = {
|
|
38
|
+
...existing,
|
|
24
39
|
hooks: {
|
|
40
|
+
...existingHooks,
|
|
25
41
|
PostToolUse: [
|
|
42
|
+
...existingPostToolUse,
|
|
26
43
|
{
|
|
27
44
|
matcher: '',
|
|
28
45
|
hooks: [{ type: 'command', command: hookCommand }],
|
|
@@ -31,7 +48,7 @@ function buildClaudeCodeHook(baseArgs, hookCommand) {
|
|
|
31
48
|
},
|
|
32
49
|
};
|
|
33
50
|
return {
|
|
34
|
-
args: [...baseArgs, '--settings', JSON.stringify(
|
|
51
|
+
args: [...baseArgs, '--settings', JSON.stringify(merged)],
|
|
35
52
|
hookFiles: [],
|
|
36
53
|
};
|
|
37
54
|
}
|
|
@@ -83,6 +100,28 @@ function buildCodexHook(baseArgs, hookCommand) {
|
|
|
83
100
|
hookFiles: [tomlPath],
|
|
84
101
|
};
|
|
85
102
|
}
|
|
103
|
+
function buildCopilotHook(baseArgs, hookCommand, cwd) {
|
|
104
|
+
const projectDir = cwd ?? process.cwd();
|
|
105
|
+
const hooksDir = join(projectDir, '.github', 'hooks');
|
|
106
|
+
const hookPath = join(hooksDir, `mav-${randomUUID()}.json`);
|
|
107
|
+
const hookConfig = {
|
|
108
|
+
version: 1,
|
|
109
|
+
hooks: {
|
|
110
|
+
postToolUse: [
|
|
111
|
+
{
|
|
112
|
+
type: 'command',
|
|
113
|
+
command: hookCommand,
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
mkdirSync(hooksDir, { recursive: true });
|
|
119
|
+
writeFileSync(hookPath, JSON.stringify(hookConfig, null, 2));
|
|
120
|
+
return {
|
|
121
|
+
args: baseArgs,
|
|
122
|
+
hookFiles: [hookPath],
|
|
123
|
+
};
|
|
124
|
+
}
|
|
86
125
|
/**
|
|
87
126
|
* Deletes temp files generated by buildHookArgs.
|
|
88
127
|
* Call this when the agent process exits.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hook-injector.js","sourceRoot":"","sources":["../../src/hook-injector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AACxF,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAcxC;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAC3B,SAAiB,EACjB,QAAkB,EAClB,WAAmB,EACnB,UAAgC,EAAE;IAElC,QAAQ,SAAS,EAAE,CAAC;QAClB,KAAK,aAAa;YAChB,OAAO,mBAAmB,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAA;QACnD,KAAK,YAAY;YACf,OAAO,eAAe,CAAC,QAAQ,EAAE,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,CAAA;QAC5D,KAAK,OAAO;YACV,OAAO,cAAc,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAA;QAC9C;YACE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,EAAE,CAAA;IAC5C,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB,CAAC,QAAkB,EAAE,WAAmB;IAClE,MAAM,QAAQ,GAAG;
|
|
1
|
+
{"version":3,"file":"hook-injector.js","sourceRoot":"","sources":["../../src/hook-injector.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/hook-injector.ts
CHANGED
|
@@ -31,6 +31,8 @@ export function buildHookArgs(
|
|
|
31
31
|
return buildClaudeCodeHook(baseArgs, hookCommand)
|
|
32
32
|
case 'gemini-cli':
|
|
33
33
|
return buildGeminiHook(baseArgs, hookCommand, options.cwd)
|
|
34
|
+
case 'copilot':
|
|
35
|
+
return buildCopilotHook(baseArgs, hookCommand, options.cwd)
|
|
34
36
|
case 'codex':
|
|
35
37
|
return buildCodexHook(baseArgs, hookCommand)
|
|
36
38
|
default:
|
|
@@ -39,9 +41,25 @@ export function buildHookArgs(
|
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
function buildClaudeCodeHook(baseArgs: string[], hookCommand: string): HookInjectionResult {
|
|
42
|
-
const
|
|
44
|
+
const claudeSettingsPath = join(homedir(), '.claude', 'settings.json')
|
|
45
|
+
let existing: Record<string, unknown> = {}
|
|
46
|
+
if (existsSync(claudeSettingsPath)) {
|
|
47
|
+
try {
|
|
48
|
+
existing = JSON.parse(readFileSync(claudeSettingsPath, 'utf-8')) as Record<string, unknown>
|
|
49
|
+
} catch {
|
|
50
|
+
// Unreadable/invalid JSON — start from empty
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const existingHooks = (existing.hooks ?? {}) as Record<string, unknown[]>
|
|
55
|
+
const existingPostToolUse = (existingHooks.PostToolUse ?? []) as unknown[]
|
|
56
|
+
|
|
57
|
+
const merged = {
|
|
58
|
+
...existing,
|
|
43
59
|
hooks: {
|
|
60
|
+
...existingHooks,
|
|
44
61
|
PostToolUse: [
|
|
62
|
+
...existingPostToolUse,
|
|
45
63
|
{
|
|
46
64
|
matcher: '',
|
|
47
65
|
hooks: [{ type: 'command', command: hookCommand }],
|
|
@@ -49,8 +67,9 @@ function buildClaudeCodeHook(baseArgs: string[], hookCommand: string): HookInjec
|
|
|
49
67
|
],
|
|
50
68
|
},
|
|
51
69
|
}
|
|
70
|
+
|
|
52
71
|
return {
|
|
53
|
-
args: [...baseArgs, '--settings', JSON.stringify(
|
|
72
|
+
args: [...baseArgs, '--settings', JSON.stringify(merged)],
|
|
54
73
|
hookFiles: [],
|
|
55
74
|
}
|
|
56
75
|
}
|
|
@@ -116,6 +135,35 @@ function buildCodexHook(baseArgs: string[], hookCommand: string): HookInjectionR
|
|
|
116
135
|
}
|
|
117
136
|
}
|
|
118
137
|
|
|
138
|
+
function buildCopilotHook(
|
|
139
|
+
baseArgs: string[],
|
|
140
|
+
hookCommand: string,
|
|
141
|
+
cwd?: string,
|
|
142
|
+
): HookInjectionResult {
|
|
143
|
+
const projectDir = cwd ?? process.cwd()
|
|
144
|
+
const hooksDir = join(projectDir, '.github', 'hooks')
|
|
145
|
+
const hookPath = join(hooksDir, `mav-${randomUUID()}.json`)
|
|
146
|
+
const hookConfig = {
|
|
147
|
+
version: 1,
|
|
148
|
+
hooks: {
|
|
149
|
+
postToolUse: [
|
|
150
|
+
{
|
|
151
|
+
type: 'command',
|
|
152
|
+
command: hookCommand,
|
|
153
|
+
},
|
|
154
|
+
],
|
|
155
|
+
},
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
mkdirSync(hooksDir, { recursive: true })
|
|
159
|
+
writeFileSync(hookPath, JSON.stringify(hookConfig, null, 2))
|
|
160
|
+
|
|
161
|
+
return {
|
|
162
|
+
args: baseArgs,
|
|
163
|
+
hookFiles: [hookPath],
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
119
167
|
/**
|
|
120
168
|
* Deletes temp files generated by buildHookArgs.
|
|
121
169
|
* Call this when the agent process exits.
|