feat(shell): add rtk-shell, bash-wrapped shell for agent harnesses#2855
feat(shell): add rtk-shell, bash-wrapped shell for agent harnesses#2855guyzmo wants to merge 1 commit into
Conversation
|
Automatic message from CI checks : It seems like this branch is targeting the wrong branch, any contribution should target develop branch. See CONTRIBUTING.md for details. |
|
@guyzmo Nice work on the session internals here, the nonce-based sentinels, dual-stream draining threads, and the sentinel-leak regression tests show real care on the trickiest part of this (process concurrency). One blocker before we get into the actual review: this PR targets Can you retarget the base branch to |
|
@FlorianBruniaux I already rebased last night when I saw this. I'm sorry, I'm not used for projects in git flow, especially using master for production. This is surprising ;-) Maybe you should add something in agents.md to make the llm yell when a contributor does a PR against master? 😝 |
Implement rtk-shell: a minimal shell wrapper that filters recognized CLI commands (git status, cargo test/build/clippy, etc.) through RTK to achieve 60-90% token savings for agent harnesses like opencode, while transparently forwarding unsupported commands to a real backing shell. Three invocation modes: 1. One-shot: `rtk-shell -c "..."` (mirrors `sh -c`), used as $SHELL 2. Persistent: `rtk-shell` interactive session with state persistence 3. RC swap: `rtk init --shell-mode` injects ~1KB guarded swap into RC files to auto-enable modes 1-2 when invoked by known harnesses Implementation: - Extract src/lib.rs (rtk crate) to share modules with rtk-shell binary (Cargo.toml: add [lib] target, [[bin]] for rtk-shell) - New src/shell/ module: dispatch (classify line into Filterable/Forward segments), oneshot (run -c line via backing shell + filters), session (persistent backing shell with nonce-based sentinels to avoid deadlock, threaded stdout/stderr draining, signal forwarding, heredoc detection) - Extend src/core/config.rs: ShellConfig (backing_shell, minimal_ps1) - Extend src/core/tracking.rs: optional session_id column for metrics - Add src/core/utils::exit_code_from_status (map signal deaths to 128+signum, fixing Commands::Proxy/Commands::Run exit code gaps) - Extend src/hooks/: Mode-3 RC injection (~/.rtk-shell-swap.sh) with recursion guard (RTK_IN_SHELL), env-var detection, isatty failsafe - Fix module imports across all command modules (aws, container, dotnet, git, go, js/vitest, etc.) for new lib root - Add tests/shell_integration_test.rs: git status filtering, exit codes, signal handling, cd/pwd persistence in session mode Motivation: RTK's primary use case is reducing token overhead for agentic interactions. The existing `rtk <cmd>` syntax requires explicit rewriting via PreToolUse hooks. rtk-shell eliminates that friction by becoming the $SHELL itself — agents get token savings by default. This implementation targets agent harnesses (mode 2/$SHELL, mode 3 RC swap) rather than human interactive use, per explicit design guidance. Known limitations: no PTY/TUI (forward unfiltered), Windows out of scope, OPENCODE_SESSION_ID placeholder (unconfirmed), most ecosystems beyond git/cargo fall back to raw passthrough (intentional, documented). Co-Authored-By: Claude <noreply@anthropic.com>
Summary
rtk-shell, a minimal shell wrapper that filters recognized CLI commands (git status,cargo test/build/clippy, etc.) through RTK's existing filters to cut token overhead for agent harnesses (e.g. opencode), while transparently forwarding anything it doesn't recognize to a real backing shell.rtk-shell -c "...", usable as$SHELL), persistent interactive session (withcd/env state persistence across commands), and an opt-in RC-file swap (rtk init) that auto-enables the shell when invoked by a known agent harness in non-interactive mode.src/lib.rsso the module tree is shared between thertkandrtk-shellbinaries; addssrc/shell/(dispatch, oneshot, session) plus supporting changes to config, tracking, and hooks.Design notes / known limitations
git status/cargo test/build/check/clippyget real filtering in session mode today; other recognized commands intentionally fall back to raw passthrough (documented, not silent) pending follow-up work.OPENCODE_SESSION_IDin the known-harness env var list is an unconfirmed placeholder — flagged for review.Test plan
cargo fmt --all -- --checkcargo clippy --all-targets(zero warnings)cargo test --all(2408 passed, 9 ignored, 0 failed)git status(git repo + non-git dir)cd/pwdstate persists across commands in a sessionecho hello | grep hello) still worksOPENCODE_SESSION_IDenv var name against opencode's actual harness detection surface🤖 Generated with Claude Code