Skip to content

feat(dispatch): run rtk as a busybox-style multi-call binary via argv[0]#2594

Closed
mazzz1y wants to merge 1 commit into
rtk-ai:developfrom
mazzz1y:feat/argv0-multicall-dispatch
Closed

feat(dispatch): run rtk as a busybox-style multi-call binary via argv[0]#2594
mazzz1y wants to merge 1 commit into
rtk-ai:developfrom
mazzz1y:feat/argv0-multicall-dispatch

Conversation

@mazzz1y

@mazzz1y mazzz1y commented Jun 24, 2026

Copy link
Copy Markdown

Summary

  • Run rtk as a busybox-style multi-call binary: when invoked under a tool's name via a symlink (e.g. head -> rtk), it rewrites the invocation to the equivalent rtk <sub> via the rewrite registry, and execs the real tool when there's no equivalent (or the synthesized form fails to parse)
  • Self-excluding binary resolution (resolve_binary skips PATH candidates that are symlinks resolving to a file named rtk) so a tool -> rtk symlink can't re-exec rtk forever — it always finds the genuine tool further down PATH
  • The arg tail is spliced from the original OsString args (not re-split from a shell string), so quotes/escapes/non-UTF8 survive verbatim; a lexer round-trip guard passes structured/compound args straight through to the real tool
  • Manual usage documented in README.md

Why

I want to wire rtk into a Nix derivation that builds an idempotent, declarative setup across multiple tools on a machine. The auto-rewrite hook needs a Unix shell + per-agent hook config and mutates state at runtime, which doesn't fit a pure/idempotent Nix build.

With argv0 dispatch I can declaratively create tool -> rtk symlinks (ln -s rtk head) in the derivation output and have those tools transparently routed through rtk's filters — no hook, no runtime mutation, reproducible across hosts.

Tools rtk doesn't rewrite (or invocations with no equivalent) pass straight through to the real binary, so shadowing them on PATH is safe.

Test plan

# Build, then create tool-name symlinks pointing at the rtk binary.
RTK="$(pwd)/target/debug/rtk"
mkdir -p /tmp/rtk-shims
ln -sf "$RTK" /tmp/rtk-shims/head
ln -sf "$RTK" /tmp/rtk-shims/git
export PATH="/tmp/rtk-shims:$PATH"   # shadow the real tools

# Invoked under a tool's name -> rewritten to the rtk equivalent:
head file.txt           # runs `rtk read file.txt`
git log                 # runs `rtk git log`

When rtk is invoked under a tool's name via a symlink (e.g. `head` -> rtk),
translate the invocation to the equivalent `rtk <sub>` via the rewrite
registry and parse it with Clap; on no-equivalent or parse failure, exec
the real tool. A self-check on resolved binaries prevents re-exec loops.

- resolve_binary skips candidates that are symlinks whose target's file
  name is `rtk` (first_non_self_candidate); wrapper scripts that re-invoke
  rtk are out of scope and would loop — use symlinks for packaging.
- synthesize_rtk_argv splices the arg tail from original OsStrings so
  quotes/escapes/non-UTF8 survive; a lexer round-trip guard passes
  structured args through to the real tool.
- exec_real_tool: #[cfg(unix)] exec, #[cfg(not(unix))] spawn+wait.
- telemetry fires only on real rtk runs, never on passthrough.
- document manual symlink usage in README.
@CLAassistant

CLAassistant commented Jun 24, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@mazzz1y mazzz1y closed this Jul 16, 2026
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