@with-logic/elwood 0.1.0 → 0.1.2
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 +182 -3
- package/CONTRIBUTING.md +104 -0
- package/LICENSE +1 -1
- package/README.md +295 -26
- package/SECURITY.md +42 -0
- package/dist/claude/command.d.ts +9 -2
- package/dist/claude/command.d.ts.map +1 -1
- package/dist/claude/command.js +23 -16
- package/dist/claude/command.js.map +1 -1
- package/dist/claude/model-picker.d.ts.map +1 -1
- package/dist/claude/model-picker.js +4 -3
- package/dist/claude/model-picker.js.map +1 -1
- package/dist/claude/model-switch-confirmation.js +9 -1
- package/dist/claude/model-switch-confirmation.js.map +1 -1
- package/dist/claude/screen-table.js +1 -1
- package/dist/claude/screen-table.js.map +1 -1
- package/dist/claude/session/build.d.ts.map +1 -1
- package/dist/claude/session/build.js +3 -0
- package/dist/claude/session/build.js.map +1 -1
- package/dist/claude/session/index.d.ts.map +1 -1
- package/dist/claude/session/index.js +5 -2
- package/dist/claude/session/index.js.map +1 -1
- package/dist/claude/session/resume.d.ts +1 -1
- package/dist/claude/session/resume.d.ts.map +1 -1
- package/dist/claude/session/resume.js +5 -1
- package/dist/claude/session/resume.js.map +1 -1
- package/dist/claude/session/start-or-resume.js +1 -0
- package/dist/claude/session/start-or-resume.js.map +1 -1
- package/dist/claude/simple.d.ts.map +1 -1
- package/dist/claude/simple.js +4 -0
- package/dist/claude/simple.js.map +1 -1
- package/dist/cli/args/index.d.ts +3 -1
- package/dist/cli/args/index.d.ts.map +1 -1
- package/dist/cli/args/index.js +10 -2
- package/dist/cli/args/index.js.map +1 -1
- package/dist/cli/args/options.d.ts.map +1 -1
- package/dist/cli/args/options.js +2 -0
- package/dist/cli/args/options.js.map +1 -1
- package/dist/cli/args-commands.d.ts +10 -0
- package/dist/cli/args-commands.d.ts.map +1 -0
- package/dist/cli/args-commands.js +113 -0
- package/dist/cli/args-commands.js.map +1 -0
- package/dist/cli/command-types.d.ts +26 -0
- package/dist/cli/command-types.d.ts.map +1 -0
- package/dist/cli/command-types.js +9 -0
- package/dist/cli/command-types.js.map +1 -0
- package/dist/cli/config/codec-primitives.d.ts +20 -0
- package/dist/cli/config/codec-primitives.d.ts.map +1 -0
- package/dist/cli/config/codec-primitives.js +51 -0
- package/dist/cli/config/codec-primitives.js.map +1 -0
- package/dist/cli/config/codec.d.ts.map +1 -1
- package/dist/cli/config/codec.js +4 -46
- package/dist/cli/config/codec.js.map +1 -1
- package/dist/cli/config/effective.d.ts.map +1 -1
- package/dist/cli/config/effective.js +1 -0
- package/dist/cli/config/effective.js.map +1 -1
- package/dist/cli/config/keys.d.ts +1 -1
- package/dist/cli/config/keys.d.ts.map +1 -1
- package/dist/cli/config/keys.js +1 -0
- package/dist/cli/config/keys.js.map +1 -1
- package/dist/cli/entry.d.ts +4 -2
- package/dist/cli/entry.d.ts.map +1 -1
- package/dist/cli/entry.js +2 -1
- package/dist/cli/entry.js.map +1 -1
- package/dist/cli/help.d.ts +2 -2
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +40 -1
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/interactive/index.d.ts +26 -0
- package/dist/cli/interactive/index.d.ts.map +1 -0
- package/dist/cli/interactive/index.js +33 -0
- package/dist/cli/interactive/index.js.map +1 -0
- package/dist/cli/interactive/launch.d.ts +14 -0
- package/dist/cli/interactive/launch.d.ts.map +1 -0
- package/dist/cli/interactive/launch.js +66 -0
- package/dist/cli/interactive/launch.js.map +1 -0
- package/dist/cli/interactive/spawn.d.ts +18 -0
- package/dist/cli/interactive/spawn.d.ts.map +1 -0
- package/dist/cli/interactive/spawn.js +53 -0
- package/dist/cli/interactive/spawn.js.map +1 -0
- package/dist/cli/main-failure.d.ts +28 -0
- package/dist/cli/main-failure.d.ts.map +1 -0
- package/dist/cli/main-failure.js +78 -0
- package/dist/cli/main-failure.js.map +1 -0
- package/dist/cli/main.d.ts +12 -4
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +27 -73
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/models/index.d.ts +20 -0
- package/dist/cli/models/index.d.ts.map +1 -0
- package/dist/cli/models/index.js +63 -0
- package/dist/cli/models/index.js.map +1 -0
- package/dist/cli/models/render.d.ts +9 -0
- package/dist/cli/models/render.d.ts.map +1 -0
- package/dist/cli/models/render.js +33 -0
- package/dist/cli/models/render.js.map +1 -0
- package/dist/cli/request/index.d.ts.map +1 -1
- package/dist/cli/request/index.js +8 -2
- package/dist/cli/request/index.js.map +1 -1
- package/dist/cli/request/layers.d.ts +2 -0
- package/dist/cli/request/layers.d.ts.map +1 -1
- package/dist/cli/request/layers.js +9 -5
- package/dist/cli/request/layers.js.map +1 -1
- package/dist/cli/request/posture.d.ts +28 -0
- package/dist/cli/request/posture.d.ts.map +1 -0
- package/dist/cli/request/posture.js +70 -0
- package/dist/cli/request/posture.js.map +1 -0
- package/dist/cli/request/resolution-types.d.ts +1 -0
- package/dist/cli/request/resolution-types.d.ts.map +1 -1
- package/dist/cli/request/settings.d.ts +2 -12
- package/dist/cli/request/settings.d.ts.map +1 -1
- package/dist/cli/request/settings.js +2 -25
- package/dist/cli/request/settings.js.map +1 -1
- package/dist/cli/request/validation.d.ts +12 -0
- package/dist/cli/request/validation.d.ts.map +1 -1
- package/dist/cli/request/validation.js +30 -10
- package/dist/cli/request/validation.js.map +1 -1
- package/dist/cli/request/values.d.ts +1 -0
- package/dist/cli/request/values.d.ts.map +1 -1
- package/dist/cli/request/values.js +1 -0
- package/dist/cli/request/values.js.map +1 -1
- package/dist/cli/run/index.d.ts.map +1 -1
- package/dist/cli/run/index.js +5 -41
- package/dist/cli/run/index.js.map +1 -1
- package/dist/cli/run/subscribe.d.ts +19 -0
- package/dist/cli/run/subscribe.d.ts.map +1 -0
- package/dist/cli/run/subscribe.js +47 -0
- package/dist/cli/run/subscribe.js.map +1 -0
- package/dist/cli/session/launch.d.ts +3 -0
- package/dist/cli/session/launch.d.ts.map +1 -1
- package/dist/cli/session/launch.js +11 -0
- package/dist/cli/session/launch.js.map +1 -1
- package/dist/cli/sessions/index.d.ts +30 -0
- package/dist/cli/sessions/index.d.ts.map +1 -0
- package/dist/cli/sessions/index.js +61 -0
- package/dist/cli/sessions/index.js.map +1 -0
- package/dist/cli/sessions/list.d.ts +28 -0
- package/dist/cli/sessions/list.d.ts.map +1 -0
- package/dist/cli/sessions/list.js +63 -0
- package/dist/cli/sessions/list.js.map +1 -0
- package/dist/cli/sessions/settings.d.ts +11 -0
- package/dist/cli/sessions/settings.d.ts.map +1 -0
- package/dist/cli/sessions/settings.js +26 -0
- package/dist/cli/sessions/settings.js.map +1 -0
- package/dist/cli/table.d.ts +7 -0
- package/dist/cli/table.d.ts.map +1 -0
- package/dist/cli/table.js +14 -0
- package/dist/cli/table.js.map +1 -0
- package/dist/cli/types.d.ts +5 -1
- package/dist/cli/types.d.ts.map +1 -1
- package/dist/cli/types.js.map +1 -1
- package/dist/codex/command.d.ts +18 -2
- package/dist/codex/command.d.ts.map +1 -1
- package/dist/codex/command.js +39 -24
- package/dist/codex/command.js.map +1 -1
- package/dist/codex/model-picker.d.ts.map +1 -1
- package/dist/codex/model-picker.js +3 -2
- package/dist/codex/model-picker.js.map +1 -1
- package/dist/codex/session/build.d.ts.map +1 -1
- package/dist/codex/session/build.js +5 -7
- package/dist/codex/session/build.js.map +1 -1
- package/dist/codex/session/index.d.ts.map +1 -1
- package/dist/codex/session/index.js +5 -2
- package/dist/codex/session/index.js.map +1 -1
- package/dist/codex/session/resume.d.ts +1 -1
- package/dist/codex/session/resume.d.ts.map +1 -1
- package/dist/codex/session/resume.js +5 -1
- package/dist/codex/session/resume.js.map +1 -1
- package/dist/codex/session/start-or-resume.js +1 -0
- package/dist/codex/session/start-or-resume.js.map +1 -1
- package/dist/codex/session/types.d.ts +3 -0
- package/dist/codex/session/types.d.ts.map +1 -1
- package/dist/codex/simple.d.ts.map +1 -1
- package/dist/codex/simple.js +4 -0
- package/dist/codex/simple.js.map +1 -1
- package/dist/core/errors.d.ts +1 -1
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js.map +1 -1
- package/dist/core/high-trust.d.ts +41 -0
- package/dist/core/high-trust.d.ts.map +1 -0
- package/dist/core/high-trust.js +50 -0
- package/dist/core/high-trust.js.map +1 -0
- package/dist/core/input/index.d.ts.map +1 -1
- package/dist/core/input/index.js +15 -3
- package/dist/core/input/index.js.map +1 -1
- package/dist/core/models/input.d.ts +3 -0
- package/dist/core/models/input.d.ts.map +1 -0
- package/dist/core/models/input.js +9 -0
- package/dist/core/models/input.js.map +1 -0
- package/dist/core/models/picker.d.ts +2 -1
- package/dist/core/models/picker.d.ts.map +1 -1
- package/dist/core/models/picker.js +6 -5
- package/dist/core/models/picker.js.map +1 -1
- package/dist/core/models/tui-screen.d.ts +1 -1
- package/dist/core/models/tui-screen.d.ts.map +1 -1
- package/dist/core/models/tui-screen.js +26 -3
- package/dist/core/models/tui-screen.js.map +1 -1
- package/dist/core/trust/allowlist.d.ts +56 -0
- package/dist/core/trust/allowlist.d.ts.map +1 -0
- package/dist/core/{trust-prompts.js → trust/allowlist.js} +21 -38
- package/dist/core/trust/allowlist.js.map +1 -0
- package/dist/core/trust/prompts.d.ts +4 -46
- package/dist/core/trust/prompts.d.ts.map +1 -1
- package/dist/core/trust/prompts.js +2 -73
- package/dist/core/trust/prompts.js.map +1 -1
- package/dist/core/trust/responder.d.ts +2 -0
- package/dist/core/trust/responder.d.ts.map +1 -1
- package/dist/core/trust/responder.js +4 -0
- package/dist/core/trust/responder.js.map +1 -1
- package/dist/core/types.d.ts +3 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/runtime/launch-arguments.d.ts +12 -0
- package/dist/runtime/launch-arguments.d.ts.map +1 -0
- package/dist/runtime/launch-arguments.js +15 -0
- package/dist/runtime/launch-arguments.js.map +1 -0
- package/dist/runtime/session/base.d.ts.map +1 -1
- package/dist/runtime/session/base.js +4 -1
- package/dist/runtime/session/base.js.map +1 -1
- package/dist/runtime/session/commands.d.ts +2 -1
- package/dist/runtime/session/commands.d.ts.map +1 -1
- package/dist/runtime/session/commands.js +10 -4
- package/dist/runtime/session/commands.js.map +1 -1
- package/dist/runtime/session/lifecycle.d.ts +3 -4
- package/dist/runtime/session/lifecycle.d.ts.map +1 -1
- package/dist/runtime/session/lifecycle.js +6 -5
- package/dist/runtime/session/lifecycle.js.map +1 -1
- package/dist/state/directories.d.ts +4 -0
- package/dist/state/directories.d.ts.map +1 -0
- package/dist/state/directories.js +41 -0
- package/dist/state/directories.js.map +1 -0
- package/dist/state/files.d.ts.map +1 -1
- package/dist/state/files.js +25 -11
- package/dist/state/files.js.map +1 -1
- package/dist/state/private-session.d.ts.map +1 -1
- package/dist/state/private-session.js +2 -0
- package/dist/state/private-session.js.map +1 -1
- package/dist/state/store.d.ts.map +1 -1
- package/dist/state/store.js +7 -1
- package/dist/state/store.js.map +1 -1
- package/docs/cli-behavior.md +89 -1
- package/docs/cli-output.md +60 -0
- package/docs/cli.md +10 -2
- package/docs/codex/cli.md +57 -0
- package/docs/codex/config.md +47 -0
- package/docs/codex/hooks.md +70 -0
- package/examples/README.md +56 -0
- package/examples/full.ts +113 -0
- package/examples/minimal.ts +15 -0
- package/examples/stream.ts +39 -0
- package/examples/support.ts +71 -0
- package/package.json +17 -10
- package/prd/01-overview.md +21 -0
- package/prd/02-goals.md +47 -0
- package/prd/03-terminology.md +32 -0
- package/prd/04-architecture.md +121 -0
- package/prd/05-api/5.1-starting-claude.md +108 -0
- package/prd/05-api/5.2-resuming-claude.md +86 -0
- package/prd/05-api/5.3-claude-session-api.md +658 -0
- package/prd/05-api/5.4-events.md +145 -0
- package/prd/05-api/5.5-starting-codex.md +106 -0
- package/prd/05-api/5.6-resuming-codex.md +48 -0
- package/prd/05-api/5.7-codex-session-api.md +425 -0
- package/prd/05-api/5.8-session-api.md +122 -0
- package/prd/05-api/5.9-loops.md +170 -0
- package/prd/05-api/README.md +19 -0
- package/prd/06-claude-hook-bridge.md +164 -0
- package/prd/07-claude-policy.md +15 -0
- package/prd/07a-codex-hook-bridge.md +76 -0
- package/prd/08-state.md +127 -0
- package/prd/09-lifecycle.md +222 -0
- package/prd/10-errors.md +55 -0
- package/prd/11-test-app.md +53 -0
- package/prd/12-e2e.md +23 -0
- package/prd/12a-cli.md +375 -0
- package/prd/13-latitude.md +12 -0
- package/prd/14-conformance.md +333 -0
- package/prd/15-open-notes.md +8 -0
- package/prd/README.md +45 -0
- package/dist/claude/hook-dispatch.d.ts +0 -9
- package/dist/claude/hook-dispatch.d.ts.map +0 -1
- package/dist/claude/hook-dispatch.js +0 -12
- package/dist/claude/hook-dispatch.js.map +0 -1
- package/dist/claude/hook-events-extra.d.ts +0 -81
- package/dist/claude/hook-events-extra.d.ts.map +0 -1
- package/dist/claude/hook-events-extra.js +0 -6
- package/dist/claude/hook-events-extra.js.map +0 -1
- package/dist/claude/hook-events.d.ts +0 -101
- package/dist/claude/hook-events.d.ts.map +0 -1
- package/dist/claude/hook-events.js +0 -6
- package/dist/claude/hook-events.js.map +0 -1
- package/dist/claude/hook-names.d.ts +0 -24
- package/dist/claude/hook-names.d.ts.map +0 -1
- package/dist/claude/hook-names.js +0 -45
- package/dist/claude/hook-names.js.map +0 -1
- package/dist/claude/hooks.d.ts +0 -78
- package/dist/claude/hooks.d.ts.map +0 -1
- package/dist/claude/hooks.js +0 -6
- package/dist/claude/hooks.js.map +0 -1
- package/dist/claude/session-bridge.d.ts +0 -11
- package/dist/claude/session-bridge.d.ts.map +0 -1
- package/dist/claude/session-bridge.js +0 -18
- package/dist/claude/session-bridge.js.map +0 -1
- package/dist/claude/session-build.d.ts +0 -15
- package/dist/claude/session-build.d.ts.map +0 -1
- package/dist/claude/session-build.js +0 -147
- package/dist/claude/session-build.js.map +0 -1
- package/dist/claude/session-hook-handler.d.ts +0 -34
- package/dist/claude/session-hook-handler.d.ts.map +0 -1
- package/dist/claude/session-hook-handler.js +0 -42
- package/dist/claude/session-hook-handler.js.map +0 -1
- package/dist/claude/session-instance.d.ts +0 -42
- package/dist/claude/session-instance.d.ts.map +0 -1
- package/dist/claude/session-instance.js +0 -146
- package/dist/claude/session-instance.js.map +0 -1
- package/dist/claude/session-interface.d.ts +0 -49
- package/dist/claude/session-interface.d.ts.map +0 -1
- package/dist/claude/session-interface.js +0 -10
- package/dist/claude/session-interface.js.map +0 -1
- package/dist/claude/session-resume.d.ts +0 -8
- package/dist/claude/session-resume.d.ts.map +0 -1
- package/dist/claude/session-resume.js +0 -47
- package/dist/claude/session-resume.js.map +0 -1
- package/dist/claude/session-runtime.d.ts +0 -43
- package/dist/claude/session-runtime.d.ts.map +0 -1
- package/dist/claude/session-runtime.js +0 -105
- package/dist/claude/session-runtime.js.map +0 -1
- package/dist/claude/session-transcript.d.ts +0 -62
- package/dist/claude/session-transcript.d.ts.map +0 -1
- package/dist/claude/session-transcript.js +0 -88
- package/dist/claude/session-transcript.js.map +0 -1
- package/dist/claude/session.d.ts +0 -18
- package/dist/claude/session.d.ts.map +0 -1
- package/dist/claude/session.js +0 -58
- package/dist/claude/session.js.map +0 -1
- package/dist/claude/start-or-resume.d.ts +0 -12
- package/dist/claude/start-or-resume.d.ts.map +0 -1
- package/dist/claude/start-or-resume.js +0 -32
- package/dist/claude/start-or-resume.js.map +0 -1
- package/dist/claude/tool-hook-events.d.ts +0 -10
- package/dist/claude/tool-hook-events.d.ts.map +0 -1
- package/dist/claude/tool-hook-events.js +0 -18
- package/dist/claude/tool-hook-events.js.map +0 -1
- package/dist/claude/tool-types.d.ts +0 -158
- package/dist/claude/tool-types.d.ts.map +0 -1
- package/dist/claude/tool-types.js +0 -6
- package/dist/claude/tool-types.js.map +0 -1
- package/dist/claude/validate-input.d.ts +0 -8
- package/dist/claude/validate-input.d.ts.map +0 -1
- package/dist/claude/validate-input.js +0 -137
- package/dist/claude/validate-input.js.map +0 -1
- package/dist/claude/validate-permission-update.d.ts +0 -10
- package/dist/claude/validate-permission-update.d.ts.map +0 -1
- package/dist/claude/validate-permission-update.js +0 -72
- package/dist/claude/validate-permission-update.js.map +0 -1
- package/dist/claude/validate-result.d.ts +0 -7
- package/dist/claude/validate-result.d.ts.map +0 -1
- package/dist/claude/validate-result.js +0 -118
- package/dist/claude/validate-result.js.map +0 -1
- package/dist/claude/validate-shapes.d.ts +0 -22
- package/dist/claude/validate-shapes.d.ts.map +0 -1
- package/dist/claude/validate-shapes.js +0 -15
- package/dist/claude/validate-shapes.js.map +0 -1
- package/dist/claude/validate-tool-update.d.ts +0 -15
- package/dist/claude/validate-tool-update.d.ts.map +0 -1
- package/dist/claude/validate-tool-update.js +0 -122
- package/dist/claude/validate-tool-update.js.map +0 -1
- package/dist/cli/agent-detect.d.ts +0 -44
- package/dist/cli/agent-detect.d.ts.map +0 -1
- package/dist/cli/agent-detect.js +0 -66
- package/dist/cli/agent-detect.js.map +0 -1
- package/dist/cli/arg-errors.d.ts +0 -6
- package/dist/cli/arg-errors.d.ts.map +0 -1
- package/dist/cli/arg-errors.js +0 -44
- package/dist/cli/arg-errors.js.map +0 -1
- package/dist/cli/arg-options.d.ts +0 -26
- package/dist/cli/arg-options.d.ts.map +0 -1
- package/dist/cli/arg-options.js +0 -50
- package/dist/cli/arg-options.js.map +0 -1
- package/dist/cli/args.d.ts +0 -7
- package/dist/cli/args.d.ts.map +0 -1
- package/dist/cli/args.js +0 -70
- package/dist/cli/args.js.map +0 -1
- package/dist/cli/lifecycle-outcome.d.ts +0 -13
- package/dist/cli/lifecycle-outcome.d.ts.map +0 -1
- package/dist/cli/lifecycle-outcome.js +0 -20
- package/dist/cli/lifecycle-outcome.js.map +0 -1
- package/dist/cli/lifecycle.d.ts +0 -61
- package/dist/cli/lifecycle.d.ts.map +0 -1
- package/dist/cli/lifecycle.js +0 -152
- package/dist/cli/lifecycle.js.map +0 -1
- package/dist/cli/request-finalize.d.ts +0 -10
- package/dist/cli/request-finalize.d.ts.map +0 -1
- package/dist/cli/request-finalize.js +0 -135
- package/dist/cli/request-finalize.js.map +0 -1
- package/dist/cli/request-layers.d.ts +0 -30
- package/dist/cli/request-layers.d.ts.map +0 -1
- package/dist/cli/request-layers.js +0 -44
- package/dist/cli/request-layers.js.map +0 -1
- package/dist/cli/request-settings.d.ts +0 -34
- package/dist/cli/request-settings.d.ts.map +0 -1
- package/dist/cli/request-settings.js +0 -66
- package/dist/cli/request-settings.js.map +0 -1
- package/dist/cli/request-sources.d.ts +0 -13
- package/dist/cli/request-sources.d.ts.map +0 -1
- package/dist/cli/request-sources.js +0 -23
- package/dist/cli/request-sources.js.map +0 -1
- package/dist/cli/request-validation.d.ts +0 -18
- package/dist/cli/request-validation.d.ts.map +0 -1
- package/dist/cli/request-validation.js +0 -84
- package/dist/cli/request-validation.js.map +0 -1
- package/dist/cli/request-values.d.ts +0 -33
- package/dist/cli/request-values.d.ts.map +0 -1
- package/dist/cli/request-values.js +0 -73
- package/dist/cli/request-values.js.map +0 -1
- package/dist/cli/request.d.ts +0 -12
- package/dist/cli/request.d.ts.map +0 -1
- package/dist/cli/request.js +0 -103
- package/dist/cli/request.js.map +0 -1
- package/dist/cli/resolution-types.d.ts +0 -35
- package/dist/cli/resolution-types.d.ts.map +0 -1
- package/dist/cli/resolution-types.js +0 -6
- package/dist/cli/resolution-types.js.map +0 -1
- package/dist/cli/run-output-lines.d.ts +0 -14
- package/dist/cli/run-output-lines.d.ts.map +0 -1
- package/dist/cli/run-output-lines.js +0 -42
- package/dist/cli/run-output-lines.js.map +0 -1
- package/dist/cli/run-output.d.ts +0 -48
- package/dist/cli/run-output.d.ts.map +0 -1
- package/dist/cli/run-output.js +0 -150
- package/dist/cli/run-output.js.map +0 -1
- package/dist/cli/run.d.ts +0 -20
- package/dist/cli/run.d.ts.map +0 -1
- package/dist/cli/run.js +0 -126
- package/dist/cli/run.js.map +0 -1
- package/dist/cli/session-launch.d.ts +0 -23
- package/dist/cli/session-launch.d.ts.map +0 -1
- package/dist/cli/session-launch.js +0 -57
- package/dist/cli/session-launch.js.map +0 -1
- package/dist/cli/session.d.ts +0 -68
- package/dist/cli/session.d.ts.map +0 -1
- package/dist/cli/session.js +0 -124
- package/dist/cli/session.js.map +0 -1
- package/dist/codex/attach-images.d.ts +0 -20
- package/dist/codex/attach-images.d.ts.map +0 -1
- package/dist/codex/attach-images.js +0 -66
- package/dist/codex/attach-images.js.map +0 -1
- package/dist/codex/clipboard-lock.d.ts +0 -15
- package/dist/codex/clipboard-lock.d.ts.map +0 -1
- package/dist/codex/clipboard-lock.js +0 -16
- package/dist/codex/clipboard-lock.js.map +0 -1
- package/dist/codex/clipboard.d.ts +0 -32
- package/dist/codex/clipboard.d.ts.map +0 -1
- package/dist/codex/clipboard.js +0 -92
- package/dist/codex/clipboard.js.map +0 -1
- package/dist/codex/config-lock.d.ts +0 -21
- package/dist/codex/config-lock.d.ts.map +0 -1
- package/dist/codex/config-lock.js +0 -22
- package/dist/codex/config-lock.js.map +0 -1
- package/dist/codex/config-restore.d.ts +0 -33
- package/dist/codex/config-restore.d.ts.map +0 -1
- package/dist/codex/config-restore.js +0 -90
- package/dist/codex/config-restore.js.map +0 -1
- package/dist/codex/config-transaction.d.ts +0 -26
- package/dist/codex/config-transaction.d.ts.map +0 -1
- package/dist/codex/config-transaction.js +0 -47
- package/dist/codex/config-transaction.js.map +0 -1
- package/dist/codex/hook-dispatch.d.ts +0 -9
- package/dist/codex/hook-dispatch.d.ts.map +0 -1
- package/dist/codex/hook-dispatch.js +0 -14
- package/dist/codex/hook-dispatch.js.map +0 -1
- package/dist/codex/hook-names.d.ts +0 -19
- package/dist/codex/hook-names.d.ts.map +0 -1
- package/dist/codex/hook-names.js +0 -17
- package/dist/codex/hook-names.js.map +0 -1
- package/dist/codex/hooks.d.ts +0 -99
- package/dist/codex/hooks.d.ts.map +0 -1
- package/dist/codex/hooks.js +0 -6
- package/dist/codex/hooks.js.map +0 -1
- package/dist/codex/initial-ready.d.ts +0 -19
- package/dist/codex/initial-ready.d.ts.map +0 -1
- package/dist/codex/initial-ready.js +0 -19
- package/dist/codex/initial-ready.js.map +0 -1
- package/dist/codex/serialize.d.ts +0 -8
- package/dist/codex/serialize.d.ts.map +0 -1
- package/dist/codex/serialize.js +0 -48
- package/dist/codex/serialize.js.map +0 -1
- package/dist/codex/session-bridge.d.ts +0 -14
- package/dist/codex/session-bridge.d.ts.map +0 -1
- package/dist/codex/session-bridge.js +0 -20
- package/dist/codex/session-bridge.js.map +0 -1
- package/dist/codex/session-build.d.ts +0 -15
- package/dist/codex/session-build.d.ts.map +0 -1
- package/dist/codex/session-build.js +0 -144
- package/dist/codex/session-build.js.map +0 -1
- package/dist/codex/session-cleanup.d.ts +0 -12
- package/dist/codex/session-cleanup.d.ts.map +0 -1
- package/dist/codex/session-cleanup.js +0 -15
- package/dist/codex/session-cleanup.js.map +0 -1
- package/dist/codex/session-hooks.d.ts +0 -13
- package/dist/codex/session-hooks.d.ts.map +0 -1
- package/dist/codex/session-hooks.js +0 -54
- package/dist/codex/session-hooks.js.map +0 -1
- package/dist/codex/session-instance.d.ts +0 -50
- package/dist/codex/session-instance.d.ts.map +0 -1
- package/dist/codex/session-instance.js +0 -117
- package/dist/codex/session-instance.js.map +0 -1
- package/dist/codex/session-resume.d.ts +0 -7
- package/dist/codex/session-resume.d.ts.map +0 -1
- package/dist/codex/session-resume.js +0 -44
- package/dist/codex/session-resume.js.map +0 -1
- package/dist/codex/session-runtime.d.ts +0 -7
- package/dist/codex/session-runtime.d.ts.map +0 -1
- package/dist/codex/session-runtime.js +0 -10
- package/dist/codex/session-runtime.js.map +0 -1
- package/dist/codex/session-transcript.d.ts +0 -30
- package/dist/codex/session-transcript.d.ts.map +0 -1
- package/dist/codex/session-transcript.js +0 -53
- package/dist/codex/session-transcript.js.map +0 -1
- package/dist/codex/session-types.d.ts +0 -87
- package/dist/codex/session-types.d.ts.map +0 -1
- package/dist/codex/session-types.js +0 -6
- package/dist/codex/session-types.js.map +0 -1
- package/dist/codex/session-warnings.d.ts +0 -27
- package/dist/codex/session-warnings.d.ts.map +0 -1
- package/dist/codex/session-warnings.js +0 -54
- package/dist/codex/session-warnings.js.map +0 -1
- package/dist/codex/session.d.ts +0 -16
- package/dist/codex/session.d.ts.map +0 -1
- package/dist/codex/session.js +0 -61
- package/dist/codex/session.js.map +0 -1
- package/dist/codex/start-or-resume.d.ts +0 -12
- package/dist/codex/start-or-resume.d.ts.map +0 -1
- package/dist/codex/start-or-resume.js +0 -31
- package/dist/codex/start-or-resume.js.map +0 -1
- package/dist/codex/transcript/cursor-io.d.ts +0 -7
- package/dist/codex/transcript/cursor-io.d.ts.map +0 -1
- package/dist/codex/transcript/cursor-io.js +0 -7
- package/dist/codex/transcript/cursor-io.js.map +0 -1
- package/dist/codex/transcript/cursor.d.ts +0 -8
- package/dist/codex/transcript/cursor.d.ts.map +0 -1
- package/dist/codex/transcript/cursor.js +0 -8
- package/dist/codex/transcript/cursor.js.map +0 -1
- package/dist/codex/transcript/drops.d.ts +0 -9
- package/dist/codex/transcript/drops.d.ts.map +0 -1
- package/dist/codex/transcript/drops.js +0 -9
- package/dist/codex/transcript/drops.js.map +0 -1
- package/dist/codex/transcript.d.ts +0 -12
- package/dist/codex/transcript.d.ts.map +0 -1
- package/dist/codex/transcript.js +0 -10
- package/dist/codex/transcript.js.map +0 -1
- package/dist/codex/validate-result.d.ts +0 -7
- package/dist/codex/validate-result.d.ts.map +0 -1
- package/dist/codex/validate-result.js +0 -84
- package/dist/codex/validate-result.js.map +0 -1
- package/dist/codex/validate.d.ts +0 -11
- package/dist/codex/validate.d.ts.map +0 -1
- package/dist/codex/validate.js +0 -88
- package/dist/codex/validate.js.map +0 -1
- package/dist/core/activity-lifecycle.d.ts +0 -21
- package/dist/core/activity-lifecycle.d.ts.map +0 -1
- package/dist/core/activity-lifecycle.js +0 -45
- package/dist/core/activity-lifecycle.js.map +0 -1
- package/dist/core/activity-meta.d.ts +0 -13
- package/dist/core/activity-meta.d.ts.map +0 -1
- package/dist/core/activity-meta.js +0 -67
- package/dist/core/activity-meta.js.map +0 -1
- package/dist/core/activity-transcript.d.ts +0 -19
- package/dist/core/activity-transcript.d.ts.map +0 -1
- package/dist/core/activity-transcript.js +0 -60
- package/dist/core/activity-transcript.js.map +0 -1
- package/dist/core/activity.d.ts +0 -51
- package/dist/core/activity.d.ts.map +0 -1
- package/dist/core/activity.js +0 -81
- package/dist/core/activity.js.map +0 -1
- package/dist/core/control-queue-state.d.ts +0 -29
- package/dist/core/control-queue-state.d.ts.map +0 -1
- package/dist/core/control-queue-state.js +0 -95
- package/dist/core/control-queue-state.js.map +0 -1
- package/dist/core/control-queue-traits.d.ts +0 -54
- package/dist/core/control-queue-traits.d.ts.map +0 -1
- package/dist/core/control-queue-traits.js +0 -118
- package/dist/core/control-queue-traits.js.map +0 -1
- package/dist/core/control-queue-types.d.ts +0 -45
- package/dist/core/control-queue-types.d.ts.map +0 -1
- package/dist/core/control-queue-types.js +0 -7
- package/dist/core/control-queue-types.js.map +0 -1
- package/dist/core/control-queue.d.ts +0 -21
- package/dist/core/control-queue.d.ts.map +0 -1
- package/dist/core/control-queue.js +0 -98
- package/dist/core/control-queue.js.map +0 -1
- package/dist/core/list-models.d.ts +0 -44
- package/dist/core/list-models.d.ts.map +0 -1
- package/dist/core/list-models.js +0 -73
- package/dist/core/list-models.js.map +0 -1
- package/dist/core/model-picker.d.ts +0 -22
- package/dist/core/model-picker.d.ts.map +0 -1
- package/dist/core/model-picker.js +0 -58
- package/dist/core/model-picker.js.map +0 -1
- package/dist/core/model-rows.d.ts +0 -21
- package/dist/core/model-rows.d.ts.map +0 -1
- package/dist/core/model-rows.js +0 -57
- package/dist/core/model-rows.js.map +0 -1
- package/dist/core/probe-state.d.ts +0 -21
- package/dist/core/probe-state.d.ts.map +0 -1
- package/dist/core/probe-state.js +0 -39
- package/dist/core/probe-state.js.map +0 -1
- package/dist/core/session-input-abort.d.ts +0 -10
- package/dist/core/session-input-abort.d.ts.map +0 -1
- package/dist/core/session-input-abort.js +0 -44
- package/dist/core/session-input-abort.js.map +0 -1
- package/dist/core/session-input.d.ts +0 -37
- package/dist/core/session-input.d.ts.map +0 -1
- package/dist/core/session-input.js +0 -154
- package/dist/core/session-input.js.map +0 -1
- package/dist/core/session-warnings.d.ts +0 -20
- package/dist/core/session-warnings.d.ts.map +0 -1
- package/dist/core/session-warnings.js +0 -32
- package/dist/core/session-warnings.js.map +0 -1
- package/dist/core/simple/loop-controls.d.ts +0 -7
- package/dist/core/simple/loop-controls.d.ts.map +0 -1
- package/dist/core/simple/loop-controls.js +0 -7
- package/dist/core/simple/loop-controls.js.map +0 -1
- package/dist/core/startup-automation.d.ts +0 -54
- package/dist/core/startup-automation.d.ts.map +0 -1
- package/dist/core/startup-automation.js +0 -40
- package/dist/core/startup-automation.js.map +0 -1
- package/dist/core/startup-frame.d.ts +0 -39
- package/dist/core/startup-frame.d.ts.map +0 -1
- package/dist/core/startup-frame.js +0 -60
- package/dist/core/startup-frame.js.map +0 -1
- package/dist/core/startup-write.d.ts +0 -47
- package/dist/core/startup-write.d.ts.map +0 -1
- package/dist/core/startup-write.js +0 -73
- package/dist/core/startup-write.js.map +0 -1
- package/dist/core/trust-blocking.d.ts +0 -22
- package/dist/core/trust-blocking.d.ts.map +0 -1
- package/dist/core/trust-blocking.js +0 -38
- package/dist/core/trust-blocking.js.map +0 -1
- package/dist/core/trust-prompts.d.ts +0 -135
- package/dist/core/trust-prompts.d.ts.map +0 -1
- package/dist/core/trust-prompts.js.map +0 -1
- package/dist/core/trust-responder.d.ts +0 -48
- package/dist/core/trust-responder.d.ts.map +0 -1
- package/dist/core/trust-responder.js +0 -119
- package/dist/core/trust-responder.js.map +0 -1
- package/dist/core/tui-screen.d.ts +0 -21
- package/dist/core/tui-screen.d.ts.map +0 -1
- package/dist/core/tui-screen.js +0 -56
- package/dist/core/tui-screen.js.map +0 -1
- package/dist/core/update-warning.d.ts +0 -25
- package/dist/core/update-warning.d.ts.map +0 -1
- package/dist/core/update-warning.js +0 -33
- package/dist/core/update-warning.js.map +0 -1
- package/dist/core/warning-lifecycle.d.ts +0 -23
- package/dist/core/warning-lifecycle.d.ts.map +0 -1
- package/dist/core/warning-lifecycle.js +0 -6
- package/dist/core/warning-lifecycle.js.map +0 -1
- package/dist/core/warning-reasons.d.ts +0 -62
- package/dist/core/warning-reasons.d.ts.map +0 -1
- package/dist/core/warning-reasons.js +0 -121
- package/dist/core/warning-reasons.js.map +0 -1
- package/dist/core/warnings.d.ts +0 -145
- package/dist/core/warnings.d.ts.map +0 -1
- package/dist/core/warnings.js +0 -12
- package/dist/core/warnings.js.map +0 -1
- package/dist/runtime/cleanup-latch.d.ts +0 -27
- package/dist/runtime/cleanup-latch.d.ts.map +0 -1
- package/dist/runtime/cleanup-latch.js +0 -43
- package/dist/runtime/cleanup-latch.js.map +0 -1
- package/dist/runtime/initial-ready-advance.d.ts +0 -22
- package/dist/runtime/initial-ready-advance.d.ts.map +0 -1
- package/dist/runtime/initial-ready-advance.js +0 -39
- package/dist/runtime/initial-ready-advance.js.map +0 -1
- package/dist/runtime/initial-ready-fallback.d.ts +0 -12
- package/dist/runtime/initial-ready-fallback.d.ts.map +0 -1
- package/dist/runtime/initial-ready-fallback.js +0 -20
- package/dist/runtime/initial-ready-fallback.js.map +0 -1
- package/dist/runtime/initial-ready.d.ts +0 -49
- package/dist/runtime/initial-ready.d.ts.map +0 -1
- package/dist/runtime/initial-ready.js +0 -81
- package/dist/runtime/initial-ready.js.map +0 -1
- package/dist/runtime/reap-tree.d.ts +0 -62
- package/dist/runtime/reap-tree.d.ts.map +0 -1
- package/dist/runtime/reap-tree.js +0 -108
- package/dist/runtime/reap-tree.js.map +0 -1
- package/dist/runtime/session-base-types.d.ts +0 -36
- package/dist/runtime/session-base-types.d.ts.map +0 -1
- package/dist/runtime/session-base-types.js +0 -14
- package/dist/runtime/session-base-types.js.map +0 -1
- package/dist/runtime/session-base.d.ts +0 -48
- package/dist/runtime/session-base.d.ts.map +0 -1
- package/dist/runtime/session-base.js +0 -76
- package/dist/runtime/session-base.js.map +0 -1
- package/dist/runtime/session-commands.d.ts +0 -43
- package/dist/runtime/session-commands.d.ts.map +0 -1
- package/dist/runtime/session-commands.js +0 -52
- package/dist/runtime/session-commands.js.map +0 -1
- package/dist/runtime/session-exit.d.ts +0 -16
- package/dist/runtime/session-exit.d.ts.map +0 -1
- package/dist/runtime/session-exit.js +0 -32
- package/dist/runtime/session-exit.js.map +0 -1
- package/dist/runtime/session-image-attach.d.ts +0 -45
- package/dist/runtime/session-image-attach.d.ts.map +0 -1
- package/dist/runtime/session-image-attach.js +0 -82
- package/dist/runtime/session-image-attach.js.map +0 -1
- package/dist/runtime/session-lifecycle.d.ts +0 -61
- package/dist/runtime/session-lifecycle.d.ts.map +0 -1
- package/dist/runtime/session-lifecycle.js +0 -164
- package/dist/runtime/session-lifecycle.js.map +0 -1
- package/dist/runtime/session-loops.d.ts +0 -32
- package/dist/runtime/session-loops.d.ts.map +0 -1
- package/dist/runtime/session-loops.js +0 -62
- package/dist/runtime/session-loops.js.map +0 -1
- package/dist/runtime/session-readiness.d.ts +0 -18
- package/dist/runtime/session-readiness.d.ts.map +0 -1
- package/dist/runtime/session-readiness.js +0 -22
- package/dist/runtime/session-readiness.js.map +0 -1
- package/dist/runtime/session-reap.d.ts +0 -28
- package/dist/runtime/session-reap.d.ts.map +0 -1
- package/dist/runtime/session-reap.js +0 -51
- package/dist/runtime/session-reap.js.map +0 -1
- package/dist/runtime/session-resize.d.ts +0 -20
- package/dist/runtime/session-resize.d.ts.map +0 -1
- package/dist/runtime/session-resize.js +0 -26
- package/dist/runtime/session-resize.js.map +0 -1
- package/dist/runtime/session-shutdown-binding.d.ts +0 -30
- package/dist/runtime/session-shutdown-binding.d.ts.map +0 -1
- package/dist/runtime/session-shutdown-binding.js +0 -37
- package/dist/runtime/session-shutdown-binding.js.map +0 -1
- package/dist/runtime/session-shutdown.d.ts +0 -60
- package/dist/runtime/session-shutdown.d.ts.map +0 -1
- package/dist/runtime/session-shutdown.js +0 -140
- package/dist/runtime/session-shutdown.js.map +0 -1
- package/dist/runtime/session-status-wiring.d.ts +0 -38
- package/dist/runtime/session-status-wiring.d.ts.map +0 -1
- package/dist/runtime/session-status-wiring.js +0 -41
- package/dist/runtime/session-status-wiring.js.map +0 -1
- package/dist/runtime/session-status.d.ts +0 -7
- package/dist/runtime/session-status.d.ts.map +0 -1
- package/dist/runtime/session-status.js +0 -22
- package/dist/runtime/session-status.js.map +0 -1
- package/dist/runtime/shutdown-coordinator.d.ts +0 -57
- package/dist/runtime/shutdown-coordinator.d.ts.map +0 -1
- package/dist/runtime/shutdown-coordinator.js +0 -77
- package/dist/runtime/shutdown-coordinator.js.map +0 -1
- package/dist/runtime/startup-buffer.d.ts +0 -33
- package/dist/runtime/startup-buffer.d.ts.map +0 -1
- package/dist/runtime/startup-buffer.js +0 -53
- package/dist/runtime/startup-buffer.js.map +0 -1
- package/dist/runtime/startup-cleanup.d.ts +0 -43
- package/dist/runtime/startup-cleanup.d.ts.map +0 -1
- package/dist/runtime/startup-cleanup.js +0 -89
- package/dist/runtime/startup-cleanup.js.map +0 -1
- package/dist/runtime/startup.d.ts +0 -17
- package/dist/runtime/startup.d.ts.map +0 -1
- package/dist/runtime/startup.js +0 -47
- package/dist/runtime/startup.js.map +0 -1
- package/dist/runtime/status-emit.d.ts +0 -14
- package/dist/runtime/status-emit.d.ts.map +0 -1
- package/dist/runtime/status-emit.js +0 -15
- package/dist/runtime/status-emit.js.map +0 -1
- package/dist/runtime/teardown.d.ts +0 -15
- package/dist/runtime/teardown.d.ts.map +0 -1
- package/dist/runtime/teardown.js +0 -40
- package/dist/runtime/teardown.js.map +0 -1
- package/dist/runtime/terminate.d.ts +0 -22
- package/dist/runtime/terminate.d.ts.map +0 -1
- package/dist/runtime/terminate.js +0 -129
- package/dist/runtime/terminate.js.map +0 -1
- package/dist/runtime/update-lock.d.ts +0 -19
- package/dist/runtime/update-lock.d.ts.map +0 -1
- package/dist/runtime/update-lock.js +0 -183
- package/dist/runtime/update-lock.js.map +0 -1
- package/dist/runtime/update-once.d.ts +0 -40
- package/dist/runtime/update-once.d.ts.map +0 -1
- package/dist/runtime/update-once.js +0 -88
- package/dist/runtime/update-once.js.map +0 -1
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Codex CLI Notes
|
|
2
|
+
|
|
3
|
+
Sources researched:
|
|
4
|
+
|
|
5
|
+
- https://developers.openai.com/codex/cli/features
|
|
6
|
+
- https://developers.openai.com/codex/cli/reference
|
|
7
|
+
- local `codex --help` and `codex --version` output
|
|
8
|
+
|
|
9
|
+
## Interactive Mode
|
|
10
|
+
|
|
11
|
+
`codex` launches an interactive full-screen terminal UI. That is the mode Elwood
|
|
12
|
+
must wrap. The parent app should control Codex through PTY input and observe it
|
|
13
|
+
through hooks, not through `codex exec`, the SDK, or app-server APIs.
|
|
14
|
+
|
|
15
|
+
Codex accepts an optional initial prompt, but Elwood starts without one by
|
|
16
|
+
default and sends prompts later through the terminal input path.
|
|
17
|
+
|
|
18
|
+
Useful CLI capabilities for Elwood:
|
|
19
|
+
|
|
20
|
+
- `codex` starts a new interactive session.
|
|
21
|
+
- `codex resume <SESSION_ID>` resumes a specific interactive session.
|
|
22
|
+
- `codex resume --last` resumes the most recent interactive session for the
|
|
23
|
+
current working directory.
|
|
24
|
+
- `--cd <DIR>` tells Codex which project root to use.
|
|
25
|
+
- `--config key=value` applies one-off TOML configuration overrides.
|
|
26
|
+
- `--model <MODEL>`, `--profile <NAME>`, `--sandbox <MODE>`, and
|
|
27
|
+
`--ask-for-approval <POLICY>` map naturally to adapter launch options.
|
|
28
|
+
- Some Codex versions expose `--dangerously-bypass-hook-trust`, which lets
|
|
29
|
+
generated Elwood hooks run for one invocation without requiring a persisted
|
|
30
|
+
trust prompt. Elwood must detect support before passing it because other Codex
|
|
31
|
+
versions reject unknown flags. Detection is cached for the lifetime of the
|
|
32
|
+
Elwood process.
|
|
33
|
+
- Codex can also render interactive trust and update prompts before the session
|
|
34
|
+
is usable. Elwood should select `Trust all and continue` for hook prompts, and
|
|
35
|
+
skip TUI update prompts because API-level `autoupdate` runs `codex update`
|
|
36
|
+
before launch when requested. Detection should use Elwood's headless xterm.js
|
|
37
|
+
screen snapshot, not raw ANSI/PTY byte parsing.
|
|
38
|
+
- Codex may print non-fatal environment warnings before the session is ready,
|
|
39
|
+
such as MCP servers that are not logged in. Elwood should preserve raw
|
|
40
|
+
terminal output and also project recognized warnings into typed `warning`
|
|
41
|
+
events with remediation commands.
|
|
42
|
+
|
|
43
|
+
## Resume Implications
|
|
44
|
+
|
|
45
|
+
Codex stores transcripts locally under Codex-owned state. Elwood should persist
|
|
46
|
+
only the Codex session id needed to call `codex resume <SESSION_ID>`. If that id
|
|
47
|
+
has not arrived through hooks yet, Elwood fails with `resume_unavailable`.
|
|
48
|
+
Elwood must not silently fall back to `codex resume --last` because that can
|
|
49
|
+
attach the caller's Elwood session id to the wrong Codex conversation. A future
|
|
50
|
+
API may add an explicit opt-in fallback, but it is not part of the current
|
|
51
|
+
contract.
|
|
52
|
+
|
|
53
|
+
## Shell Implications
|
|
54
|
+
|
|
55
|
+
The process should still be launched from the user's normal interactive login
|
|
56
|
+
shell so `codex` resolution, auth environment, and user shell startup behavior
|
|
57
|
+
match opening Terminal.app manually.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Codex Configuration Notes
|
|
2
|
+
|
|
3
|
+
Sources researched:
|
|
4
|
+
|
|
5
|
+
- https://developers.openai.com/codex/config-basic
|
|
6
|
+
- https://developers.openai.com/codex/config-advanced
|
|
7
|
+
- https://developers.openai.com/codex/config-reference
|
|
8
|
+
- https://developers.openai.com/codex/hooks
|
|
9
|
+
|
|
10
|
+
## Layers
|
|
11
|
+
|
|
12
|
+
Codex reads configuration from CLI flags and `--config` overrides first, then
|
|
13
|
+
profiles, trusted project `.codex/config.toml` files, user config, system config,
|
|
14
|
+
and built-in defaults.
|
|
15
|
+
|
|
16
|
+
Project-local `.codex` layers are only loaded when Codex trusts the project.
|
|
17
|
+
Because Elwood should be minimally invasive, it should not edit user or project
|
|
18
|
+
Codex config by default.
|
|
19
|
+
|
|
20
|
+
## Elwood Strategy
|
|
21
|
+
|
|
22
|
+
Elwood should generate session-scoped hook bridge files under `.elwood/` and
|
|
23
|
+
inject Codex hook configuration through `--config` one-off overrides. This keeps
|
|
24
|
+
existing `.codex/config.toml` and `~/.codex/config.toml` intact while still
|
|
25
|
+
letting Codex merge user defaults and policies normally.
|
|
26
|
+
Elwood applies `hookTrust="trust-all"` after caller overrides so parent apps
|
|
27
|
+
cannot accidentally create an unusable wrapper session.
|
|
28
|
+
|
|
29
|
+
The generated command should enable or configure:
|
|
30
|
+
|
|
31
|
+
- hooks for every supported Codex hook event;
|
|
32
|
+
- the bridge command and timeout for each event;
|
|
33
|
+
- `hookTrust="trust-all"`, because Elwood cannot observe or control Codex
|
|
34
|
+
without trusted hooks;
|
|
35
|
+
- optional launch policy such as model, profile, sandbox, approval policy, and
|
|
36
|
+
caller-supplied raw config overrides;
|
|
37
|
+
- `--dangerously-bypass-hook-trust` when the installed Codex CLI advertises it,
|
|
38
|
+
because the generated hooks are ephemeral Elwood-owned bridge commands. Elwood
|
|
39
|
+
must omit this flag for Codex versions that do not support it.
|
|
40
|
+
|
|
41
|
+
If Codex still renders a `Hooks need review` TUI prompt, Elwood should select
|
|
42
|
+
`Trust all and continue` through the headless xterm.js input path so the session
|
|
43
|
+
is usable headlessly.
|
|
44
|
+
|
|
45
|
+
If a managed Codex requirement disallows unmanaged hooks, Codex may ignore or
|
|
46
|
+
reject Elwood hook config. Elwood should surface startup/bridge failures through
|
|
47
|
+
typed errors where possible and hook runtime failures through `hookError`.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Codex Hooks Notes
|
|
2
|
+
|
|
3
|
+
Sources researched:
|
|
4
|
+
|
|
5
|
+
- https://developers.openai.com/codex/hooks
|
|
6
|
+
- https://github.com/openai/codex/tree/main/docs
|
|
7
|
+
- local `codex features list` output
|
|
8
|
+
|
|
9
|
+
## Events
|
|
10
|
+
|
|
11
|
+
The current documented Codex hook events relevant to Elwood are:
|
|
12
|
+
|
|
13
|
+
- `SessionStart`
|
|
14
|
+
- `SubagentStart`
|
|
15
|
+
- `PreToolUse`
|
|
16
|
+
- `PermissionRequest`
|
|
17
|
+
- `PostToolUse`
|
|
18
|
+
- `PreCompact`
|
|
19
|
+
- `PostCompact`
|
|
20
|
+
- `UserPromptSubmit`
|
|
21
|
+
- `SubagentStop`
|
|
22
|
+
- `Stop`
|
|
23
|
+
|
|
24
|
+
`SessionStart`, `PreToolUse`, `PermissionRequest`, `PostToolUse`,
|
|
25
|
+
`UserPromptSubmit`, `SubagentStart`, `SubagentStop`, and `Stop` include a Codex
|
|
26
|
+
permission mode field. Turn-scoped hooks include `turn_id`.
|
|
27
|
+
|
|
28
|
+
## Matchers
|
|
29
|
+
|
|
30
|
+
Hook matchers are regex strings. Tool hooks match `tool_name`; compaction hooks
|
|
31
|
+
match `manual` or `auto`; `SessionStart` matches the source such as startup or
|
|
32
|
+
resume; subagent hooks match agent type. `UserPromptSubmit` and `Stop` currently
|
|
33
|
+
ignore matchers.
|
|
34
|
+
|
|
35
|
+
For file edits, Codex reports the canonical tool name `apply_patch`, while
|
|
36
|
+
matchers may also use `Edit` or `Write`.
|
|
37
|
+
|
|
38
|
+
Tool hooks currently cover `Bash`, `apply_patch`, and MCP tool calls. They do
|
|
39
|
+
not cover every TUI-visible activity. In particular, Codex docs state that web
|
|
40
|
+
search and other non-shell/non-MCP tool calls do not trigger `PreToolUse` or
|
|
41
|
+
`PostToolUse` today. Reasoning/status lines shown in the TUI are also not hook
|
|
42
|
+
events.
|
|
43
|
+
|
|
44
|
+
Elwood therefore treats hooks as the control/approval path and uses live-only
|
|
45
|
+
transcript observation as a secondary rendering path for parent apps that need
|
|
46
|
+
to display reasoning phases, web search calls, assistant messages, and other
|
|
47
|
+
Codex-visible activity.
|
|
48
|
+
|
|
49
|
+
## Response Model
|
|
50
|
+
|
|
51
|
+
No output with exit code `0` means no decision and Codex continues.
|
|
52
|
+
|
|
53
|
+
Codex accepts event-specific JSON output. Important shapes for Elwood:
|
|
54
|
+
|
|
55
|
+
- `PreToolUse` can deny a supported tool call with `permissionDecision: "deny"`
|
|
56
|
+
and a reason, add additional context, or allow a rewritten tool input.
|
|
57
|
+
- `PermissionRequest` can decide `allow` or `deny` with `{ hookSpecificOutput:
|
|
58
|
+
{ hookEventName, decision: { behavior, message? } } }`. It must not return
|
|
59
|
+
updated input or permission edits.
|
|
60
|
+
- `Stop` and `SubagentStop` can return `decision: "block"` with a reason to ask
|
|
61
|
+
Codex to continue instead of marking the turn done.
|
|
62
|
+
- `PostToolUse`, `UserPromptSubmit`, `SubagentStart`, `PreCompact`, and
|
|
63
|
+
`PostCompact` are observe-only in Elwood until Codex documents a stable
|
|
64
|
+
response contract for them.
|
|
65
|
+
|
|
66
|
+
Elwood should fail open when parent handlers are missing, time out, throw, or
|
|
67
|
+
return an invalid response for the event.
|
|
68
|
+
|
|
69
|
+
Handlers should return `undefined` for no decision. Empty objects are invalid so
|
|
70
|
+
accidentally empty responses surface as `hookError` and fail open.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Elwood Examples
|
|
2
|
+
|
|
3
|
+
## Minimal: ask and answer (`minimal.ts`)
|
|
4
|
+
|
|
5
|
+
The smallest possible use of Elwood. Construct a session, `send` a message, get the
|
|
6
|
+
assistant's reply back as a string, ask a follow-up. The session starts lazily on the
|
|
7
|
+
first `send`, so there is no start ceremony and no manual "wait for ready".
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm run example:minimal
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
const session = new CodexSession({ autotrust: true });
|
|
15
|
+
const joke = await session.send("Tell me a joke that involves a dog.");
|
|
16
|
+
const rewrite = await session.send("Now rewrite it to be about a cat.");
|
|
17
|
+
await session.close();
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Streaming: watch the work (`stream.ts`)
|
|
21
|
+
|
|
22
|
+
When you want the intermediate steps, `stream` yields typed events (`thinking`,
|
|
23
|
+
`tool_call`, `tool_result`, `text`) as they arrive. `send` is just this generator
|
|
24
|
+
drained for the `text`, so the two share one turn boundary.
|
|
25
|
+
|
|
26
|
+
```sh
|
|
27
|
+
npm run example:stream
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
for await (const event of session.stream("List the files, then summarize the project.")) {
|
|
32
|
+
if (event.type === "text") process.stdout.write(event.text);
|
|
33
|
+
// event.type is also "thinking" | "tool_call" | "tool_result"
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Full: the raw control surface (`full.ts`)
|
|
38
|
+
|
|
39
|
+
`full.ts` drops below the ergonomic facade to the low-level API: `startClaude`/
|
|
40
|
+
`startCodex`, raw `activity`/`warning`/`terminal:exit` events, an explicit
|
|
41
|
+
`waitForSettled` helper (from `support.ts`) that watches `status` and
|
|
42
|
+
`terminal:exit`, and CLI flags for agent/cwd/prompt/timeout. Reach for this when you
|
|
43
|
+
need full control over the session lifecycle; most callers want `send`/`stream` above.
|
|
44
|
+
|
|
45
|
+
```sh
|
|
46
|
+
npm run example:full
|
|
47
|
+
npm run example:full -- --agent codex --cwd . --prompt "Summarize this repo in one paragraph."
|
|
48
|
+
npm run example:full -- --agent claude --cwd . --prompt "Summarize this repo in one paragraph."
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
All examples use `autotrust: true` so embedded sessions can move past known workspace
|
|
52
|
+
trust prompts. The package scripts run the TypeScript examples under a small Node
|
|
53
|
+
supervisor because `node-pty` owns real PTYs more reliably there and the supervisor can
|
|
54
|
+
kill the example process tree on Ctrl-C. The examples import from `../src/index.ts`
|
|
55
|
+
so they run from a checkout without a build; in your own project import the same
|
|
56
|
+
symbols from `@with-logic/elwood`.
|
package/examples/full.ts
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Full runnable Elwood example for starting one agent session, sending one
|
|
3
|
+
* message, logging rich events, and cleaning up the process.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { resolve } from "node:path";
|
|
7
|
+
import { startClaude, startCodex } from "../src/index.ts";
|
|
8
|
+
import {
|
|
9
|
+
type Agent,
|
|
10
|
+
cleanupSession,
|
|
11
|
+
type ExampleSession,
|
|
12
|
+
errorMessage,
|
|
13
|
+
isTerminalStatus,
|
|
14
|
+
textSuffix,
|
|
15
|
+
waitForSettled,
|
|
16
|
+
} from "./support.ts";
|
|
17
|
+
|
|
18
|
+
type Options = {
|
|
19
|
+
readonly agent: Agent;
|
|
20
|
+
readonly cwd: string;
|
|
21
|
+
readonly keep: boolean;
|
|
22
|
+
readonly prompt: string;
|
|
23
|
+
readonly timeoutMs: number;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const defaultPrompt = "Say hello from Elwood in one short sentence, then stop.";
|
|
27
|
+
const options = parseArgs(process.argv.slice(2));
|
|
28
|
+
let session: ExampleSession | undefined;
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
session = await startSession(options);
|
|
32
|
+
wireLogs(session);
|
|
33
|
+
process.stdout.write(`started ${options.agent} session ${session.elwoodSessionId}\n`);
|
|
34
|
+
await session.sendMessage(options.prompt);
|
|
35
|
+
if (!(await waitForSettled(session, options.timeoutMs))) {
|
|
36
|
+
throw new Error(`Timed out after ${options.timeoutMs}ms waiting for the agent to finish.`);
|
|
37
|
+
}
|
|
38
|
+
} catch (error) {
|
|
39
|
+
process.stderr.write(`${errorMessage(error)}\n`);
|
|
40
|
+
process.exitCode = 1;
|
|
41
|
+
} finally {
|
|
42
|
+
if (session && !options.keep && !isTerminalStatus(session.status)) await cleanupSession(session);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async function startSession(options: Options): Promise<ExampleSession> {
|
|
46
|
+
const common = { cwd: options.cwd, autotrust: true, initialSize: { cols: 120, rows: 40 } };
|
|
47
|
+
return options.agent === "claude" ? await startClaude(common) : await startCodex(common);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function wireLogs(session: ExampleSession): void {
|
|
51
|
+
session.on("activity", (event) => {
|
|
52
|
+
process.stdout.write(
|
|
53
|
+
`[activity] ${event.agent}:${event.kind}:${event.label}${textSuffix(event.text)}\n`,
|
|
54
|
+
);
|
|
55
|
+
});
|
|
56
|
+
session.on("warning", (event) => {
|
|
57
|
+
process.stdout.write(`[warning] ${event.agent}:${event.code} ${event.message}\n`);
|
|
58
|
+
});
|
|
59
|
+
session.on("hookError", (event) => {
|
|
60
|
+
process.stdout.write(`[hookError] ${event.hookEventName}:${event.category} ${event.message}\n`);
|
|
61
|
+
});
|
|
62
|
+
session.on("terminal:exit", (event) => {
|
|
63
|
+
process.stdout.write(`[terminal:exit] code=${event.exitCode}\n`);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function parseArgs(args: readonly string[]): Options {
|
|
68
|
+
let agent: Agent = "codex";
|
|
69
|
+
let cwd = process.cwd();
|
|
70
|
+
let keep = false;
|
|
71
|
+
let prompt = defaultPrompt;
|
|
72
|
+
let timeoutMs = 120_000;
|
|
73
|
+
let index = 0;
|
|
74
|
+
while (index < args.length) {
|
|
75
|
+
const arg = args[index];
|
|
76
|
+
if (arg === "--help") return printUsageAndExit();
|
|
77
|
+
if (arg === "--agent")
|
|
78
|
+
[agent, index] = [parseAgent(requireValue(args, index + 1, arg)), index + 2];
|
|
79
|
+
else if (arg === "--cwd")
|
|
80
|
+
[cwd, index] = [resolve(requireValue(args, index + 1, arg)), index + 2];
|
|
81
|
+
else if (arg === "--prompt") [prompt, index] = [requireValue(args, index + 1, arg), index + 2];
|
|
82
|
+
else if (arg === "--timeout-ms")
|
|
83
|
+
[timeoutMs, index] = [Number(requireValue(args, index + 1, arg)), index + 2];
|
|
84
|
+
else if (arg === "--keep") [keep, index] = [true, index + 1];
|
|
85
|
+
else throw new Error(`Unknown option: ${arg}`);
|
|
86
|
+
}
|
|
87
|
+
if (!prompt) throw new Error("--prompt must not be empty.");
|
|
88
|
+
if (!Number.isInteger(timeoutMs) || timeoutMs <= 0)
|
|
89
|
+
throw new Error("--timeout-ms must be positive.");
|
|
90
|
+
return { agent, cwd: resolve(cwd), keep, prompt, timeoutMs };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function requireValue(args: readonly string[], index: number, flag: string): string {
|
|
94
|
+
const value = args[index];
|
|
95
|
+
if (!value) throw new Error(`Missing value for ${flag}.`);
|
|
96
|
+
return value;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function parseAgent(value: string): Agent {
|
|
100
|
+
if (value === "claude" || value === "codex") return value;
|
|
101
|
+
throw new Error("--agent must be claude or codex.");
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function printUsageAndExit(): never {
|
|
105
|
+
process.stdout.write(
|
|
106
|
+
[
|
|
107
|
+
"Usage: npm run example:full",
|
|
108
|
+
' npm run example:full -- --agent codex --cwd . --prompt "Summarize this repo."',
|
|
109
|
+
"",
|
|
110
|
+
].join("\n"),
|
|
111
|
+
);
|
|
112
|
+
process.exit(0);
|
|
113
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The smallest Elwood example: ask a question, get the answer, ask a follow-up.
|
|
3
|
+
* The ergonomic facade starts Codex lazily on the first `send` and gives back the
|
|
4
|
+
* assistant's text as a string (PRD §5.8).
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { CodexSession } from "../src/index.ts";
|
|
8
|
+
|
|
9
|
+
const session = new CodexSession({ autotrust: true });
|
|
10
|
+
try {
|
|
11
|
+
process.stdout.write(`${await session.send("Tell me a joke that involves a dog.")}\n`);
|
|
12
|
+
process.stdout.write(`${await session.send("Now rewrite it to be about a cat.")}\n`);
|
|
13
|
+
} finally {
|
|
14
|
+
await session.close();
|
|
15
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ergonomic streaming: watch a turn's typed events — thinking, tool calls/results, and
|
|
3
|
+
* assistant text — as they arrive, instead of waiting for the final string (PRD §5.8).
|
|
4
|
+
* `send` is just this generator drained for text; `stream` is the same turn, live.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { ClaudeSession } from "../src/index.ts";
|
|
8
|
+
|
|
9
|
+
/** Compile-time exhaustiveness guard: reaching this with a real value means a case is missing. */
|
|
10
|
+
function assertNever(value: never): never {
|
|
11
|
+
throw new Error(`unhandled turn event: ${JSON.stringify(value)}`);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const session = new ClaudeSession({ autotrust: true });
|
|
15
|
+
try {
|
|
16
|
+
for await (const event of session.stream("List the files here, then summarize the project.")) {
|
|
17
|
+
switch (event.type) {
|
|
18
|
+
case "thinking":
|
|
19
|
+
process.stderr.write(` (thinking) ${event.text}\n`);
|
|
20
|
+
break;
|
|
21
|
+
case "tool_call":
|
|
22
|
+
process.stdout.write(`→ ${event.name}${event.input ? ` ${event.input}` : ""}\n`);
|
|
23
|
+
break;
|
|
24
|
+
case "tool_result":
|
|
25
|
+
process.stdout.write(`← ${event.output ?? ""}\n`);
|
|
26
|
+
break;
|
|
27
|
+
case "text":
|
|
28
|
+
process.stdout.write(event.text);
|
|
29
|
+
break;
|
|
30
|
+
default:
|
|
31
|
+
// Exhaustiveness: adding a new TurnEvent variant makes this fail to compile, so the
|
|
32
|
+
// canonical example can never silently ignore a newly-surfaced event kind.
|
|
33
|
+
assertNever(event);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
process.stdout.write("\n");
|
|
37
|
+
} finally {
|
|
38
|
+
await session.close();
|
|
39
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared helpers for runnable Elwood examples.
|
|
3
|
+
* Implements PRD §11 example behavior.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type {
|
|
7
|
+
ElwoodActivityEvent,
|
|
8
|
+
ElwoodSessionStatus,
|
|
9
|
+
ElwoodWarningEvent,
|
|
10
|
+
HookErrorEvent,
|
|
11
|
+
Unsubscribe,
|
|
12
|
+
} from "../src/index.ts";
|
|
13
|
+
|
|
14
|
+
export type Agent = "claude" | "codex";
|
|
15
|
+
export type ExampleSession = {
|
|
16
|
+
readonly elwoodSessionId: string;
|
|
17
|
+
readonly status: ElwoodSessionStatus;
|
|
18
|
+
on(event: "activity", handler: (event: ElwoodActivityEvent) => void): Unsubscribe;
|
|
19
|
+
on(event: "warning", handler: (event: ElwoodWarningEvent) => void): Unsubscribe;
|
|
20
|
+
on(event: "hookError", handler: (event: HookErrorEvent) => void): Unsubscribe;
|
|
21
|
+
on(
|
|
22
|
+
event: "status",
|
|
23
|
+
handler: (event: { readonly status: ElwoodSessionStatus }) => void,
|
|
24
|
+
): Unsubscribe;
|
|
25
|
+
on(event: "terminal:exit", handler: (event: { readonly exitCode: number }) => void): Unsubscribe;
|
|
26
|
+
sendMessage(message: string): Promise<void>;
|
|
27
|
+
stop(): Promise<void>;
|
|
28
|
+
kill(): Promise<void>;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export function waitForSettled(session: ExampleSession, timeoutMs: number): Promise<boolean> {
|
|
32
|
+
if (session.status === "ready" || isTerminalStatus(session.status)) return Promise.resolve(true);
|
|
33
|
+
return new Promise((resolveWait) => {
|
|
34
|
+
const done = (result: boolean) => {
|
|
35
|
+
clearTimeout(timer);
|
|
36
|
+
for (const unsubscribe of unsubs) unsubscribe();
|
|
37
|
+
resolveWait(result);
|
|
38
|
+
};
|
|
39
|
+
const timer = setTimeout(() => done(false), timeoutMs);
|
|
40
|
+
const unsubs: Unsubscribe[] = [
|
|
41
|
+
session.on("status", (event) => {
|
|
42
|
+
if (event.status === "ready" || isTerminalStatus(event.status)) done(true);
|
|
43
|
+
}),
|
|
44
|
+
session.on("terminal:exit", () => done(true)),
|
|
45
|
+
];
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export async function cleanupSession(session: ExampleSession): Promise<void> {
|
|
50
|
+
try {
|
|
51
|
+
await session.stop();
|
|
52
|
+
} catch (error) {
|
|
53
|
+
process.stderr.write(`stop failed, killing session: ${errorMessage(error)}\n`);
|
|
54
|
+
await session.kill();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function isTerminalStatus(status: ElwoodSessionStatus): boolean {
|
|
59
|
+
return (
|
|
60
|
+
status === "stopped" || status === "exited" || status === "killed" || status === "torn_down"
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function textSuffix(text: string | undefined): string {
|
|
65
|
+
if (!text) return "";
|
|
66
|
+
return ` ${text.replace(/\s+/g, " ").slice(0, 120)}`;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function errorMessage(error: unknown): string {
|
|
70
|
+
return error instanceof Error ? error.message : String(error);
|
|
71
|
+
}
|
package/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@with-logic/elwood",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Control interactive agentic coding CLIs (Claude Code, Codex) through real terminal sessions: typed hooks, a unified activity stream, resumable sessions, and a headless CLI.",
|
|
5
5
|
"license": "MIT",
|
|
6
|
+
"author": "Logic App, Inc.",
|
|
6
7
|
"repository": {
|
|
7
8
|
"type": "git",
|
|
8
9
|
"url": "git+https://github.com/with-logic/elwood.git"
|
|
9
10
|
},
|
|
10
|
-
"homepage": "https://
|
|
11
|
+
"homepage": "https://elwood.bot",
|
|
11
12
|
"bugs": {
|
|
12
13
|
"url": "https://github.com/with-logic/elwood/issues"
|
|
13
14
|
},
|
|
@@ -25,7 +26,12 @@
|
|
|
25
26
|
"type": "module",
|
|
26
27
|
"files": [
|
|
27
28
|
"dist",
|
|
28
|
-
"docs
|
|
29
|
+
"docs/**/*.md",
|
|
30
|
+
"prd/**/*.md",
|
|
31
|
+
"examples/*.ts",
|
|
32
|
+
"examples/README.md",
|
|
33
|
+
"CONTRIBUTING.md",
|
|
34
|
+
"SECURITY.md",
|
|
29
35
|
"CHANGELOG.md",
|
|
30
36
|
"README.md"
|
|
31
37
|
],
|
|
@@ -45,11 +51,12 @@
|
|
|
45
51
|
"node": ">=24"
|
|
46
52
|
},
|
|
47
53
|
"publishConfig": {
|
|
48
|
-
"access": "public"
|
|
54
|
+
"access": "public",
|
|
55
|
+
"registry": "https://registry.npmjs.org"
|
|
49
56
|
},
|
|
50
57
|
"scripts": {
|
|
51
58
|
"build": "tsc -p tsconfig.build.json && node scripts/postbuild.mjs",
|
|
52
|
-
"
|
|
59
|
+
"prepublishOnly": "npm run build",
|
|
53
60
|
"test": "vitest run --coverage",
|
|
54
61
|
"typecheck": "tsc --noEmit",
|
|
55
62
|
"lint": "biome check .",
|
|
@@ -58,9 +65,9 @@
|
|
|
58
65
|
"check:lines": "node --no-warnings scripts/check-lines.ts",
|
|
59
66
|
"check": "npm run build && npm run typecheck && npm run lint && npm run check:lines && npm test",
|
|
60
67
|
"check:all": "npm run check && npm run test:e2e",
|
|
61
|
-
"test:e2e": "exec node --no-warnings --experimental-test-coverage --test-coverage-include='src/**/*.ts' --test-coverage-exclude='
|
|
62
|
-
"dev:app": "exec node --no-warnings
|
|
63
|
-
"dev:web": "exec node --no-warnings scripts/supervise.ts
|
|
68
|
+
"test:e2e": "exec node --no-warnings --experimental-test-coverage --test-coverage-include='src/**/*.ts' --test-coverage-exclude='tests/**' --test-timeout=240000 --test-concurrency=1 --test tests/e2e/*.e2e.ts",
|
|
69
|
+
"dev:app": "exec node --no-warnings dev/dev.ts",
|
|
70
|
+
"dev:web": "exec node --no-warnings scripts/supervise.ts dev/web/dev.ts",
|
|
64
71
|
"example:minimal": "exec node --no-warnings scripts/supervise.ts examples/minimal.ts",
|
|
65
72
|
"example:stream": "exec node --no-warnings scripts/supervise.ts examples/stream.ts",
|
|
66
73
|
"example:full": "exec node --no-warnings scripts/supervise.ts examples/full.ts"
|
|
@@ -69,11 +76,11 @@
|
|
|
69
76
|
"@biomejs/biome": "2.4.15",
|
|
70
77
|
"@types/node": "^25.9.1",
|
|
71
78
|
"@types/ws": "^8.18.1",
|
|
72
|
-
"@vitest/coverage-istanbul": "^4.1.
|
|
79
|
+
"@vitest/coverage-istanbul": "^4.1.11",
|
|
73
80
|
"@xterm/addon-fit": "^0.11.0",
|
|
74
81
|
"@xterm/xterm": "^6.0.0",
|
|
75
82
|
"typescript": "^6.0.3",
|
|
76
|
-
"vitest": "^4.1.
|
|
83
|
+
"vitest": "^4.1.11",
|
|
77
84
|
"ws": "^8.21.0"
|
|
78
85
|
},
|
|
79
86
|
"dependencies": {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
## 1. Overview
|
|
2
|
+
|
|
3
|
+
Elwood lets an application control an agentic coding CLI that is running in its
|
|
4
|
+
native interactive terminal mode, without forcing a human to operate the TUI.
|
|
5
|
+
|
|
6
|
+
The first supported tool is Claude Code. The second supported tool is OpenAI
|
|
7
|
+
Codex CLI. Elwood starts the selected agent inside a real pseudoterminal,
|
|
8
|
+
configured so the agent sees the same kind of interactive shell session it would
|
|
9
|
+
see if the user opened Terminal.app and ran the CLI manually. Elwood then
|
|
10
|
+
controls the session by writing terminal input, and observes the agent primarily
|
|
11
|
+
through tool-specific hooks routed over local IPC.
|
|
12
|
+
|
|
13
|
+
The core premise is deliberate: the agent should not know it is running in a
|
|
14
|
+
special wrapper. Elwood does not replace Claude Code or Codex with print mode,
|
|
15
|
+
non-interactive mode, SDKs, or custom protocols. It runs the real interactive
|
|
16
|
+
TUI and wraps it.
|
|
17
|
+
|
|
18
|
+
Parent applications can use Elwood headlessly, or attach a terminal renderer
|
|
19
|
+
such as xterm.js to show the live session. A likely parent app is a local
|
|
20
|
+
Tauri-style desktop app that manages many agent sessions, renders their status,
|
|
21
|
+
and lets a user inspect the actual terminal when needed.
|
package/prd/02-goals.md
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
## 2. Goals And Non-Goals
|
|
2
|
+
|
|
3
|
+
### 2.1 Goals
|
|
4
|
+
|
|
5
|
+
- Provide a TypeScript library for starting, controlling, stopping, killing,
|
|
6
|
+
resuming, and tearing down interactive Claude Code and Codex CLI sessions.
|
|
7
|
+
- Run each agent in a real PTY so its TUI behaves as it would in a normal
|
|
8
|
+
terminal.
|
|
9
|
+
- Start Claude from the user's normal macOS interactive login shell environment,
|
|
10
|
+
including startup files such as `~/.zshrc` when that is what Terminal.app
|
|
11
|
+
would load.
|
|
12
|
+
- Route every Claude Code and Codex hook event through Elwood via a generated
|
|
13
|
+
per-session hook bridge.
|
|
14
|
+
- Expose every hook event to the parent app with strong TypeScript types.
|
|
15
|
+
- Let parent hook handlers return event-specific, strongly typed responses that
|
|
16
|
+
map to Claude Code's hook output protocol.
|
|
17
|
+
- Provide a unified agent-control surface where callers can send messages and
|
|
18
|
+
observe a rich chronological activity stream without branching on the
|
|
19
|
+
underlying adapter for common chat-loop workflows.
|
|
20
|
+
- Fail open when no hook handler exists, a handler times out, or a handler
|
|
21
|
+
fails at runtime.
|
|
22
|
+
- Send prompts through terminal input exactly as a human would, including
|
|
23
|
+
multi-line prompts.
|
|
24
|
+
- Persist only session metadata needed for resume and cleanup, plus loop
|
|
25
|
+
definitions that a caller explicitly creates as durable automation state.
|
|
26
|
+
- Avoid persisting raw terminal contents, ordinary user prompts, hook payloads,
|
|
27
|
+
or conversation logs by default. A loop prompt is the narrow exception: its
|
|
28
|
+
exact text is persisted because explicit recurring automation cannot be
|
|
29
|
+
restored without it.
|
|
30
|
+
- Provide a small local test app for manual development and acceptance testing.
|
|
31
|
+
|
|
32
|
+
### 2.2 Non-Goals
|
|
33
|
+
|
|
34
|
+
- Windows or Linux support in the MVP.
|
|
35
|
+
- Additional non-Claude/non-Codex adapters in the MVP.
|
|
36
|
+
- Using Claude Code print mode (`claude -p`) as the primary control mechanism.
|
|
37
|
+
- Cloud execution, remote hosts, or multi-machine session sync.
|
|
38
|
+
- Full visual parsing of Claude's TUI as the source of truth.
|
|
39
|
+
- Installing or updating Claude Code or Codex, or performing the INITIAL
|
|
40
|
+
authentication for a fresh install. Elwood assumes `claude`/`codex` is
|
|
41
|
+
installed, on `PATH`, and initially authenticated. Elwood DOES detect a lapsed
|
|
42
|
+
Claude login and can drive the interactive `/login` re-authentication flow to
|
|
43
|
+
recover a session whose login expired mid-run (C-CLAUDE-17/18, C-API-43); it
|
|
44
|
+
never performs the human browser sign-in itself.
|
|
45
|
+
- A first-class multi-session manager. Parent apps own orchestration across
|
|
46
|
+
many sessions.
|
|
47
|
+
- Durable audit logging of terminal or hook activity.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
## 3. Terminology
|
|
2
|
+
|
|
3
|
+
**Elwood session.** One wrapped interactive agent CLI process. A successfully started
|
|
4
|
+
session owns exactly one main CLI process: a live `ClaudeSessionApi` owns one main
|
|
5
|
+
`claude` process, a live `CodexSessionApi` one main `codex` process. The ergonomic
|
|
6
|
+
`ClaudeSession`/`CodexSession` classes (§5.8) are lazy wrappers that own NO process
|
|
7
|
+
before start and at most one after — each wraps a single such live session.
|
|
8
|
+
|
|
9
|
+
**Elwood session ID.** Stable opaque identifier generated by Elwood and exposed
|
|
10
|
+
to callers as `elwoodSessionId`. Callers use this ID to resume or tear down a
|
|
11
|
+
session. Claude's own session ID is internal metadata.
|
|
12
|
+
|
|
13
|
+
**Agent adapter.** Tool-specific implementation layer. The MVP adapter is
|
|
14
|
+
`claude` and `codex`. Future adapters might support other TUI-based agentic
|
|
15
|
+
CLIs.
|
|
16
|
+
|
|
17
|
+
**PTY session.** The pseudoterminal process and byte streams that make the CLI
|
|
18
|
+
believe it is running in an interactive terminal.
|
|
19
|
+
|
|
20
|
+
**Headless terminal.** Elwood-owned xterm.js terminal instance that renders PTY
|
|
21
|
+
output into a screen model and emits terminal input back to the PTY. This model
|
|
22
|
+
is required even when no UI is shown.
|
|
23
|
+
|
|
24
|
+
**Terminal renderer.** Optional parent-app UI component, such as browser
|
|
25
|
+
xterm.js, that renders the same live PTY stream for users.
|
|
26
|
+
|
|
27
|
+
**Hook bridge.** Elwood-owned command installed into agent hook settings. The
|
|
28
|
+
agent invokes it for hook events; it forwards hook input to the owning Elwood
|
|
29
|
+
runtime over local IPC and returns the runtime's response to the agent.
|
|
30
|
+
|
|
31
|
+
**Parent app.** The application embedding Elwood, commonly a Tauri or Electron
|
|
32
|
+
desktop app.
|