Bug
rtk rewrite treats a command that already starts with rtk as a valid rewrite target and returns it unchanged with exit 3 ("handled"). When the inner command is a shell builtin (cd, export, source, etc.) this silently breaks the builtin's effect, because the model's manually-prefixed rtk cd /path executes rtk as a subprocess — the directory change is lost when that subprocess exits.
Reproduction
$ rtk rewrite "rtk cd /tmp"
rtk cd /tmp # ← same as input, exit 3 ("handled")
$ rtk rewrite "cd /tmp"
# exit 1 (passthrough — correct)
$ rtk cd /tmp; pwd
/original/dir # ← directory unchanged despite exit 0
Expected behaviour
rtk rewrite "rtk <builtin> ..." should either:
- Return passthrough (exit 1) so the shell runs the bare builtin, or
- Strip the redundant prefix and return
cd /tmp (exit 3)
Either way, the shell builtin should execute in the current process rather than a dead-end subprocess.
Context
The opencode plugin calls rtk rewrite on every bash tool call and replaces the command if the output differs from input. When a model manually prefixes rtk cd (following the "always use rtk" instruction in AGENTS.md), rtk rewrite returns the same string with exit 3 — so the plugin leaves the command as rtk cd /path, which executes with no net directory change.
Observed during GLM-4.7-Flash evaluation (2026-06-19): model ran rtk cd /path && rtk npm init -y, npm init ran in the wrong directory, model then invented a non-existent --workdir flag to compensate.
Workaround (local opencode plugin)
const SHELL_BUILTINS = /^rtk\s+(cd|pushd|popd|export|source|alias|unset|ulimit|umask)\b/
if (SHELL_BUILTINS.test(command)) {
command = command.replace(/^rtk\s+/, "")
;(args as Record<string, unknown>).command = command
return
}
Version
rtk 0.42.4
Bug
rtk rewritetreats a command that already starts withrtkas a valid rewrite target and returns it unchanged with exit 3 ("handled"). When the inner command is a shell builtin (cd,export,source, etc.) this silently breaks the builtin's effect, because the model's manually-prefixedrtk cd /pathexecutesrtkas a subprocess — the directory change is lost when that subprocess exits.Reproduction
Expected behaviour
rtk rewrite "rtk <builtin> ..."should either:cd /tmp(exit 3)Either way, the shell builtin should execute in the current process rather than a dead-end subprocess.
Context
The opencode plugin calls
rtk rewriteon every bash tool call and replaces the command if the output differs from input. When a model manually prefixesrtk cd(following the "always use rtk" instruction inAGENTS.md),rtk rewritereturns the same string with exit 3 — so the plugin leaves the command asrtk cd /path, which executes with no net directory change.Observed during GLM-4.7-Flash evaluation (2026-06-19): model ran
rtk cd /path && rtk npm init -y, npm init ran in the wrong directory, model then invented a non-existent--workdirflag to compensate.Workaround (local opencode plugin)
Version
rtk 0.42.4