@goodfoot/agent-hooks 1.0.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 (68) hide show
  1. package/README.md +137 -0
  2. package/dist/agents/antigravity/events.js +42 -0
  3. package/dist/agents/antigravity/hooks.js +59 -0
  4. package/dist/agents/antigravity/index.js +28 -0
  5. package/dist/agents/antigravity/outputs.js +81 -0
  6. package/dist/agents/antigravity/transport.js +84 -0
  7. package/dist/agents/antigravity/types.js +11 -0
  8. package/dist/agents/claude-code/env.js +27 -0
  9. package/dist/agents/claude-code/events.js +87 -0
  10. package/dist/agents/claude-code/hooks.js +1000 -0
  11. package/dist/agents/claude-code/index.js +57 -0
  12. package/dist/agents/claude-code/outputs.js +579 -0
  13. package/dist/agents/claude-code/tool-helpers.js +840 -0
  14. package/dist/agents/claude-code/transport.js +254 -0
  15. package/dist/agents/claude-code/types.js +11 -0
  16. package/dist/agents/codex/cli-support.js +318 -0
  17. package/dist/agents/codex/constants.js +29 -0
  18. package/dist/agents/codex/events.js +68 -0
  19. package/dist/agents/codex/hooks.js +93 -0
  20. package/dist/agents/codex/index.js +21 -0
  21. package/dist/agents/codex/outputs.js +189 -0
  22. package/dist/agents/codex/scaffold.js +273 -0
  23. package/dist/agents/codex/transport.js +139 -0
  24. package/dist/agents/codex/types.js +1 -0
  25. package/dist/cli.js +1357 -0
  26. package/dist/constants.js +39 -0
  27. package/dist/core/define-hook.js +61 -0
  28. package/dist/core/env.js +186 -0
  29. package/dist/core/logger.js +508 -0
  30. package/dist/core/stdin.js +38 -0
  31. package/dist/core/transport.js +231 -0
  32. package/dist/core/types.js +10 -0
  33. package/dist/index.js +17 -0
  34. package/dist/scaffold.js +512 -0
  35. package/package.json +61 -0
  36. package/types/agents/antigravity/events.d.ts +50 -0
  37. package/types/agents/antigravity/hooks.d.ts +76 -0
  38. package/types/agents/antigravity/index.d.ts +27 -0
  39. package/types/agents/antigravity/outputs.d.ts +107 -0
  40. package/types/agents/antigravity/transport.d.ts +47 -0
  41. package/types/agents/antigravity/types.d.ts +58 -0
  42. package/types/agents/claude-code/env.d.ts +27 -0
  43. package/types/agents/claude-code/events.d.ts +69 -0
  44. package/types/agents/claude-code/hooks.d.ts +1182 -0
  45. package/types/agents/claude-code/index.d.ts +23 -0
  46. package/types/agents/claude-code/outputs.d.ts +1160 -0
  47. package/types/agents/claude-code/tool-helpers.d.ts +807 -0
  48. package/types/agents/claude-code/transport.d.ts +119 -0
  49. package/types/agents/claude-code/types.d.ts +557 -0
  50. package/types/agents/codex/cli-support.d.ts +105 -0
  51. package/types/agents/codex/constants.d.ts +10 -0
  52. package/types/agents/codex/events.d.ts +63 -0
  53. package/types/agents/codex/hooks.d.ts +135 -0
  54. package/types/agents/codex/index.d.ts +19 -0
  55. package/types/agents/codex/outputs.d.ts +190 -0
  56. package/types/agents/codex/scaffold.d.ts +14 -0
  57. package/types/agents/codex/transport.d.ts +74 -0
  58. package/types/agents/codex/types.d.ts +131 -0
  59. package/types/cli.d.ts +315 -0
  60. package/types/constants.d.ts +9 -0
  61. package/types/core/define-hook.d.ts +39 -0
  62. package/types/core/env.d.ts +150 -0
  63. package/types/core/logger.d.ts +476 -0
  64. package/types/core/stdin.d.ts +21 -0
  65. package/types/core/transport.d.ts +131 -0
  66. package/types/core/types.d.ts +137 -0
  67. package/types/index.d.ts +18 -0
  68. package/types/scaffold.d.ts +46 -0
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Codex-specific CLI internals: AST analysis (with `statusMessage`), bundle
3
+ * compilation linking the Codex runtime module, command-context detection
4
+ * (`.codex-plugin` marker / `.codex` local mode / absolute), hooks.json
5
+ * generation with Codex's matcher/timeout-seconds/statusMessage rules, and
6
+ * plugin-mode stable-names default.
7
+ *
8
+ * Driver-level primitives (loader parsing, glob discovery, content hashing,
9
+ * symlink re-rooting, stale-bundle pruning) are imported from the shared CLI
10
+ * module — never re-derived here.
11
+ * @module
12
+ */
13
+ import * as esbuild from "esbuild";
14
+ import type { HookEventName } from "./types.js";
15
+ /** Codex CLI arguments accepted on top of the shared `--agent codex` gate. */
16
+ export interface CodexCliArgs {
17
+ input: string;
18
+ output: string;
19
+ executable?: string;
20
+ loaderFlags: string[];
21
+ pluginRoot: boolean;
22
+ stableNames?: boolean;
23
+ sourcemap?: boolean;
24
+ }
25
+ export type CommandMode = "plugin" | "codex-local" | "absolute";
26
+ export interface CommandContext {
27
+ mode: CommandMode;
28
+ pluginRoot?: string;
29
+ }
30
+ export interface CodexHookMetadata {
31
+ hookEventName: HookEventName;
32
+ matcher?: string;
33
+ timeout?: number;
34
+ statusMessage?: string;
35
+ }
36
+ interface CompiledHook {
37
+ sourcePath: string;
38
+ outputPath: string;
39
+ outputFilename: string;
40
+ metadata: CodexHookMetadata;
41
+ }
42
+ interface HookConfigEntry {
43
+ type: "command";
44
+ command: string;
45
+ timeout?: number;
46
+ statusMessage?: string;
47
+ }
48
+ export interface CodexMatcherEntry {
49
+ matcher?: string;
50
+ hooks: HookConfigEntry[];
51
+ }
52
+ export interface CodexHooksJson {
53
+ hooks: Partial<Record<HookEventName, CodexMatcherEntry[]>>;
54
+ }
55
+ type HookLoaderMap = Record<string, esbuild.Loader>;
56
+ /**
57
+ * Extracts Codex hook metadata (event name, matcher, timeout in
58
+ * milliseconds, status message) from a TypeScript source file's default
59
+ * export of a hook factory call.
60
+ */
61
+ export declare function analyzeCodexHookFile(sourcePath: string): CodexHookMetadata | undefined;
62
+ /**
63
+ * Compiles one Codex hook to a self-contained ESM executable whose entry
64
+ * wrapper imports this package's Codex runtime module (`execute`).
65
+ */
66
+ export declare function compileCodexHook(sourcePath: string, loaders: HookLoaderMap, sourcemap?: boolean): Promise<{
67
+ content: string;
68
+ contentHash: string;
69
+ }>;
70
+ /**
71
+ * Detects the command context: `.codex-plugin/` marker found by walking up
72
+ * from the output → plugin mode; explicit `--plugin-root` flag → plugin mode
73
+ * anchored at the output's parent; output under a `/.codex` segment →
74
+ * codex-local mode; otherwise absolute.
75
+ */
76
+ export declare function detectCodexCommandContext(outputPath: string, pluginRootFlag: boolean): CommandContext;
77
+ /** Generates Codex hooks.json: matchers only where the event supports them, timeouts in seconds, statusMessage when set. */
78
+ export declare function generateCodexHooksJson(compiledHooks: CompiledHook[], outputPath: string, executable?: string, context?: CommandContext): CodexHooksJson;
79
+ /**
80
+ * Validates Codex build/scaffold arguments beyond the shared `--agent` gate:
81
+ * `-i` and `-o` required for build mode; scaffold requires `--hooks` and
82
+ * `-o`.
83
+ */
84
+ export declare function validateCodexArgs(args: CodexCliArgs & {
85
+ scaffold?: string;
86
+ hooks?: string;
87
+ }): string | undefined;
88
+ /**
89
+ * Runs the Codex build/scaffold branch of the unified CLI. Plugin mode
90
+ * defaults to hash-free stable filenames; every other mode defaults to
91
+ * hashed names unless `--stable-names` is passed explicitly (source
92
+ * parity).
93
+ */
94
+ export declare function runCodexCli(args: {
95
+ input: string;
96
+ output: string;
97
+ executable?: string;
98
+ loaderFlags: string[];
99
+ pluginRoot: boolean;
100
+ stableNames?: boolean;
101
+ sourcemap?: boolean;
102
+ scaffold?: string;
103
+ hooks?: string;
104
+ }): Promise<void>;
105
+ export {};
@@ -0,0 +1,10 @@
1
+ import type { HookEventName } from "./types.js";
2
+ export declare const PACKAGE_NAME = "@goodfoot/agent-hooks";
3
+ export declare const DEFAULT_TIMEOUT_MS = 600000;
4
+ export declare const DEFAULT_STATUS_MESSAGE: undefined;
5
+ export declare const DEFAULT_ESBUILD_LOADERS: {
6
+ readonly ".md": "text";
7
+ };
8
+ export declare const HOOK_FACTORY_TO_EVENT: Record<string, HookEventName>;
9
+ export declare const EVENTS_WITH_MATCHER: Set<HookEventName>;
10
+ export declare const EVENTS_WITH_TEXT_OUTPUT: Set<HookEventName>;
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Codex hook event names and the advisory fail-open allow-list.
3
+ *
4
+ * `HOOK_EVENT_NAMES` mirrors the `HookEventName` union in `types.ts` (10
5
+ * events). The advisory allow-list is **not** authored here: per the plan's
6
+ * derivation rule it is transcribed from `codex-hooks/README.md` — quoted
7
+ * below above the provenance notes — and `ADVISORY_EVENTS` is derived
8
+ * mechanically as "every event except the exclusion set". The unit test in
9
+ * `tests/agents/codex/` transcribes the same sentence a second time,
10
+ * independently, so the runtime list and the test oracle are two copies of
11
+ * the citation rather than one list read twice.
12
+ * @module
13
+ */
14
+ import type { UnexpectedErrorPolicy } from "../../core/types.js";
15
+ import type { HookEventName } from "./types.js";
16
+ /**
17
+ * All Codex hook event names as a readonly array (same order as the
18
+ * `HookEventName` union).
19
+ */
20
+ export declare const HOOK_EVENT_NAMES: readonly ["PreToolUse", "PostToolUse", "PermissionRequest", "UserPromptSubmit", "SessionStart", "SubagentStart", "Stop", "SubagentStop", "PreCompact", "PostCompact"];
21
+ /**
22
+ * Events never allowed the fail-open `unexpectedError: "continue"` policy.
23
+ *
24
+ * Transcribed verbatim from codex-hooks/README.md (Fail-Open Execution
25
+ * section):
26
+ *
27
+ * > Only opt in for **advisory enrichment hooks** — ones that add optional
28
+ * > context and whose failure should be invisible to the user (e.g.
29
+ * > `UserPromptSubmit`, `SessionStart`, `SubagentStart` context nudges). Do
30
+ * > not use `"continue"` for hooks that make permission, safety, or policy
31
+ * > decisions (`PreToolUse`, `PermissionRequest`, blocking
32
+ * > `PostToolUse`/`Stop`/`SubagentStop` checks) — silently swallowing a
33
+ * > failure there means the hook's decision was silently skipped.
34
+ *
35
+ * Provenance of each element:
36
+ *
37
+ * - `PreToolUse`, `PermissionRequest`, blocking `PostToolUse`/`Stop`/
38
+ * `SubagentStop` — named verbatim in the README sentence above.
39
+ * - `PreCompact`, `PostCompact` — **not mentioned anywhere in the README**;
40
+ * excluded by default (fail-closed) until a future card's docs justify an
41
+ * entry. This is a stated default, not a silent gap (plan Decisions).
42
+ */
43
+ export declare const EXCLUDED_FROM_ADVISORY: readonly ["PreToolUse", "PostToolUse", "PermissionRequest", "Stop", "SubagentStop", "PreCompact", "PostCompact"];
44
+ /** The exclusion set as a literal union. */
45
+ export type ExcludedEventName = (typeof EXCLUDED_FROM_ADVISORY)[number];
46
+ /** Type-level membership check: `true` only for excluded event names. */
47
+ export type IsExcludedEvent<TEventName extends HookEventName> = TEventName extends ExcludedEventName ? true : false;
48
+ /** The advisory allow-list as a literal union: every event except {@link ExcludedEventName}. */
49
+ export type AdvisoryEventName = Exclude<HookEventName, ExcludedEventName>;
50
+ /**
51
+ * The advisory allow-list: every Codex event except
52
+ * {@link EXCLUDED_FROM_ADVISORY} — exactly the README's three named
53
+ * enrichment hooks. Only these accept `unexpectedError: "continue"`,
54
+ * enforced at factory-call time by the injected policy gate and at compile
55
+ * time by the excluded events' narrowed config types.
56
+ */
57
+ export declare const ADVISORY_EVENTS: readonly AdvisoryEventName[];
58
+ /**
59
+ * The policy type an event may carry, narrowed by allow-list membership:
60
+ * advisory events keep `"error" | "continue"`; every excluded event collapses
61
+ * to `"error"`.
62
+ */
63
+ export type AllowedUnexpectedErrorPolicy<TEventName extends HookEventName> = IsExcludedEvent<TEventName> extends true ? Exclude<UnexpectedErrorPolicy, "continue"> : UnexpectedErrorPolicy;
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Typed factory functions for Codex hooks, built on the shared core
3
+ * {@link ../core/define-hook.ts|defineHook}.
4
+ *
5
+ * Public surface mirrors the source codex-hooks package 1.3.0: same factory names,
6
+ * config shapes (`MatcherHookConfig`/`NoMatcherHookConfig`, including
7
+ * `statusMessage`), result unions, and `hookEventName` metadata property.
8
+ * Two deliberate additions carry the consolidation contract:
9
+ *
10
+ * - every factory injects the advisory allow-list policy gate, so
11
+ * `unexpectedError: "continue"` fails closed at factory-call time for any
12
+ * event not on {@link ADVISORY_EVENTS};
13
+ * - non-advisory events' config types narrow the policy field via
14
+ * {@link MatcherHookConfigFor}/{@link NoMatcherHookConfigFor}, rejecting
15
+ * `"continue"` at compile time as well.
16
+ * @module
17
+ */
18
+ import type { HookContext, UnexpectedErrorHandler, UnexpectedErrorPolicy } from "../../core/types.js";
19
+ import { type AllowedUnexpectedErrorPolicy } from "./events.js";
20
+ import type { PermissionRequestOutput, PostCompactOutput, PostToolUseOutput, PreCompactOutput, PreToolUseOutput, SessionStartOutput, StopOutput, SubagentStartOutput, SubagentStopOutput, UserPromptSubmitOutput } from "./outputs.js";
21
+ import type { HookEventName, PermissionRequestInput, PostCompactInput, PostToolUseInput, PreCompactInput, PreToolUseInput, SessionStartInput, StopInput, SubagentStartInput, SubagentStopInput, UserPromptSubmitInput } from "./types.js";
22
+ /**
23
+ * Policy/phase/diagnostic vocabulary is shared across agents and owned by the
24
+ * core; re-exported here so the Codex surface keeps its historical import
25
+ * site (`hooks.js`). See the Claude Code surface's documentation of the same
26
+ * vocabulary for the full fail-open contract.
27
+ */
28
+ export type { HookContext, UnexpectedErrorHandler, UnexpectedErrorPolicy };
29
+ /**
30
+ * The base config shapes from the source package. `statusMessage` is a Codex
31
+ *-specific field: it flows into generated `hooks.json` entries by the CLI.
32
+ */
33
+ export interface MatcherHookConfig {
34
+ matcher?: string;
35
+ timeout?: number;
36
+ statusMessage?: string;
37
+ unexpectedError?: UnexpectedErrorPolicy;
38
+ onUnexpectedError?: UnexpectedErrorHandler;
39
+ }
40
+ export interface NoMatcherHookConfig {
41
+ timeout?: number;
42
+ statusMessage?: string;
43
+ unexpectedError?: UnexpectedErrorPolicy;
44
+ onUnexpectedError?: UnexpectedErrorHandler;
45
+ }
46
+ /**
47
+ * Per-event matcher config with the fail-open policy narrowed by the advisory
48
+ * allow-list: excluded events collapse `unexpectedError` to `"error"` only.
49
+ * @template TEvent - The event the factory binds.
50
+ */
51
+ export type MatcherHookConfigFor<TEvent extends HookEventName> = Omit<MatcherHookConfig, "unexpectedError"> & {
52
+ unexpectedError?: AllowedUnexpectedErrorPolicy<TEvent>;
53
+ };
54
+ /** Per-event no-matcher variant of {@link MatcherHookConfigFor}. @template TEvent - The event the factory binds. */
55
+ export type NoMatcherHookConfigFor<TEvent extends HookEventName> = Omit<NoMatcherHookConfig, "unexpectedError"> & {
56
+ unexpectedError?: AllowedUnexpectedErrorPolicy<TEvent>;
57
+ };
58
+ type PreToolUseResult = PreToolUseOutput | undefined;
59
+ type PostToolUseResult = PostToolUseOutput | undefined;
60
+ type PermissionRequestResult = PermissionRequestOutput | undefined;
61
+ type UserPromptSubmitResult = UserPromptSubmitOutput | string | undefined;
62
+ type SessionStartResult = SessionStartOutput | string | undefined;
63
+ type SubagentStartResult = SubagentStartOutput | string | undefined;
64
+ type StopResult = StopOutput | undefined;
65
+ type SubagentStopResult = SubagentStopOutput | undefined;
66
+ type PreCompactResult = PreCompactOutput | undefined;
67
+ type PostCompactResult = PostCompactOutput | undefined;
68
+ /**
69
+ * The result of a hook factory — a function wrapping the handler, carrying
70
+ * its metadata for the driver and the CLI's AST analysis. Preserves the
71
+ * source package's `hookEventName` property name alongside the core's
72
+ * `eventName`.
73
+ * @template TInput - The input type for this hook
74
+ * @template TOutput - The output type for this hook
75
+ * @template TEvent - The literal event name this hook is bound to
76
+ */
77
+ export interface HookFunction<TInput, TOutput, TEvent extends string> {
78
+ /**
79
+ * Execute the hook handler with the given input and context.
80
+ */
81
+ (input: TInput, context: HookContext): Promise<TOutput | null>;
82
+ /**
83
+ * The Codex event name this hook is for (source-package property name).
84
+ */
85
+ hookEventName: TEvent;
86
+ /**
87
+ * The core driver's event-name property; identical value.
88
+ */
89
+ eventName: string;
90
+ /**
91
+ * The matcher pattern, if configured.
92
+ */
93
+ matcher?: string;
94
+ /**
95
+ * The timeout in milliseconds, if configured.
96
+ */
97
+ timeout?: number;
98
+ /**
99
+ * Codex-specific status message shown while the hook runs.
100
+ */
101
+ statusMessage?: string;
102
+ /**
103
+ * The fail-open policy, if configured.
104
+ */
105
+ unexpectedError?: UnexpectedErrorPolicy;
106
+ /**
107
+ * The diagnostic callback for the "continue" policy, if configured.
108
+ */
109
+ onUnexpectedError?: UnexpectedErrorHandler;
110
+ /**
111
+ * Optional context factory (unused by the Codex surface today; part of the
112
+ * shared core function shape).
113
+ */
114
+ createContext?: (input: TInput) => HookContext;
115
+ }
116
+ /** Creates a PreToolUse hook handler. Excluded from the advisory list. */
117
+ export declare function preToolUseHook(config: MatcherHookConfigFor<"PreToolUse">, handler: (input: PreToolUseInput, context: HookContext) => PreToolUseResult | Promise<PreToolUseResult>): HookFunction<PreToolUseInput, PreToolUseResult, "PreToolUse">;
118
+ /** Creates a PostToolUse hook handler. Blocking variant excluded from the advisory list. */
119
+ export declare function postToolUseHook(config: MatcherHookConfigFor<"PostToolUse">, handler: (input: PostToolUseInput, context: HookContext) => PostToolUseResult | Promise<PostToolUseResult>): HookFunction<PostToolUseInput, PostToolUseResult, "PostToolUse">;
120
+ /** Creates a PermissionRequest hook handler. Excluded from the advisory list. */
121
+ export declare function permissionRequestHook(config: MatcherHookConfigFor<"PermissionRequest">, handler: (input: PermissionRequestInput, context: HookContext) => PermissionRequestResult | Promise<PermissionRequestResult>): HookFunction<PermissionRequestInput, PermissionRequestResult, "PermissionRequest">;
122
+ /** Creates a UserPromptSubmit hook handler. Advisory enrichment hook. */
123
+ export declare function userPromptSubmitHook(config: NoMatcherHookConfigFor<"UserPromptSubmit">, handler: (input: UserPromptSubmitInput, context: HookContext) => UserPromptSubmitResult | Promise<UserPromptSubmitResult>): HookFunction<UserPromptSubmitInput, UserPromptSubmitResult, "UserPromptSubmit">;
124
+ /** Creates a SessionStart hook handler. Advisory enrichment hook. */
125
+ export declare function sessionStartHook(config: MatcherHookConfigFor<"SessionStart">, handler: (input: SessionStartInput, context: HookContext) => SessionStartResult | Promise<SessionStartResult>): HookFunction<SessionStartInput, SessionStartResult, "SessionStart">;
126
+ /** Creates a SubagentStart hook handler. Advisory enrichment hook. */
127
+ export declare function subagentStartHook(config: MatcherHookConfigFor<"SubagentStart">, handler: (input: SubagentStartInput, context: HookContext) => SubagentStartResult | Promise<SubagentStartResult>): HookFunction<SubagentStartInput, SubagentStartResult, "SubagentStart">;
128
+ /** Creates a Stop hook handler. Blocking variant excluded from the advisory list. */
129
+ export declare function stopHook(config: NoMatcherHookConfigFor<"Stop">, handler: (input: StopInput, context: HookContext) => StopResult | Promise<StopResult>): HookFunction<StopInput, StopResult, "Stop">;
130
+ /** Creates a SubagentStop hook handler. Blocking variant excluded from the advisory list. */
131
+ export declare function subagentStopHook(config: MatcherHookConfigFor<"SubagentStop">, handler: (input: SubagentStopInput, context: HookContext) => SubagentStopResult | Promise<SubagentStopResult>): HookFunction<SubagentStopInput, SubagentStopResult, "SubagentStop">;
132
+ /** Creates a PreCompact hook handler. Excluded by default pending doc clarification. */
133
+ export declare function preCompactHook(config: MatcherHookConfigFor<"PreCompact">, handler: (input: PreCompactInput, context: HookContext) => PreCompactResult | Promise<PreCompactResult>): HookFunction<PreCompactInput, PreCompactResult, "PreCompact">;
134
+ /** Creates a PostCompact hook handler. Excluded by default pending doc clarification. */
135
+ export declare function postCompactHook(config: MatcherHookConfigFor<"PostCompact">, handler: (input: PostCompactInput, context: HookContext) => PostCompactResult | Promise<PostCompactResult>): HookFunction<PostCompactInput, PostCompactResult, "PostCompact">;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * `@goodfoot/agent-hooks/codex` — the Codex agent surface.
3
+ *
4
+ * Re-exports all 10 hook factories, their output builders (reserved fields
5
+ * emitted only when passed), the `BlockError` block signal, input/output
6
+ * types, constants, the advisory allow-list events module, Logger, and the
7
+ * runtime `execute` entry point. No default export.
8
+ * @module
9
+ */
10
+ export type { LogEvent, LogEventHandler, LoggerConfig, LogLevel, Unsubscribe } from "../../core/logger.js";
11
+ export { LOG_LEVELS, Logger, logger } from "../../core/logger.js";
12
+ export { DEFAULT_ESBUILD_LOADERS, DEFAULT_TIMEOUT_MS, EVENTS_WITH_MATCHER, EVENTS_WITH_TEXT_OUTPUT, HOOK_FACTORY_TO_EVENT, PACKAGE_NAME, } from "./constants.js";
13
+ export type { AdvisoryEventName, AllowedUnexpectedErrorPolicy, ExcludedEventName, IsExcludedEvent, } from "./events.js";
14
+ export { ADVISORY_EVENTS, EXCLUDED_FROM_ADVISORY, HOOK_EVENT_NAMES } from "./events.js";
15
+ export type { HookContext, HookFunction, MatcherHookConfig, MatcherHookConfigFor, NoMatcherHookConfig, NoMatcherHookConfigFor, UnexpectedErrorHandler, UnexpectedErrorPolicy, } from "./hooks.js";
16
+ export { permissionRequestHook, postCompactHook, postToolUseHook, preCompactHook, preToolUseHook, sessionStartHook, stopHook, subagentStartHook, subagentStopHook, userPromptSubmitHook, } from "./hooks.js";
17
+ export { BlockError, EXIT_CODES, type ExitCode, type HookOutput, type HookSpecificOutput, type PermissionRequestBehavior, type PermissionRequestDecision, type PermissionRequestHookSpecificOutput, type PermissionRequestOptions, type PermissionRequestOutput, type PostCompactOptions, type PostCompactOutput, type PostToolUseHookSpecificOutput, type PostToolUseOptions, type PostToolUseOutput, type PreCompactOptions, type PreCompactOutput, type PreToolUseHookSpecificOutput, type PreToolUseLegacyBlockOptions, type PreToolUseOptions, type PreToolUseOutput, type PreToolUsePermissionDecision, permissionRequestOutput, postCompactOutput, postToolUseOutput, preCompactOutput, preToolUseLegacyBlockOutput, preToolUseOutput, type RawOutput, rawOutput, type SessionStartHookSpecificOutput, type SessionStartOptions, type SessionStartOutput, type SpecificHookOutput, type StopOptions, type StopOutput, type SubagentStartHookSpecificOutput, type SubagentStartOptions, type SubagentStartOutput, type SubagentStopOptions, type SubagentStopOutput, type SyncHookJSONOutput, sessionStartOutput, stopOutput, subagentStartOutput, subagentStopOutput, type UserPromptSubmitHookSpecificOutput, type UserPromptSubmitOptions, type UserPromptSubmitOutput, userPromptSubmitOutput, } from "./outputs.js";
18
+ export { convertToHookOutput, createCodexTransport, execute } from "./transport.js";
19
+ export type { BaseHookInput, HookErrorPhase, HookEventName, HookInput, PermissionMode, PermissionRequestInput, PostCompactInput, PostToolUseInput, PreCompactInput, PreCompactTrigger, PreToolUseInput, SessionStartInput, SessionStartSource, StopInput, SubagentStartInput, SubagentStopInput, UserPromptSubmitInput, } from "./types.js";
@@ -0,0 +1,190 @@
1
+ import { HookBlockError } from "../../core/transport.js";
2
+ export declare const EXIT_CODES: {
3
+ readonly SUCCESS: 0;
4
+ readonly ERROR: 1;
5
+ readonly BLOCK: 2;
6
+ };
7
+ export type ExitCode = (typeof EXIT_CODES)[keyof typeof EXIT_CODES];
8
+ interface BaseSpecificOutput<T extends string> {
9
+ readonly _type: T;
10
+ readonly stdout: SyncHookJSONOutput;
11
+ readonly stderr?: string;
12
+ }
13
+ export type RawOutput = BaseSpecificOutput<"Raw">;
14
+ export type PreToolUseOutput = BaseSpecificOutput<"PreToolUse">;
15
+ export type PostToolUseOutput = BaseSpecificOutput<"PostToolUse">;
16
+ export type PermissionRequestOutput = BaseSpecificOutput<"PermissionRequest">;
17
+ export type UserPromptSubmitOutput = BaseSpecificOutput<"UserPromptSubmit">;
18
+ export type SessionStartOutput = BaseSpecificOutput<"SessionStart">;
19
+ export type SubagentStartOutput = BaseSpecificOutput<"SubagentStart">;
20
+ export type StopOutput = BaseSpecificOutput<"Stop">;
21
+ export type SubagentStopOutput = BaseSpecificOutput<"SubagentStop">;
22
+ export type PreCompactOutput = BaseSpecificOutput<"PreCompact">;
23
+ export type PostCompactOutput = BaseSpecificOutput<"PostCompact">;
24
+ export type SpecificHookOutput = RawOutput | PreToolUseOutput | PostToolUseOutput | PermissionRequestOutput | UserPromptSubmitOutput | SessionStartOutput | SubagentStartOutput | StopOutput | SubagentStopOutput | PreCompactOutput | PostCompactOutput;
25
+ export interface HookOutput {
26
+ stdout: SyncHookJSONOutput;
27
+ stderr?: string;
28
+ }
29
+ export interface SyncHookJSONOutput {
30
+ continue?: boolean;
31
+ decision?: "approve" | "block";
32
+ hookSpecificOutput?: HookSpecificOutput;
33
+ reason?: string;
34
+ stopReason?: string;
35
+ suppressOutput?: boolean;
36
+ systemMessage?: string;
37
+ }
38
+ export type HookSpecificOutput = PreToolUseHookSpecificOutput | PostToolUseHookSpecificOutput | PermissionRequestHookSpecificOutput | UserPromptSubmitHookSpecificOutput | SessionStartHookSpecificOutput | SubagentStartHookSpecificOutput;
39
+ export type PreToolUsePermissionDecision = "allow" | "deny" | "ask";
40
+ export interface PreToolUseHookSpecificOutput {
41
+ hookEventName: "PreToolUse";
42
+ additionalContext?: string;
43
+ permissionDecision?: PreToolUsePermissionDecision;
44
+ permissionDecisionReason?: string;
45
+ updatedInput?: unknown;
46
+ }
47
+ export interface PostToolUseHookSpecificOutput {
48
+ hookEventName: "PostToolUse";
49
+ additionalContext?: string;
50
+ updatedMCPToolOutput?: unknown;
51
+ }
52
+ export type PermissionRequestBehavior = "allow" | "deny";
53
+ export interface PermissionRequestDecision {
54
+ behavior: PermissionRequestBehavior;
55
+ message?: string;
56
+ interrupt?: boolean;
57
+ updatedInput?: unknown;
58
+ updatedPermissions?: unknown;
59
+ }
60
+ export interface PermissionRequestHookSpecificOutput {
61
+ hookEventName: "PermissionRequest";
62
+ decision?: PermissionRequestDecision;
63
+ }
64
+ export interface UserPromptSubmitHookSpecificOutput {
65
+ hookEventName: "UserPromptSubmit";
66
+ additionalContext?: string;
67
+ }
68
+ export interface SessionStartHookSpecificOutput {
69
+ hookEventName: "SessionStart";
70
+ additionalContext?: string;
71
+ }
72
+ export interface SubagentStartHookSpecificOutput {
73
+ hookEventName: "SubagentStart";
74
+ additionalContext?: string;
75
+ }
76
+ export interface PreToolUseOptions {
77
+ continue?: boolean;
78
+ stopReason?: string;
79
+ suppressOutput?: boolean;
80
+ systemMessage?: string;
81
+ decision?: "approve" | "block";
82
+ reason?: string;
83
+ additionalContext?: string;
84
+ permissionDecision?: PreToolUsePermissionDecision;
85
+ permissionDecisionReason?: string;
86
+ updatedInput?: unknown;
87
+ }
88
+ export interface PreToolUseLegacyBlockOptions {
89
+ systemMessage?: string;
90
+ decision: "block";
91
+ reason: string;
92
+ }
93
+ export interface PostToolUseOptions {
94
+ continue?: boolean;
95
+ stopReason?: string;
96
+ suppressOutput?: boolean;
97
+ systemMessage?: string;
98
+ decision?: "block";
99
+ reason?: string;
100
+ additionalContext?: string;
101
+ updatedMCPToolOutput?: unknown;
102
+ }
103
+ export interface PermissionRequestOptions {
104
+ continue?: boolean;
105
+ stopReason?: string;
106
+ suppressOutput?: boolean;
107
+ systemMessage?: string;
108
+ behavior: PermissionRequestBehavior;
109
+ message?: string;
110
+ interrupt?: boolean;
111
+ updatedInput?: unknown;
112
+ updatedPermissions?: unknown;
113
+ }
114
+ export interface UserPromptSubmitOptions {
115
+ continue?: boolean;
116
+ stopReason?: string;
117
+ suppressOutput?: boolean;
118
+ systemMessage?: string;
119
+ decision?: "block";
120
+ reason?: string;
121
+ additionalContext?: string;
122
+ }
123
+ export interface SessionStartOptions {
124
+ continue?: boolean;
125
+ stopReason?: string;
126
+ suppressOutput?: boolean;
127
+ systemMessage?: string;
128
+ additionalContext?: string;
129
+ }
130
+ export interface SubagentStartOptions {
131
+ continue?: boolean;
132
+ stopReason?: string;
133
+ suppressOutput?: boolean;
134
+ systemMessage?: string;
135
+ additionalContext?: string;
136
+ }
137
+ export interface StopOptions {
138
+ continue?: boolean;
139
+ stopReason?: string;
140
+ suppressOutput?: boolean;
141
+ systemMessage?: string;
142
+ decision?: "block";
143
+ reason?: string;
144
+ }
145
+ export interface SubagentStopOptions {
146
+ continue?: boolean;
147
+ stopReason?: string;
148
+ suppressOutput?: boolean;
149
+ systemMessage?: string;
150
+ decision?: "block";
151
+ reason?: string;
152
+ }
153
+ export interface PreCompactOptions {
154
+ continue?: boolean;
155
+ stopReason?: string;
156
+ suppressOutput?: boolean;
157
+ systemMessage?: string;
158
+ }
159
+ export interface PostCompactOptions {
160
+ continue?: boolean;
161
+ stopReason?: string;
162
+ suppressOutput?: boolean;
163
+ systemMessage?: string;
164
+ }
165
+ /**
166
+ * The Codex block signal, carried into the new package as a subclass of the
167
+ * shared core {@link ../core/transport.ts|HookBlockError} so `drive()`
168
+ * classifies it **before** consulting `unexpectedError` policy — carrying an
169
+ * ordering the source runtime already implemented (`runtime.ts` tested
170
+ * `instanceof BlockError` ahead of the policy branch). Public surface is
171
+ * preserved: `name`, `reason`, and `instanceof BlockError` semantics are
172
+ * unchanged, and `instanceof HookBlockError` now also holds.
173
+ */
174
+ export declare class BlockError extends HookBlockError {
175
+ readonly reason: string;
176
+ constructor(reason: string);
177
+ }
178
+ export declare function rawOutput(stdout: SyncHookJSONOutput, stderr?: string): SpecificHookOutput;
179
+ export declare function preToolUseOutput(options?: PreToolUseOptions): PreToolUseOutput;
180
+ export declare function preToolUseLegacyBlockOutput(options: PreToolUseLegacyBlockOptions): PreToolUseOutput;
181
+ export declare function postToolUseOutput(options?: PostToolUseOptions): PostToolUseOutput;
182
+ export declare function permissionRequestOutput(options: PermissionRequestOptions): PermissionRequestOutput;
183
+ export declare function userPromptSubmitOutput(options?: UserPromptSubmitOptions): UserPromptSubmitOutput;
184
+ export declare function sessionStartOutput(options?: SessionStartOptions): SessionStartOutput;
185
+ export declare function subagentStartOutput(options?: SubagentStartOptions): SubagentStartOutput;
186
+ export declare function stopOutput(options?: StopOptions): StopOutput;
187
+ export declare function subagentStopOutput(options?: SubagentStopOptions): SubagentStopOutput;
188
+ export declare function preCompactOutput(options?: PreCompactOptions): PreCompactOutput;
189
+ export declare function postCompactOutput(options?: PostCompactOptions): PostCompactOutput;
190
+ export {};
@@ -0,0 +1,14 @@
1
+ import type { HookEventName } from "./types.js";
2
+ export interface ScaffoldOptions {
3
+ directory: string;
4
+ hooks: string[];
5
+ outputPath: string;
6
+ }
7
+ export declare function validateHookNames(hookNames: string[]): {
8
+ valid: true;
9
+ normalized: HookEventName[];
10
+ } | {
11
+ valid: false;
12
+ error: string;
13
+ };
14
+ export declare function scaffoldProject(options: ScaffoldOptions): void;
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Wire transport for Codex hooks, rewritten against the core
3
+ * `drive()`/`Transport` interface; the wire semantics carry over
4
+ * `codex-hooks/src/runtime.ts` verbatim:
5
+ *
6
+ * - **BlockError → its reason written to stderr + exit 2, regardless of
7
+ * policy** — a single translation for every event including
8
+ * `SubagentStart`; there is deliberately no per-event table here (Codex
9
+ * has no narrower native deny shape than the stderr channel). The source
10
+ * runtime already classified `BlockError` ahead of the policy branch; that
11
+ * precedence now lives in `drive()` via {@link BlockError} extending the
12
+ * core `HookBlockError`.
13
+ * - every other unexpected failure (stdin read, parse, handler, serialize,
14
+ * write, cleanup) under the default `"error"` policy → stacktrace on
15
+ * stderr + exit 1 (`ERROR`) — note Codex exits **1**, unlike Claude Code's
16
+ * handler-error exit 2; under `"continue"` → reported and swallowed to the
17
+ * event's valid empty output `{}` at exit 0. Malformed stdin is therefore
18
+ * NOT unconditionally fail-open on Codex — the policy decides, exactly as
19
+ * in the source runtime.
20
+ * - success → `JSON.stringify(output.stdout)` at exit 0; a `null`/`undefined`
21
+ * result serializes as `{}`, valid for every event's output schema.
22
+ * - a returned `stderr` **field** on an output object is carried by
23
+ * `convertToHookOutput` but discarded by the success path — the source
24
+ * runtime only ever serialized `output.stdout`; blocking is expressed
25
+ * exclusively through the thrown-`BlockError` channel.
26
+ *
27
+ * String returns (`"Loaded from text"`) are normalized into the event's
28
+ * additionalContext output for the three text-output events; any other event
29
+ * rejecting plain text throws exactly like the source, flowing through the
30
+ * standard policy-gated error path.
31
+ * @module
32
+ * @example
33
+ * ```typescript
34
+ * // In a compiled hook file
35
+ * import { execute } from './transport.js';
36
+ * import myHook from './my-hook.js';
37
+ *
38
+ * execute(myHook);
39
+ * ```
40
+ */
41
+ import type { Transport } from "../../core/transport.js";
42
+ import type { HookFunction } from "./hooks.js";
43
+ import { type SpecificHookOutput } from "./outputs.js";
44
+ import type { HookEventName, HookInput } from "./types.js";
45
+ /**
46
+ * Converts a SpecificHookOutput to the wire shape by stripping the `_type`
47
+ * discriminator (source parity: builders produce wire-format directly).
48
+ */
49
+ export declare function convertToHookOutput(output: SpecificHookOutput): {
50
+ stdout: SpecificHookOutput["stdout"];
51
+ stderr?: string;
52
+ };
53
+ /**
54
+ * Normalizes a plain-string handler return into the event's additionalContext
55
+ * output; non-text events reject strings with the source package's exact
56
+ * error, which then flows through the standard policy-gated error path.
57
+ */
58
+ export declare function normalizeStringOutput(hookEventName: HookEventName, result: string): SpecificHookOutput;
59
+ /**
60
+ * Builds the Codex wire transport. Unlike the Claude Code adapter there is no
61
+ * per-event block-shape table: every caught {@link BlockError} translates to
62
+ * `stderr: reason + "\n"` at exit 2 under every policy value, and no
63
+ * `rawStdout` predicate exists because Codex has no plain-text-stdout
64
+ * protocol events (the `rawOutput()` builder is ordinary JSON passthrough).
65
+ */
66
+ export declare function createCodexTransport(): Transport<SpecificHookOutput | undefined>;
67
+ /**
68
+ * Executes a hook handler with full runtime orchestration (delegates to the
69
+ * shared core driver with this agent's transport). String returns are
70
+ * normalized before the driver sees them so that a plain-text violation
71
+ * classifies through the same policy gate as any other handler failure,
72
+ * matching the source runtime's observable wire behaviour.
73
+ */
74
+ export declare function execute<TInput extends HookInput, TOutput>(hookFn: HookFunction<TInput, TOutput, HookEventName>): Promise<void>;