Skip to content

feat(hooks): wire tool hooks into builtin pipeline, add HTTP hooks#1255

Merged
chaliy merged 4 commits intomainfrom
claude/wire-tool-hooks-MW1KT
Apr 13, 2026
Merged

feat(hooks): wire tool hooks into builtin pipeline, add HTTP hooks#1255
chaliy merged 4 commits intomainfrom
claude/wire-tool-hooks-MW1KT

Conversation

@chaliy
Copy link
Copy Markdown
Contributor

@chaliy chaliy commented Apr 13, 2026

Summary

Completes the two main functional gaps from #1235 that PR #1253 deferred as follow-up:

  • Wire before_tool/after_tool into execute_registered_builtin() — hooks can now modify args, cancel tool invocations, and observe results
  • Add before_http/after_http — new HttpRequestEvent/HttpResponseEvent event types, interceptor hooks on HttpClient fired around every HTTP request (after allowlist check), builder API via BashBuilder::before_http()/after_http()
  • Add "never close half-done issues" rule to process-issues and ship skills to prevent premature issue closure
  • Update specs/009-implementation-status.md with hooks/interceptors section

What changed

File Change
hooks.rs Add HttpRequestEvent/HttpResponseEvent types; remove #[allow(dead_code)]
interpreter/mod.rs Fire before_tool/after_tool in builtin execution; add fire_after_tool helper
lib.rs Builder fields/methods for HTTP hooks; hook transfer during build; 6 new tests
network/client.rs HTTP hook storage, setters, firing in request_with_headers and request_with_timeouts
Skills "never close half-done issues" rule in process-issues and ship
Spec 009 Hooks/interceptors status table

Security

  • before_http fires after the allowlist check — security boundary stays in bashkit
  • Hooks are registered by the trusted embedder via BashBuilder (same trust model as HttpHandler)
  • Cancellation messages don't leak internal state

What remains from #1235

Part of #1235 — the following items from the original issue are still open:

  • Runtime registration API (bash.hooks().on_exit(...))
  • Dedicated hooks spec in specs/
  • Rustdoc guide in crates/bashkit/docs/
  • examples/hooks.rs

Test plan

  • test_before_tool_hook_modifies_args — hook rewrites args, output reflects change
  • test_before_tool_hook_cancels — hook cancels echo, exit code 1
  • test_after_tool_hook_observes_result — hook captures tool name, stdout, exit code
  • test_before_tool_hook_does_not_fire_for_special_builtins — declare (special) skipped, echo (registered) fires
  • test_before_http_hook_cancels_request — hook blocks curl to blocked.example.com
  • test_after_http_hook_observes_response — hook wires correctly, builder accepts it
  • 2413 lib tests pass, 123 doctests pass
  • cargo fmt --check clean
  • cargo clippy --all-targets --all-features -- -D warnings clean

chaliy added 4 commits April 13, 2026 17:43
…efore_http/after_http

Completes the remaining items from #1235 that were deferred as follow-up:

- Wire `fire_before_tool()`/`fire_after_tool()` into
  `execute_registered_builtin()` — hooks can now modify args, cancel
  tool invocations, and observe results
- Define `HttpRequestEvent`/`HttpResponseEvent` event types
- Implement `before_http`/`after_http` interceptor hooks on `HttpClient`,
  fired around every HTTP request (after allowlist check)
- Add `BashBuilder::before_http()`/`after_http()` builder methods
- 6 new tests: modify args, cancel tool, observe result, special-builtin
  exclusion, cancel HTTP request, observe HTTP response
…ship skills

PR #1253 auto-closed #1235 via `Closes #1235` despite explicitly noting
that tool hooks and HTTP hooks were deferred as follow-up. This left
dead code and missing features hidden behind a closed issue.

Add a rule to both skills: only use closing keywords when every
task/checkbox in the issue is complete. Use `Part of #N` for partial work.
@chaliy chaliy merged commit 019a914 into main Apr 13, 2026
27 checks passed
@chaliy chaliy deleted the claude/wire-tool-hooks-MW1KT branch April 13, 2026 18:38
chaliy added a commit that referenced this pull request Apr 14, 2026
…ests

Add transparent per-host credential injection so sandboxed scripts can
make authenticated API calls without ever seeing the real secrets.

Two modes:
- Injection: headers added automatically based on URL pattern
- Placeholder: opaque env var replaced with real credential on the wire

Built on the before_http hooks system (#1255). Credential policy hook
runs first so subsequent hooks see injected headers. Injected headers
overwrite existing headers with the same name (prevents spoofing).

New files:
- specs/019-credential-injection.md (design spec)
- crates/bashkit/src/credential.rs (Credential, CredentialPolicy)
- crates/bashkit/docs/credential-injection.md (rustdoc guide)
- crates/bashkit/tests/credential_injection_tests.rs (13 integration tests)
chaliy added a commit that referenced this pull request Apr 14, 2026
…ests

Add transparent per-host credential injection so sandboxed scripts can
make authenticated API calls without ever seeing the real secrets.

Two modes:
- Injection: headers added automatically based on URL pattern
- Placeholder: opaque env var replaced with real credential on the wire

Built on the before_http hooks system (#1255). Credential policy hook
runs first so subsequent hooks see injected headers. Injected headers
overwrite existing headers with the same name (prevents spoofing).

New files:
- specs/019-credential-injection.md (design spec)
- crates/bashkit/src/credential.rs (Credential, CredentialPolicy)
- crates/bashkit/docs/credential-injection.md (rustdoc guide)
- crates/bashkit/tests/credential_injection_tests.rs (13 integration tests)
chaliy added a commit that referenced this pull request Apr 14, 2026
…ests

Add transparent per-host credential injection so sandboxed scripts can
make authenticated API calls without ever seeing the real secrets.

Two modes:
- Injection: headers added automatically based on URL pattern
- Placeholder: opaque env var replaced with real credential on the wire

Built on the before_http hooks system (#1255). Credential policy hook
runs first so subsequent hooks see injected headers. Injected headers
overwrite existing headers with the same name (prevents spoofing).

New files:
- specs/019-credential-injection.md (design spec)
- crates/bashkit/src/credential.rs (Credential, CredentialPolicy)
- crates/bashkit/docs/credential-injection.md (rustdoc guide)
- crates/bashkit/tests/credential_injection_tests.rs (13 integration tests)
chaliy added a commit that referenced this pull request Apr 14, 2026
…ests (#1282)

Add transparent per-host credential injection so sandboxed scripts can
make authenticated API calls without ever seeing the real secrets.

Two modes:
- Injection: headers added automatically based on URL pattern
- Placeholder: opaque env var replaced with real credential on the wire

Built on before_http hooks (#1255). Credential policy hook runs first,
injected headers overwrite existing ones (prevents spoofing).

Also fixes dead_code warning for sanitize_git_output by gating it
behind #[cfg(any(feature = "git", test))].
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant