@prohost/cli 0.13.2 → 0.14.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/CHANGELOG.md +95 -0
- package/README.md +129 -0
- package/dist/agent/claude.d.ts +28 -0
- package/dist/agent/claude.js +83 -4
- package/dist/agent/command.d.ts +8 -0
- package/dist/agent/command.js +40 -7
- package/dist/agent/daemon.d.ts +3 -1
- package/dist/agent/daemon.js +1 -2
- package/dist/agent/run.d.ts +30 -1
- package/dist/agent/run.js +311 -16
- package/dist/agent/runtime_status.d.ts +99 -3
- package/dist/agent/runtime_status.js +173 -5
- package/dist/agent/worktrees.d.ts +2 -0
- package/dist/agent/worktrees.js +3 -2
- package/dist/codehost/activity.d.ts +64 -0
- package/dist/codehost/activity.js +135 -0
- package/dist/codehost/agents.d.ts +31 -0
- package/dist/codehost/agents.js +57 -0
- package/dist/codehost/checkouts.d.ts +130 -0
- package/dist/codehost/checkouts.js +270 -0
- package/dist/codehost/claude_trust.d.ts +40 -0
- package/dist/codehost/claude_trust.js +129 -0
- package/dist/codehost/command.d.ts +25 -0
- package/dist/codehost/command.js +136 -0
- package/dist/codehost/decision.d.ts +156 -0
- package/dist/codehost/decision.js +553 -0
- package/dist/codehost/events.d.ts +49 -0
- package/dist/codehost/events.js +87 -0
- package/dist/codehost/folders.d.ts +122 -0
- package/dist/codehost/folders.js +317 -0
- package/dist/codehost/hooks.d.ts +178 -0
- package/dist/codehost/hooks.js +726 -0
- package/dist/codehost/host.d.ts +290 -0
- package/dist/codehost/host.js +625 -0
- package/dist/codehost/host_stats.d.ts +71 -0
- package/dist/codehost/host_stats.js +166 -0
- package/dist/codehost/invocations.d.ts +12 -0
- package/dist/codehost/invocations.js +82 -0
- package/dist/codehost/ledger.d.ts +35 -0
- package/dist/codehost/ledger.js +91 -0
- package/dist/codehost/local_server.d.ts +106 -0
- package/dist/codehost/local_server.js +339 -0
- package/dist/codehost/pty.d.ts +38 -0
- package/dist/codehost/pty.js +47 -0
- package/dist/codehost/ready.d.ts +31 -0
- package/dist/codehost/ready.js +109 -0
- package/dist/codehost/relay.d.ts +170 -0
- package/dist/codehost/relay.js +548 -0
- package/dist/codehost/settings.d.ts +52 -0
- package/dist/codehost/settings.js +114 -0
- package/dist/codehost/sizing.d.ts +163 -0
- package/dist/codehost/sizing.js +394 -0
- package/dist/codehost/terminals.d.ts +390 -0
- package/dist/codehost/terminals.js +965 -0
- package/dist/codehost/tmux.d.ts +196 -0
- package/dist/codehost/tmux.js +391 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +21 -0
- package/dist/version.d.ts +2 -2
- package/dist/version.js +1 -1
- package/package.json +4 -1
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code hooks and Codex `notify` for Mac-hosted Code threads.
|
|
3
|
+
*
|
|
4
|
+
* **Nothing global is installed.** The operator's `~/.claude/settings.json`
|
|
5
|
+
* and `~/.codex/config.toml` are never edited. Each thread's agent is launched
|
|
6
|
+
* with the hooks on its own command line — `claude --settings <file>`, `codex -c
|
|
7
|
+
* notify=[...]` — so they exist only in the sessions this host starts, and the
|
|
8
|
+
* one command they run is a shim that exits at once unless
|
|
9
|
+
* `$PROHOST_TERMINAL_ID` is set. A `claude` the operator starts in their own
|
|
10
|
+
* terminal sees none of it.
|
|
11
|
+
*
|
|
12
|
+
* The shim (`$PROHOST_HOME/code-host/bin/prohost-hook`) is rewritten on every
|
|
13
|
+
* daemon start to name the CLI that is installed now, so a session started
|
|
14
|
+
* under an older CLI (npx caches move) keeps working after an upgrade.
|
|
15
|
+
*
|
|
16
|
+
* What each hook reports (contract "Hook / host ingest"):
|
|
17
|
+
*
|
|
18
|
+
* | Hook | Event |
|
|
19
|
+
* | --- | --- |
|
|
20
|
+
* | `UserPromptSubmit` | `prompt {text}` |
|
|
21
|
+
* | `Stop` | `stop {finalText, question}` then `stats {...}` |
|
|
22
|
+
* | `PermissionRequest --wait <s>` | `permission_request {approvalId, command, options, capabilities: ['hook_decision'], waitMs, deadlineMs, sentAtMs}`, then waits for the decision and prints it (`decision.ts`); `prompt_local` if its wait runs out |
|
|
23
|
+
* | `PermissionRequest` (a window launched before `--wait`) | `permission_request`, then at once `prompt_local {reason: 'launched_before_update'}`: its Claude Code would kill a waiting hook at 10 s |
|
|
24
|
+
* | `Notification` (`permission_prompt`) | for a Claude Code without `PermissionRequest`: `permission_request`, then `prompt_local {reason: 'no_hook'}` |
|
|
25
|
+
* | `SessionStart` | nothing posted; like every hook, it marks the window past the trust dialog (`ready.ts`) |
|
|
26
|
+
* | Codex `agent-turn-complete` | `prompt` (when it carries one) then `stop` |
|
|
27
|
+
*
|
|
28
|
+
* `question` is always true for an interactive turn: when an interactive agent
|
|
29
|
+
* stops, its turn is over and nothing more happens until a person types — that
|
|
30
|
+
* is a hand-off by construction, not a reading of what it said.
|
|
31
|
+
*
|
|
32
|
+
* Ordinary hooks print nothing (a `UserPromptSubmit` hook's stdout becomes part of the
|
|
33
|
+
* prompt), except a waiting `PermissionRequest` hook's decision from ProhostAI,
|
|
34
|
+
* which never blocks the menu (Claude Code draws it while the hook runs, and
|
|
35
|
+
* applies whichever answers first). The verified modern profile also records
|
|
36
|
+
* PreToolUse IDs; recording failures block the tool rather than returning success. Claude Code and
|
|
37
|
+
* Codex credentials are never read; the only Claude file read is the session's
|
|
38
|
+
* own transcript, for the turn's final text and token counts, and for whether a
|
|
39
|
+
* held prompt's call is over (`decision.ts`).
|
|
40
|
+
*/
|
|
41
|
+
import type { CodeThreadEvent } from './events.js';
|
|
42
|
+
import type { HostDecision } from './decision.js';
|
|
43
|
+
export declare const TERMINAL_ID_ENV = "PROHOST_TERMINAL_ID";
|
|
44
|
+
export declare const CODE_THREAD_ID_ENV = "PROHOST_CODE_THREAD_ID";
|
|
45
|
+
/** Claude Code hook events this host registers. */
|
|
46
|
+
export declare const CLAUDE_HOOK_EVENTS: readonly ["SessionStart", "UserPromptSubmit", "Stop", "PermissionRequest", "Notification"];
|
|
47
|
+
export type ClaudeHookEvent = (typeof CLAUDE_HOOK_EVENTS)[number];
|
|
48
|
+
export declare const APPROVAL_OPTIONS: readonly ["allow", "allow_session", "deny"];
|
|
49
|
+
/**
|
|
50
|
+
* Declared on a `permission_request` whose decision the hook itself returns
|
|
51
|
+
* (`decision.ts`): the server may relay a decision the moment it has the
|
|
52
|
+
* prompt, since it can only ever answer that prompt.
|
|
53
|
+
*/
|
|
54
|
+
export declare const HOOK_DECISION_CAPABILITY = "hook_decision";
|
|
55
|
+
/** Waits between `permission_request` attempts whose outcome is unknown, within the hook's wait. */
|
|
56
|
+
export declare const POST_RETRY_DELAYS_MS: number[];
|
|
57
|
+
/** Waits between `approval_overridden_locally` attempts, all within {@link OVERRIDE_BUDGET_MS}. */
|
|
58
|
+
export declare const OVERRIDE_RETRY_DELAYS_MS: number[];
|
|
59
|
+
/** Every correction attempt ends this soon after the PostToolUse hook started, under its 10 s timeout. */
|
|
60
|
+
export declare const OVERRIDE_BUDGET_MS = 8000;
|
|
61
|
+
/**
|
|
62
|
+
* How long the `PermissionRequest` hook waits for a decision from ProhostAI.
|
|
63
|
+
* The menu is up in the terminal all along (Claude Code draws it while the hook
|
|
64
|
+
* runs), so the person at the Mac is never kept waiting by it: this bounds only
|
|
65
|
+
* how long a decision from ProhostAI may still answer the prompt.
|
|
66
|
+
*/
|
|
67
|
+
export declare const HOOK_DECISION_WAIT_S = 120;
|
|
68
|
+
/** The hook's own timeout, past which Claude Code kills it: above its wait. */
|
|
69
|
+
export declare const PERMISSION_HOOK_TIMEOUT_S = 150;
|
|
70
|
+
export declare const MAX_PREVIEW_CHARS = 280;
|
|
71
|
+
export declare function hookBinDir(env?: NodeJS.ProcessEnv): string;
|
|
72
|
+
export declare function hookShimPath(env?: NodeJS.ProcessEnv): string;
|
|
73
|
+
export declare function claudeSettingsPath(env?: NodeJS.ProcessEnv): string;
|
|
74
|
+
/** The shim script: env-guarded, then the current CLI's `hook` command. */
|
|
75
|
+
export declare function hookShimScript(nodePath: string, cliEntrypoint: string): string;
|
|
76
|
+
/** The `--settings` document Claude Code is launched with: hooks only. */
|
|
77
|
+
export declare function claudeHookSettings(shimPath: string, invocationProtocol?: boolean): Record<string, unknown>;
|
|
78
|
+
/** Codex `-c notify=[...]` value (TOML array), naming the shim. */
|
|
79
|
+
export declare function codexNotifyOverride(shimPath: string): string;
|
|
80
|
+
/** Write the shim and Claude settings. Called on every daemon start. */
|
|
81
|
+
export declare function installHookFiles(nodePath: string, cliEntrypoint: string, env?: NodeJS.ProcessEnv): {
|
|
82
|
+
shim: string;
|
|
83
|
+
claudeSettings: string;
|
|
84
|
+
claudeInvocationSettings: string;
|
|
85
|
+
};
|
|
86
|
+
/** Last non-empty line, clipped — the inbox row's preview. */
|
|
87
|
+
export declare function previewOf(text: string): string | undefined;
|
|
88
|
+
export interface TranscriptTurn {
|
|
89
|
+
finalText?: string;
|
|
90
|
+
tokensTotal?: number;
|
|
91
|
+
tokensCachedPct?: number;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* The last assistant turn of a Claude Code transcript (JSONL): its text and
|
|
95
|
+
* token usage. Unknown shapes yield nothing rather than zeros.
|
|
96
|
+
*/
|
|
97
|
+
export declare function parseTranscriptTail(content: string): TranscriptTurn;
|
|
98
|
+
/** `git diff --shortstat` numbers for a worktree, against where its branch left the default branch. */
|
|
99
|
+
export declare function parseShortstat(text: string): {
|
|
100
|
+
filesChanged: number;
|
|
101
|
+
additions: number;
|
|
102
|
+
deletions: number;
|
|
103
|
+
};
|
|
104
|
+
export type GitRunner = (args: string[], cwd: string) => Promise<string | undefined>;
|
|
105
|
+
/**
|
|
106
|
+
* What the thread changed in its worktree, against where its branch left the
|
|
107
|
+
* default branch: commits, uncommitted edits, and new files not yet added
|
|
108
|
+
* (`git diff` alone never counts an untracked file, so a thread that made one
|
|
109
|
+
* would read "No changes yet").
|
|
110
|
+
*/
|
|
111
|
+
export declare function diffStats(cwd: string, git?: GitRunner, countLines?: (file: string) => number): Promise<{
|
|
112
|
+
filesChanged: number;
|
|
113
|
+
additions: number;
|
|
114
|
+
deletions: number;
|
|
115
|
+
} | undefined>;
|
|
116
|
+
/** Stable approval id for one permission prompt, so a retried hook doesn't make two. */
|
|
117
|
+
export declare function approvalIdFor(parts: (string | undefined)[]): string;
|
|
118
|
+
/** A one-line description of what a tool wants to do. */
|
|
119
|
+
export declare function permissionCommand(toolName: string | undefined, toolInput: unknown): string;
|
|
120
|
+
export interface HookContext {
|
|
121
|
+
env: NodeJS.ProcessEnv;
|
|
122
|
+
now: () => number;
|
|
123
|
+
git: GitRunner;
|
|
124
|
+
readTranscript: (file: string) => string | undefined;
|
|
125
|
+
}
|
|
126
|
+
/** Events for one Claude Code hook invocation. Pure apart from the context's readers. */
|
|
127
|
+
export declare function claudeHookEvents(hook: string, input: Record<string, unknown>, ctx: HookContext): Promise<CodeThreadEvent[]>;
|
|
128
|
+
/** Events for one Codex `notify` call; `payload` is the JSON Codex passes as the last argument. */
|
|
129
|
+
export declare function codexNotifyEvents(payload: string, now: number): CodeThreadEvent[];
|
|
130
|
+
/**
|
|
131
|
+
* One hook can report several events at the moment it fired (`stop` then
|
|
132
|
+
* `stats`). Ingest drops an event older than the newest it applied for the
|
|
133
|
+
* thread, so each later event gets a later `at` — a millisecond apart.
|
|
134
|
+
*/
|
|
135
|
+
export declare function strictlyIncreasing(events: CodeThreadEvent[]): CodeThreadEvent[];
|
|
136
|
+
export interface RunHookOptions {
|
|
137
|
+
env?: NodeJS.ProcessEnv;
|
|
138
|
+
stdin?: NodeJS.ReadableStream;
|
|
139
|
+
fetchImpl?: typeof fetch;
|
|
140
|
+
now?: () => number;
|
|
141
|
+
git?: GitRunner;
|
|
142
|
+
sleep?: (ms: number) => Promise<void>;
|
|
143
|
+
/** A waiting `PermissionRequest` hook's decision output (default: stdout). */
|
|
144
|
+
stdout?: (text: string) => void;
|
|
145
|
+
/** Registers what runs when Claude Code stops a waiting hook (default: the signal handlers). */
|
|
146
|
+
onStop?: (handler: () => void) => void;
|
|
147
|
+
claudeVersion?: () => Promise<string | undefined>;
|
|
148
|
+
}
|
|
149
|
+
/** `--wait <seconds>` on the hook's command line, capped below its timeout; 0 without one. */
|
|
150
|
+
export declare function waitArg(args: string[]): number;
|
|
151
|
+
/**
|
|
152
|
+
* "Allow for this session", as Claude Code offers it for this prompt: its first
|
|
153
|
+
* suggestion that adds an allow rule, kept to the session. Only that kind: a
|
|
154
|
+
* suggestion to add a directory or switch mode grants more than the one call
|
|
155
|
+
* the person decided on. None: the option isn't offered.
|
|
156
|
+
*/
|
|
157
|
+
export declare function sessionRule(suggestions: unknown): Record<string, unknown> | undefined;
|
|
158
|
+
/** The hook's stdout for a decision: what Claude Code applies to the prompt. */
|
|
159
|
+
export declare function decisionOutput(decision: HostDecision, rule: Record<string, unknown> | undefined): string;
|
|
160
|
+
export interface PermissionWait {
|
|
161
|
+
/** How long to wait for a decision from ProhostAI. */
|
|
162
|
+
waitMs: number;
|
|
163
|
+
/**
|
|
164
|
+
* Why the prompt is the terminal's when the hook doesn't wait (`waitMs` 0), as `prompt_local`
|
|
165
|
+
* says it: remote control is off, or the window was launched before hooks waited.
|
|
166
|
+
*/
|
|
167
|
+
localReason: PromptLocalReason;
|
|
168
|
+
stdout: (text: string) => void;
|
|
169
|
+
/** Called with a handler for SIGTERM/SIGINT/SIGHUP: Claude Code stopping the hook (Escape, "No"). */
|
|
170
|
+
onStop: (handler: () => void) => void;
|
|
171
|
+
}
|
|
172
|
+
/** Why a prompt is answered in the terminal, as `prompt_local {reason}` tells the server. */
|
|
173
|
+
export type PromptLocalReason = 'timeout' | 'remote_off' | 'launched_before_update' | 'no_hook';
|
|
174
|
+
/**
|
|
175
|
+
* `prohost hook claude <Event>` / `prohost hook codex <payload>`. Critical invocation
|
|
176
|
+
* recording failures are nonzero; ordinary reporting failures stay nonblocking.
|
|
177
|
+
*/
|
|
178
|
+
export declare function runHook(args: string[], options?: RunHookOptions): Promise<number>;
|