The Transparent Rewrite: From Agent Request to RTK Command
RTK's transparent rewrite is the mechanism that makes output compression fit an existing AI coding workflow. This chapter asks how an ordinary request such as git status crosses from an agent into RTK, how different agents carry that request, and where permission policy enters the path. By the end, readers should be able to trace the rewrite causally and distinguish a command being transformed from a command being authorized.
Three ways to cross the boundary
An AI coding agent does not send commands to RTK in one universal format. Each host exposes its own interception point. Some provide a pre-execution hook that can replace the command before the host runs it. Some provide a plugin event in which an extension mutates the command in place. Others provide only a rules or instructions file, so the agent must choose to type rtk itself. RTK treats these as different integration tiers because they provide different guarantees about whether a command will actually be rewritten.
A transparent hook sits closest to execution. In a typical flow, the agent announces that it is about to run a shell command, and the hook receives a structured event containing the command text. The hook passes that text to RTK's rewrite logic and, when a supported form exists, returns the host's equivalent of an updated input. The agent then executes rtk git status instead of git status, without having to invent that prefix or remember which commands RTK understands.
Plugins use the same idea through a different interface. A plugin may receive a terminal-tool event and mutate its command field directly. The result is still transparent from the workflow's point of view: the user asked for the ordinary command, but the underlying process is launched through RTK. The adapter's job is to understand the plugin protocol and report the change in the form the host accepts. It should not contain a second copy of every command pattern or filtering rule.
Rules-only integrations are weaker in a precise way. They can tell an agent to prefer rtk cargo test or rtk git status, but they cannot force a command replacement before execution. Their success depends on the agent following the instruction, and a missed prefix appears as a coverage problem rather than as a broken filter. This distinction matters when reading an adoption percentage: an installed instruction file is not the same thing as an interception path that observes every shell request.
RTK keeps the policy in its Rust binary so these adapters do not drift apart. The central registry knows which command forms are recognized and which RTK route corresponds to them. The host-specific layer only handles translation: it reads the incoming event, delegates the decision, and constructs the response object or mutation expected by that host. This division has two consequences. New command support can be added to the central policy without rewriting every integration, and a change in one agent's JSON contract does not require duplicating the filtering design in all other agents.
The separation also keeps the underlying tool in charge of the operation. RTK does not implement Git's repository semantics, Cargo's compiler, or a test framework. It changes the invocation so that the tool's output can later be represented more compactly. When the rewrite succeeds, the command remains recognizable: git status becomes rtk git status, not an opaque request to an unrelated service. That makes it possible to disable the proxy, inspect the raw command, or understand a failure in terms of the original tool.
The sequence has an important asymmetry. A successful rewrite changes the command before execution, but a no-match or error does not become a reason to block the user's work. RTK's hook contract is deliberately non-blocking: if the binary is unavailable, the input cannot be parsed, or no safe equivalent exists, the original command remains available. The price is that a silent failure of the hook can also mean lost savings, which is why RTK exposes installation checks and adoption analytics rather than treating installation as proof of coverage.
A command's path from request to result
Consider the simple request git status. First, the agent's host invokes its hook or plugin with the command string. The adapter extracts that string without executing it. It then calls RTK's rewrite entry point, either as a subprocess named rtk rewrite or through the equivalent in-process path used by some native integrations. At this stage RTK is answering a narrow question: is there a supported, semantically safe RTK form for this command?
The registry classifies the command against its known patterns. It can recognize the Git command family and associate it with the rtk git route. The classification is not yet the same as permission. A command may be recognizable but still be subject to a host's deny or ask policy. Keeping those questions separate prevents an optimization feature from quietly becoming an authorization feature.
The host permission decision is evaluated with an order that protects the native policy: deny takes precedence over ask, explicit allow, and the default. A denied command is left for the host's own denial handling. An ask decision can allow the rewrite to be proposed while still requiring the host to prompt. An explicit allow can permit automatic approval where the host supports that behavior. When no rule matches, RTK treats the default as ask rather than as allow. That last detail prevents a machine with no explicit permission rules from turning every recognized command into an automatically approved command merely because RTK knows how to shorten its output.
The distinction becomes more important with a compound command. Suppose an agent sends two commands joined by &&. RTK may be able to rewrite both segments independently, but an allow verdict cannot be earned by matching only one of them. Every non-empty segment must satisfy the allow condition. Otherwise a permitted-looking first segment could carry an unexamined second segment across the same automatic-approval boundary. The rewrite and permission paths therefore share a segment-level view of the command without claiming that the shell expression is one indivisible tool invocation.
The result of this decision is communicated in the host's own language. The subprocess rewrite interface uses exit outcomes to distinguish the cases: a successful rewrite can be returned with an allow or ask status; a deny status tells the adapter to defer to native denial; and a no-equivalent status means the original command should run. The exact JSON fields vary across hosts, but the principle is stable: the adapter must not erase the difference between “RTK can rewrite this,” “the host may prompt,” and “the host should handle the original command itself.”
The exit status is a small control protocol, not a second interpretation of the underlying tool's result. In the rewrite subprocess, status 0 means that a rewritten command was produced and may be auto-allowed when the host's policy permits it. Status 3 means that a rewrite was produced but the host should still ask for approval. Status 2 means a deny rule matched, so the adapter must stay out of the way. Status 1 means there is no RTK equivalent to apply. This distinction lets a hook treat “nothing to rewrite” as a normal pass-through condition rather than as an execution failure. The hook's own error handling follows the same availability principle: malformed input or a missing RTK binary should leave the original command runnable.
Host response capabilities then shape what the user experiences. A host with an updated-command field can replace the input directly. A host without that field may return a denial with a suggestion, asking the agent to retry the explicit RTK form. A rules-only host cannot perform either operation before execution and must rely on its instructions. These paths all point at the same registry, but they do not offer the same visibility or certainty. The integration is therefore part of RTK's effective context boundary: it determines whether the compact representation is applied automatically, proposed for approval, or never reached.
If git status is accepted for rewriting, the hook returns the updated command. The agent's normal execution machinery then launches rtk git status. RTK parses its own command-line form, routes to the Git handler, and starts the underlying Git process with the relevant arguments. The later filter stage determines how the result is represented to the LLM, but the operation itself is still Git's operation on the repository. RTK's responsibility at this point is to preserve the chain between the user's request and the tool that produces the evidence.
This is why a hook adapter should not try to filter output on its own. It does not own the raw result, the command-specific parser, or the recovery policy. Those concerns belong to the RTK binary and its shared execution infrastructure. If each agent integration independently decided that a passing test line, a Git header, or a compiler warning was disposable, the same command could yield different evidence depending on which agent launched it. Centralizing the decision reduces that behavioral variance while allowing each host to keep its own response protocol.
The centralization is not absolute uniformity. Hosts differ in what their APIs can express. A host with an updatedInput field can replace the command directly. A host without that field may have to deny with a suggestion so the agent retries the command itself. A rules-only host has no pre-execution mutation path at all. Some hosts also have different permission concepts or cannot represent an ask outcome. RTK's integration layer therefore preserves the host's limitations instead of pretending that one response shape works everywhere.
The fallback behavior is part of the same design. A hook that exits with a blocking error can prevent the underlying development command from running, turning a context optimization into a workflow outage. RTK's documented contract instead requires error paths to degrade to the original command. A missing binary, malformed input, old installation, or rewrite failure should produce no effective command change, not a mysterious failure in the user's test or deployment step. The filter itself later follows a related principle: when its own transformation fails, raw output remains the fallback.
This fail-open behavior has a practical trade-off. It protects command availability but makes observability necessary. A user may see normal raw output and assume RTK is active when the hook is actually missing or an agent is using a rules-only path. Installation checks, the savings dashboard, and missed-savings analysis address that gap from different angles rather than treating installation as proof of coverage.
The command boundary also has explicit escape routes for the user. A command can be excluded from automatic rewriting through configuration. A single invocation can set RTK_DISABLED=1 to run without the RTK route. An unsupported command can be invoked through passthrough, where RTK does not invent a filter. These controls are not exceptions that undermine the architecture. They express its ownership model: RTK may improve the representation of a command, but the user and the host retain the right to decide whether the command should be changed at all.
The transparent rewrite is therefore more than a convenience wrapper. It is a controlled handoff among three authorities: the agent owns the request and its protocol, the host owns permission, and the underlying tool owns the operation. RTK sits between them to make a supported command's output easier for an LLM to read. That handoff is safe only when the registry can recognize the command without changing its meaning and the permission layer can still account for what will execute.
The simple git status path hides the harder cases. Shell operators, wrappers, environment prefixes, redirects, and pipelines can change what a command means or what consumes its output. RTK must decide when a segment is safe to rewrite and when the correct optimization is to leave it alone. That is where the transparent boundary stops being invisible and becomes deliberately conservative.