@axtary/cli 0.0.1 → 0.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.
Files changed (49) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +140 -6
  3. package/dist/bin.js +10 -0
  4. package/dist/bin.js.map +1 -1
  5. package/dist/claude-code-hook.d.ts +65 -0
  6. package/dist/claude-code-hook.d.ts.map +1 -0
  7. package/dist/claude-code-hook.js +326 -0
  8. package/dist/claude-code-hook.js.map +1 -0
  9. package/dist/codex-hook.d.ts +48 -0
  10. package/dist/codex-hook.d.ts.map +1 -0
  11. package/dist/codex-hook.js +259 -0
  12. package/dist/codex-hook.js.map +1 -0
  13. package/dist/credentials.d.ts +101 -0
  14. package/dist/credentials.d.ts.map +1 -0
  15. package/dist/credentials.js +277 -0
  16. package/dist/credentials.js.map +1 -0
  17. package/dist/cursor-hook.d.ts +51 -0
  18. package/dist/cursor-hook.d.ts.map +1 -0
  19. package/dist/cursor-hook.js +214 -0
  20. package/dist/cursor-hook.js.map +1 -0
  21. package/dist/hook-install.d.ts +21 -0
  22. package/dist/hook-install.d.ts.map +1 -0
  23. package/dist/hook-install.js +179 -0
  24. package/dist/hook-install.js.map +1 -0
  25. package/dist/index.d.ts +897 -5
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +6750 -513
  28. package/dist/index.js.map +1 -1
  29. package/dist/mcp-fs-normalize.d.ts +18 -0
  30. package/dist/mcp-fs-normalize.d.ts.map +1 -0
  31. package/dist/mcp-fs-normalize.js +39 -0
  32. package/dist/mcp-fs-normalize.js.map +1 -0
  33. package/dist/mcp-oauth.d.ts +67 -0
  34. package/dist/mcp-oauth.d.ts.map +1 -0
  35. package/dist/mcp-oauth.js +242 -0
  36. package/dist/mcp-oauth.js.map +1 -0
  37. package/dist/oauth.d.ts +90 -0
  38. package/dist/oauth.d.ts.map +1 -0
  39. package/dist/oauth.js +339 -0
  40. package/dist/oauth.js.map +1 -0
  41. package/dist/render.d.ts +103 -0
  42. package/dist/render.d.ts.map +1 -0
  43. package/dist/render.js +172 -0
  44. package/dist/render.js.map +1 -0
  45. package/dist/shell-file-normalize.d.ts +21 -0
  46. package/dist/shell-file-normalize.d.ts.map +1 -0
  47. package/dist/shell-file-normalize.js +269 -0
  48. package/dist/shell-file-normalize.js.map +1 -0
  49. package/package.json +17 -13
