Skip to content

feat(hooks): support updatedInput for transparent command rewriting#1935

Closed
zoorpha wants to merge 2 commits intoMoonshotAI:mainfrom
zoorpha:feat/hooks-support-updated-input
Closed

feat(hooks): support updatedInput for transparent command rewriting#1935
zoorpha wants to merge 2 commits intoMoonshotAI:mainfrom
zoorpha:feat/hooks-support-updated-input

Conversation

@zoorpha
Copy link
Copy Markdown

@zoorpha zoorpha commented Apr 18, 2026

Related Issue

N/A — This is a small feature addition (34 lines) that enables transparent command rewriting via PreToolUse hooks, aligning with the existing hooks Beta documentation.

Description

This PR adds support for hookSpecificOutput.updatedInput in the PreToolUse hook lifecycle, enabling hooks to transparently rewrite tool arguments without blocking and requiring a retry.

Motivation

The current Kimi CLI hook system supports two actions from a PreToolUse hook:

  • allow — execute the tool as-is
  • block — prevent execution and return an error to the LLM

This works well for guardrails (e.g. "don't rm -rf /"), but is insufficient for integrations like RTK that want to rewrite commands for token optimization (e.g. git statusrtk git status) without forcing the LLM to retry.

With this change, a hook can output:

{
  "hookSpecificOutput": {
    "updatedInput": {
      "command": "rtk git status"
    }
  }
}

And Kimi will execute the tool with the rewritten arguments, transparently to the LLM.

Changes

src/kimi_cli/hooks/runner.py

  • Added updated_input: dict[str, Any] | None = None to HookResult
  • Extended run_hook() to parse hookSpecificOutput.updatedInput from JSON stdout
  • Deny decisions still take precedence over updatedInput

src/kimi_cli/soul/toolset.py

  • After PreToolUse hooks fire, if any result contains updated_input, merge it into the tool arguments dict before tool.call(arguments)
  • Guarded by isinstance(arguments, dict) to ensure type safety

tests/hooks/test_runner.py

  • test_json_updated_input_parsing — verifies updatedInput is parsed into HookResult.updated_input
  • test_json_deny_takes_precedence_over_updated_input — verifies permissionDecision: deny still blocks even when updatedInput is present

Backward Compatibility

  • Fully backward compatible. Hooks that don't output updatedInput behave exactly as before.
  • The feature is opt-in on the hook side — no config changes required.

Use Case: RTK Integration

RTK (Rust Token Killer) is a CLI proxy that reduces LLM token consumption by 60–90% on common commands. With this PR + the RTK PR #1391, Kimi users can:

rtk init -g --kimi

And have all Shell tool calls transparently rewritten to their RTK equivalents.

Testing

uv run pytest tests/hooks/test_runner.py -v

All 8 tests pass, including the 2 new ones:

tests/hooks/test_runner.py::test_json_updated_input_parsing PASSED
tests/hooks/test_runner.py::test_json_deny_takes_precedence_over_updated_input PASSED

The full hooks test suite (36 tests) also passes:

uv run pytest tests/hooks/ -v

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked the related issue, if any. (N/A for this small feature)
  • I have added tests that prove my fix is effective or that my feature works.
  • I have run make gen-changelog to update the changelog. (Command timed out in this environment)
  • I have run make gen-docs to update the user documentation. (Command timed out in this environment)

Open in Devin Review

chatgpt-codex-connector[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

@zoorpha
Copy link
Copy Markdown
Author

zoorpha commented Apr 19, 2026

Thanks for the automated review. We've addressed the issues identified:

  • Added runtime validation for updatedInput to prevent crashes from malformed hook output
  • Added test coverage for invalid updatedInput edge cases (null, string, list)
  • Updated hooks documentation (EN + ZH) to explain the transparent rewrite capability
  • Committed the previously missing CHANGELOG entries

All tests and checks pass. Resolving this review.

@zoorpha
Copy link
Copy Markdown
Author

zoorpha commented Apr 20, 2026

we already created another PR for the rtk tool
rtk-ai/rtk#1391

@senolcolak
Copy link
Copy Markdown

great to have this feature

zoorpha added 2 commits April 21, 2026 17:27
Allow PreToolUse hooks to rewrite tool input via hookSpecificOutput.updatedInput.
This enables integrations like RTK that transparently rewrite commands
(e.g. 'git status' -> 'rtk git status') without blocking and retrying.

Changes:
- HookResult: add updated_input field
- run_hook: parse updatedInput from hookSpecificOutput JSON
- toolset: apply updated_input to tool arguments before execution
- tests: add coverage for updated_input parsing and deny precedence
- Add isinstance guard before accepting updatedInput to prevent TypeError

- Document updatedInput transparent rewrite in EN and ZH hooks guides

- Add test coverage for invalid updatedInput values (null, string, list)

- Include CHANGELOG entries for the feature
@senolcolak
Copy link
Copy Markdown

seems like we cant help kimi improvements

@zoorpha
Copy link
Copy Markdown
Author

zoorpha commented Apr 28, 2026

I'll close the ticket

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.

2 participants