@@ -0,0 +1,214 @@
1
+ import { parseNormalizedAction, } from "@axtary/actionpass";
2
+ import { DEFAULT_HOOK_TIMEOUT_MS, DEFAULT_PROXY_URL, errorReason, postAuthorize, workspaceRelativePath, } from "./claude-code-hook.js";
3
+ import { classifyMcpFilesystemTool } from "./mcp-fs-normalize.js";
4
+ // Cursor agent-hook adapter (mega-plan M8.3). Cursor calls a configured hook
5
+ // before it runs an MCP tool (`beforeMCPExecution`); the hook reads a JSON
6
+ // payload on stdin and writes a permission decision on stdout. We map that MCP
7
+ // tool call to a NormalizedAction, ask the local proxy `/authorize`, and render
8
+ // the decision back in Cursor's wire format.
9
+ //
10
+ // Cursor's permission output is snake_case (`permission`, `user_message`,
11
+ // `agent_message`), and Cursor FAILS OPEN on non-zero/non-2 exit codes — so,
12
+ // exactly like the Claude Code hook, we always exit 0 and encode every decision
13
+ // (including fail-closed denials) in the JSON. Contract verified against the
14
+ // official Cursor hooks documentation (2026-06-26).
15
+ export const CURSOR_HOOK_SCHEMA_VERSION = "axtary.cursor_hook.v0";
16
+ export function parseCursorHookPayload(payloadText) {
17
+ let raw;
18
+ try {
19
+ raw = JSON.parse(payloadText);
20
+ }
21
+ catch {
22
+ throw new Error("cursor_hook_payload_invalid_json");
23
+ }
24
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
25
+ throw new Error("cursor_hook_payload_not_object");
26
+ }
27
+ const record = raw;
28
+ const toolName = record.tool_name;
29
+ if (typeof toolName !== "string" || toolName.length === 0) {
30
+ throw new Error("cursor_hook_tool_name_required");
31
+ }
32
+ const toolInput = record.tool_input &&
33
+ typeof record.tool_input === "object" &&
34
+ !Array.isArray(record.tool_input)
35
+ ? record.tool_input
36
+ : {};
37
+ const workspaceRoots = record.workspace_roots;
38
+ const workspaceRoot = Array.isArray(workspaceRoots) && typeof workspaceRoots[0] === "string"
39
+ ? workspaceRoots[0]
40
+ : null;
41
+ return {
42
+ hookEventName: typeof record.hook_event_name === "string" ? record.hook_event_name : null,
43
+ conversationId: typeof record.conversation_id === "string" ? record.conversation_id : null,
44
+ toolName,
45
+ toolInput,
46
+ url: typeof record.url === "string" ? record.url : null,
47
+ command: typeof record.command === "string" ? record.command : null,
48
+ workspaceRoot,
49
+ userEmail: typeof record.user_email === "string" ? record.user_email : null,
50
+ };
51
+ }
52
+ export function normalizeCursorToolCall(payload, options = {}) {
53
+ // Cursor's beforeMCPExecution governs MCP tool calls; we recognize the
54
+ // filesystem family (shared with the Codex adapter) and map them to the same
55
+ // content actions so the existing read/write policy applies.
56
+ const classified = classifyMcpFilesystemTool(payload.toolName);
57
+ if (!classified) {
58
+ return {
59
+ mapped: false,
60
+ reason: `cursor_mcp_tool_unmapped:${payload.toolName}`,
61
+ };
62
+ }
63
+ const readPathField = classified.kind === "read" ? classified.pathField : undefined;
64
+ const pathField = classified.pathField;
65
+ const rawPath = payload.toolInput[pathField];
66
+ const path = workspaceRelativePath(typeof rawPath === "string" && rawPath.length > 0 ? rawPath : ".", payload.workspaceRoot);
67
+ const repoResource = options.repoResource ?? "repo:local/workspace";
68
+ const taskId = payload.conversationId
69
+ ? `cursor:${payload.conversationId.slice(0, 12)}`
70
+ : "cursor:session";
71
+ const mcpServer = payload.url ?? payload.command ?? null;
72
+ const base = {
73
+ actor: {
74
+ agentId: "agent:cursor",
75
+ humanOwner: options.humanOwner ??
76
+ (payload.userEmail ? `user:${payload.userEmail}` : "user:local-developer"),
77
+ runtime: "cursor",
78
+ },
79
+ intent: {
80
+ taskId,
81
+ declaredGoal: `Cursor MCP tool call ${payload.toolName}`,
82
+ },
83
+ };
84
+ if (readPathField) {
85
+ return {
86
+ mapped: true,
87
+ action: parseNormalizedAction({
88
+ ...base,
89
+ capability: {
90
+ tool: "github.contents.read",
91
+ resource: repoResource,
92
+ payload: {
93
+ path,
94
+ source: "cursor-hook",
95
+ cursorTool: payload.toolName,
96
+ ...(mcpServer ? { mcpServer } : {}),
97
+ },
98
+ },
99
+ }),
100
+ };
101
+ }
102
+ return {
103
+ mapped: true,
104
+ action: parseNormalizedAction({
105
+ ...base,
106
+ capability: {
107
+ tool: "github.contents.write",
108
+ resource: repoResource,
109
+ payload: {
110
+ path,
111
+ branch: options.branch ?? "workspace",
112
+ source: "cursor-hook",
113
+ cursorTool: payload.toolName,
114
+ ...(mcpServer ? { mcpServer } : {}),
115
+ },
116
+ },
117
+ }),
118
+ };
119
+ }
120
+ export async function runCursorHook(input) {
121
+ let payload;
122
+ try {
123
+ payload = parseCursorHookPayload(input.payloadText);
124
+ }
125
+ catch (error) {
126
+ return decisionResult(null, null, "deny", {
127
+ user: `Axtary blocked this tool call: hook payload could not be parsed (${errorReason(error)}).`,
128
+ agent: "The Axtary hook received an unparseable payload and failed closed. Protected actions are denied by default.",
129
+ });
130
+ }
131
+ const normalization = normalizeCursorToolCall(payload, {
132
+ repoResource: input.repoResource,
133
+ humanOwner: input.humanOwner,
134
+ branch: input.branch,
135
+ });
136
+ if (!normalization.mapped) {
137
+ // No opinion: emit empty JSON so Cursor proceeds with its own default.
138
+ return {
139
+ schemaVersion: CURSOR_HOOK_SCHEMA_VERSION,
140
+ status: "no_opinion",
141
+ tool: payload.toolName,
142
+ normalizedTool: null,
143
+ reason: normalization.reason,
144
+ output: "{}",
145
+ exitCode: 0,
146
+ };
147
+ }
148
+ const proxyUrl = (input.proxyUrl ?? DEFAULT_PROXY_URL).replace(/\/$/, "");
149
+ const fetchImpl = input.fetch ?? globalThis.fetch;
150
+ const normalizedTool = normalization.action.capability.tool;
151
+ let response;
152
+ try {
153
+ response = await postAuthorize(fetchImpl, `${proxyUrl}/authorize`, normalization.action, input.timeoutMs ?? DEFAULT_HOOK_TIMEOUT_MS);
154
+ }
155
+ catch (error) {
156
+ return decisionResult(payload.toolName, normalizedTool, "deny", {
157
+ user: `Axtary blocked ${normalizedTool}: local proxy unreachable at ${proxyUrl} (${errorReason(error)}). Start it with: axtary proxy --config axtary.yml`,
158
+ agent: `Axtary could not reach its local enforcement proxy, so ${normalizedTool} was denied (fail-closed).`,
159
+ });
160
+ }
161
+ const reasons = response.decision?.reasons ?? [];
162
+ const hints = response.hints ?? [];
163
+ const summary = response.explanation?.summary ?? reasons.join(", ");
164
+ const ledgerLine = typeof response.ledger?.lineNumber === "number"
165
+ ? ` Ledger line ${response.ledger.lineNumber}.`
166
+ : "";
167
+ if (response.status === "authorized") {
168
+ return decisionResult(payload.toolName, normalizedTool, "allow", {
169
+ user: `Axtary authorized ${normalizedTool}: ${summary}${ledgerLine}`,
170
+ agent: `Axtary authorized ${normalizedTool}: ${summary}`,
171
+ });
172
+ }
173
+ if (response.status === "step_up") {
174
+ return decisionResult(payload.toolName, normalizedTool, "ask", {
175
+ user: joinNonEmpty([
176
+ `Axtary requires step-up review for ${normalizedTool}: ${summary}`,
177
+ ...hints,
178
+ ]) + ledgerLine,
179
+ agent: joinNonEmpty([
180
+ `Axtary requires human step-up approval for ${normalizedTool}: ${summary}`,
181
+ ...hints,
182
+ ]),
183
+ });
184
+ }
185
+ return decisionResult(payload.toolName, normalizedTool, "deny", {
186
+ user: joinNonEmpty([
187
+ `Axtary blocked ${normalizedTool}: ${summary}`,
188
+ ...hints,
189
+ ]) + ledgerLine,
190
+ agent: joinNonEmpty([
191
+ `Axtary blocked ${normalizedTool}: ${summary}`,
192
+ ...hints,
193
+ ]),
194
+ });
195
+ }
196
+ function decisionResult(tool, normalizedTool, permission, messages) {
197
+ return {
198
+ schemaVersion: CURSOR_HOOK_SCHEMA_VERSION,
199
+ status: permission,
200
+ tool,
201
+ normalizedTool,
202
+ reason: messages.agent,
203
+ output: JSON.stringify({
204
+ permission,
205
+ user_message: messages.user,
206
+ agent_message: messages.agent,
207
+ }),
208
+ exitCode: 0,
209
+ };
210
+ }
211
+ function joinNonEmpty(parts) {
212
+ return parts.filter((part) => part.length > 0).join(" ");
213
+ }
214
+ //# sourceMappingURL=cursor-hook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cursor-hook.js","sourceRoot":"","sources":["../src/cursor-hook.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ export declare const HOOK_INSTALL_SCHEMA_VERSION = "axtary.hook_install.v0";
2
+ export type HookInstallRuntime = "claude" | "cursor" | "codex";
3
+ export type HookInstallInput = {
4
+ runtime: HookInstallRuntime;
5
+ cwd?: string;
6
+ proxyUrl?: string;
7
+ repoResource?: string;
8
+ humanOwner?: string;
9
+ branch?: string;
10
+ timeoutMs?: number;
11
+ binPath?: string;
12
+ };
13
+ export type HookInstallResult = {
14
+ schemaVersion: typeof HOOK_INSTALL_SCHEMA_VERSION;
15
+ runtime: HookInstallRuntime;
16
+ status: "created" | "updated" | "unchanged";
17
+ configPath: string;
18
+ command: string;
19
+ };
20
+ export declare function installRuntimeHook(input: HookInstallInput): Promise<HookInstallResult>;
21
+ //# sourceMappingURL=hook-install.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook-install.d.ts","sourceRoot":"","sources":["../src/hook-install.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,2BAA2B,2BAA2B,CAAC;AAEpE,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;AAI/D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,kBAAkB,CAAC;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,aAAa,EAAE,OAAO,2BAA2B,CAAC;IAClD,OAAO,EAAE,kBAAkB,CAAC;IAC5B,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,CAAC;IAC5C,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAKF,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,gBAAgB,GACtB,OAAO,CAAC,iBAAiB,CAAC,CAgD5B"}
@@ -0,0 +1,179 @@
1
+ import { mkdir, readFile, stat, writeFile } from "node:fs/promises";
2
+ import { dirname, resolve } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ export const HOOK_INSTALL_SCHEMA_VERSION = "axtary.hook_install.v0";
5
+ const DEFAULT_PROXY_URL = "http://127.0.0.1:7331";
6
+ const DEFAULT_CONFIG_TIMEOUT_SECONDS = 10;
7
+ export async function installRuntimeHook(input) {
8
+ const cwd = resolve(input.cwd ?? process.cwd());
9
+ const runtimeCommand = hookCommandName(input.runtime);
10
+ const configPath = runtimeConfigPath(cwd, input.runtime);
11
+ const existed = await fileExists(configPath);
12
+ const current = existed ? await readJsonObject(configPath) : {};
13
+ const command = buildHookCommand({
14
+ runtimeCommand,
15
+ proxyUrl: input.proxyUrl ?? DEFAULT_PROXY_URL,
16
+ repoResource: input.repoResource,
17
+ humanOwner: input.humanOwner,
18
+ branch: input.branch,
19
+ timeoutMs: input.timeoutMs,
20
+ binPath: input.binPath,
21
+ });
22
+ const timeoutSeconds = hookConfigTimeoutSeconds(input.timeoutMs);
23
+ const next = installIntoConfig(current, input.runtime, runtimeCommand, command, timeoutSeconds);
24
+ const nextText = `${JSON.stringify(next, null, 2)}\n`;
25
+ if (existed) {
26
+ const currentText = await readFile(configPath, "utf8");
27
+ if (currentText === nextText) {
28
+ return {
29
+ schemaVersion: HOOK_INSTALL_SCHEMA_VERSION,
30
+ runtime: input.runtime,
31
+ status: "unchanged",
32
+ configPath,
33
+ command,
34
+ };
35
+ }
36
+ }
37
+ await mkdir(dirname(configPath), { recursive: true });
38
+ await writeFile(configPath, nextText, "utf8");
39
+ return {
40
+ schemaVersion: HOOK_INSTALL_SCHEMA_VERSION,
41
+ runtime: input.runtime,
42
+ status: existed ? "updated" : "created",
43
+ configPath,
44
+ command,
45
+ };
46
+ }
47
+ function installIntoConfig(current, runtime, runtimeCommand, command, timeoutSeconds) {
48
+ return runtime === "cursor"
49
+ ? installCursorHook(current, command, timeoutSeconds)
50
+ : installClaudeShapedHook(current, runtimeCommand, command, timeoutSeconds);
51
+ }
52
+ function installClaudeShapedHook(current, runtimeCommand, command, timeoutSeconds) {
53
+ const next = { ...current };
54
+ const hooks = objectRecord(next.hooks);
55
+ const entries = arrayValue(hooks.PreToolUse)
56
+ .map((entry) => pruneClaudeShapedEntry(entry, runtimeCommand))
57
+ .filter((entry) => entry !== null);
58
+ entries.push({
59
+ matcher: runtimeCommand === "codex"
60
+ ? "Bash|apply_patch"
61
+ : "Read|Glob|Grep|Write|Edit|NotebookEdit|Bash",
62
+ hooks: [
63
+ {
64
+ type: "command",
65
+ command,
66
+ timeout: timeoutSeconds,
67
+ },
68
+ ],
69
+ });
70
+ hooks.PreToolUse = entries;
71
+ next.hooks = hooks;
72
+ return next;
73
+ }
74
+ function installCursorHook(current, command, timeoutSeconds) {
75
+ const next = { ...current };
76
+ if (!("version" in next)) {
77
+ next.version = 1;
78
+ }
79
+ const hooks = objectRecord(next.hooks);
80
+ const entries = arrayValue(hooks.beforeMCPExecution).filter((entry) => !entryHasAxtaryCommand(entry, "cursor"));
81
+ entries.push({
82
+ command,
83
+ timeout: timeoutSeconds,
84
+ failClosed: true,
85
+ });
86
+ hooks.beforeMCPExecution = entries;
87
+ next.hooks = hooks;
88
+ return next;
89
+ }
90
+ function pruneClaudeShapedEntry(entry, runtimeCommand) {
91
+ if (!isRecord(entry)) {
92
+ return entry;
93
+ }
94
+ const hooks = arrayValue(entry.hooks).filter((hook) => !entryHasAxtaryCommand(hook, runtimeCommand));
95
+ if (hooks.length === 0 && arrayValue(entry.hooks).length > 0) {
96
+ return null;
97
+ }
98
+ return { ...entry, hooks };
99
+ }
100
+ function entryHasAxtaryCommand(entry, runtimeCommand) {
101
+ if (!isRecord(entry)) {
102
+ return false;
103
+ }
104
+ const command = entry.command;
105
+ return typeof command === "string" && command.includes(` hook ${runtimeCommand}`);
106
+ }
107
+ function buildHookCommand(input) {
108
+ const args = [
109
+ shellQuote(process.execPath),
110
+ shellQuote(resolveHookBinary(input.binPath)),
111
+ "hook",
112
+ input.runtimeCommand,
113
+ "--proxy",
114
+ shellQuote(input.proxyUrl),
115
+ ];
116
+ if (input.repoResource) {
117
+ args.push("--repo", shellQuote(input.repoResource));
118
+ }
119
+ if (input.humanOwner) {
120
+ args.push("--owner", shellQuote(input.humanOwner));
121
+ }
122
+ if (input.branch) {
123
+ args.push("--branch", shellQuote(input.branch));
124
+ }
125
+ if (input.timeoutMs) {
126
+ args.push("--timeout", String(input.timeoutMs));
127
+ }
128
+ return args.join(" ");
129
+ }
130
+ function resolveHookBinary(binPath) {
131
+ if (binPath) {
132
+ return resolve(binPath);
133
+ }
134
+ const thisFile = fileURLToPath(import.meta.url);
135
+ const dir = dirname(thisFile);
136
+ return dir.endsWith("/src")
137
+ ? resolve(dir, "../dist/bin.js")
138
+ : resolve(dir, "bin.js");
139
+ }
140
+ function runtimeConfigPath(cwd, runtime) {
141
+ switch (runtime) {
142
+ case "claude":
143
+ return resolve(cwd, ".claude/settings.json");
144
+ case "cursor":
145
+ return resolve(cwd, ".cursor/hooks.json");
146
+ case "codex":
147
+ return resolve(cwd, ".codex/hooks.json");
148
+ }
149
+ }
150
+ function hookCommandName(runtime) {
151
+ return runtime === "claude" ? "claude-code" : runtime;
152
+ }
153
+ function hookConfigTimeoutSeconds(timeoutMs) {
154
+ return Math.max(DEFAULT_CONFIG_TIMEOUT_SECONDS, timeoutMs ? Math.ceil(timeoutMs / 1000) + 1 : DEFAULT_CONFIG_TIMEOUT_SECONDS);
155
+ }
156
+ async function readJsonObject(path) {
157
+ const text = await readFile(path, "utf8");
158
+ const parsed = JSON.parse(text);
159
+ if (!isRecord(parsed)) {
160
+ throw new Error("hook_config_not_json_object");
161
+ }
162
+ return parsed;
163
+ }
164
+ async function fileExists(path) {
165
+ return stat(path).then(() => true, () => false);
166
+ }
167
+ function objectRecord(value) {
168
+ return isRecord(value) ? { ...value } : {};
169
+ }
170
+ function arrayValue(value) {
171
+ return Array.isArray(value) ? [...value] : [];
172
+ }
173
+ function isRecord(value) {
174
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
175
+ }
176
+ function shellQuote(value) {
177
+ return `'${value.replaceAll("'", "'\\''")}'`;
178
+ }
179
+ //# sourceMappingURL=hook-install.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook-install.js","sourceRoot":"","sources":["../src/hook-install.ts"],"names":[],"mappings":"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"}