headroom/tests/test_cli
Tejas Chopra 44136ed042
fix(wrap): make RTK opt-in (off by default) across wrap subcommands (#2344)
## Description

RTK CLI-command filtering was set up **by default** across ~16 `wrap`
subcommands (copilot, codex, aider, cursor, cline, continue, goose,
openhands, opencode, grok, omp, openclaude, vibe, …) via `if not
no_rtk:` — so users got rtk hooks / instruction injection without opting
in. `wrap claude` was the lone exception (already gated on
`--context-tool`).

This makes RTK **opt-in (off by default)** everywhere, so Headroom's own
savings are what's measured unless a user explicitly wants rtk.

Closes #

## Type of Change
- [x] Bug fix (behavior change: default flip)

## Changes Made
- **Central gate** `_rtk_opt_in()` — RTK runs only when explicitly
enabled via `--rtk` or `HEADROOM_RTK=1`. Guards the 3 RTK entry points
(`_setup_rtk`, `_ensure_rtk_binary`, `_inject_rtk_instructions`) so they
no-op by default — one small change instead of editing ~30 call sites.
- **`--rtk` opt-in flag** on all 18 tool subcommands via a shared
eager-callback option (`expose_value=False`, sets `HEADROOM_RTK=1`; no
subcommand signature changes).
- `wrap claude`'s legacy `--context-tool` still opts in (mirrored into
the gate).
- **`--no-rtk` kept** as an accepted, now-redundant no-op (back-compat).
- lean-ctx and all non-RTK behavior untouched.

## Testing
```text
pytest tests/test_wrap_rtk_opt_in.py   -> 4 passed
ruff check / format                    -> clean
mypy headroom                          -> Success: no issues found in 504 source files
```
Verified `--rtk` appears in `wrap {claude,codex,copilot} --help`;
`_rtk_opt_in()` is False by default, True with `HEADROOM_RTK=1`; entry
points no-op + write nothing when off.

## Real Behavior Proof
- Env: local `.venv`, click CliRunner.
- Steps: import wrap; assert gate default-off / env-on; assert
`_setup_rtk`/`_ensure_rtk_binary` return None and
`_inject_rtk_instructions` returns False + writes no file when not opted
in; assert `--rtk` in subcommand help.
- Observed: all pass. Not tested: a live end-to-end wrap launch (proxy
spawn).

## Notes
Part 2 of 3 (RTK opt-in). Separate PRs cover the code-graph MCP engine
and the proxy-option cleanup. No `CHANGELOG.md` edit — release-please
generates it from the PR title (per the changelog guard).

---------

Co-authored-by: JerrettDavis <mxjerrett@gmail.com>
2026-07-17 16:47:19 -07:00
..
conftest.py feat(wrap): make tokensave the primary coding-task compressor, Serena the backup (#1230) 2026-06-25 16:55:37 -05:00
test_copilot_auth.py fix(auth): support GitHub Enterprise Copilot OAuth domain (#2192) 2026-07-14 16:07:17 -04:00
test_init_cli.py fix(cli/init): fail clearly on a target settings file with invalid JSON (#2227) 2026-07-15 18:15:45 +00:00
test_init_enable_tool_search.py fix(init): set ENABLE_TOOL_SEARCH=true so Claude Code keeps deferring tools (#746) (#995) 2026-06-19 11:26:26 -05:00
test_install_cli.py feat(deploy): Add turnkey deploy command (#1404) 2026-07-15 18:37:20 +00:00
test_main_help_version.py fix(wrap): replace stale-proxy detection with Vite-style port fallback (#1406) 2026-07-07 12:10:52 -05:00
test_mcp.py feat(mcp): add streamable HTTP MCP transport (#1773) 2026-07-14 13:25:45 -04:00
test_mcp_status.py fix(mcp): mcp status checks ~/.claude.json, not only ~/.claude/mcp.json (#990) 2026-07-15 09:25:52 -05:00
test_recover_codex.py fix(codex): preserve wrapped sessions and recover state (#2160) 2026-07-15 19:58:21 +00:00
test_serena_disable.py fix(serena): stop the Serena dashboard popup and make --no-serena actually disable Serena (#1003) 2026-06-14 23:32:46 -07:00
test_serena_migrate.py fix(serena): migrate stale Headroom-installed Serena entry on re-wrap (#1008) 2026-06-16 15:17:13 -05:00
test_subprocess_utf8_encoding.py fix(windows): pin UTF-8 encoding on text-mode subprocess calls (#1311) 2026-06-23 12:52:49 -05:00
test_tokensave_helpers.py feat(wrap): make tokensave the primary coding-task compressor, Serena the backup (#1230) 2026-06-25 16:55:37 -05:00
test_tokensave_setup.py feat(wrap): make tokensave the primary coding-task compressor, Serena the backup (#1230) 2026-06-25 16:55:37 -05:00
test_unwrap_claude.py fix(wrap): stop same-port persistent routing during claude unwrap (#2340) (#2350) 2026-07-17 16:08:40 -07:00
test_wrap_aider.py feat(proxy): per-project savings breakdown on the dashboard (claude, codex, aider, copilot, cursor) (#803) 2026-06-10 21:04:45 -05:00
test_wrap_bridge.py fix(wrap): make RTK opt-in (off by default) across wrap subcommands (#2344) 2026-07-17 16:47:19 -07:00
test_wrap_claude_base_url.py fix(proxy): dedupe Codex WS request logging for accurate mixed-provider dashboards (#2189) 2026-07-15 18:18:34 +00:00
test_wrap_claude_finally_unbound.py fix(wrap/claude): bind _wrap_settings_path before the try (#2126) 2026-07-14 12:02:39 -04:00
test_wrap_claude_vertex_proxy_env.py fix(wrap): surface Claude Remote Control base-URL gate accurately (#1… (#1883) 2026-07-13 14:01:37 -04:00
test_wrap_codex.py fix(wrap): make RTK opt-in (off by default) across wrap subcommands (#2344) 2026-07-17 16:47:19 -07:00
test_wrap_continue.py fix(cli): G1 remediation — non-string clobber, per-model systemMessage, openhands gate 2026-05-25 11:54:06 -07:00
test_wrap_copilot.py fix(wrap): make RTK opt-in (off by default) across wrap subcommands (#2344) 2026-07-17 16:47:19 -07:00
test_wrap_dead_marker_selfheal.py fix(wrap): self-heal a stale ANTHROPIC_BASE_URL left by a dead proxy (#2223) 2026-07-15 19:58:10 +00:00
test_wrap_encoding.py fix(wrap): make RTK opt-in (off by default) across wrap subcommands (#2344) 2026-07-17 16:47:19 -07:00
test_wrap_goose.py refactor(cli): factor shared wrap-subcommand scaffolding 2026-05-26 11:22:50 -07:00
test_wrap_grok.py feat(wrap): add first-class Grok CLI support (#1823) 2026-07-15 18:51:38 +00:00
test_wrap_helpers.py fix(wrap): drop -p short flag from wrap claude so claude's own -p/--print passes through (#2048) 2026-07-14 14:10:34 -04:00
test_wrap_hintfile_agents.py fix(wrap): make RTK opt-in (off by default) across wrap subcommands (#2344) 2026-07-17 16:47:19 -07:00
test_wrap_kimi.py feat(wrap): add headroom wrap kimi for Kimi CLI (#1426) 2026-07-15 21:40:58 +00:00
test_wrap_omp.py fix(wrap): make RTK opt-in (off by default) across wrap subcommands (#2344) 2026-07-17 16:47:19 -07:00
test_wrap_openclaude.py fix(wrap): make RTK opt-in (off by default) across wrap subcommands (#2344) 2026-07-17 16:47:19 -07:00
test_wrap_openclaw.py fix(wrap): use canonical headroom-openclaw npm package for wrap openclaw (#1969) (#2120) 2026-07-13 16:33:44 -04:00
test_wrap_opencode.py fix(wrap): make RTK opt-in (off by default) across wrap subcommands (#2344) 2026-07-17 16:47:19 -07:00
test_wrap_openhands.py fix(cli): G1 remediation — non-string clobber, per-model systemMessage, openhands gate 2026-05-25 11:54:06 -07:00
test_wrap_persistent.py fix: check feature configuration before reusing persistent deployments (#1330) 2026-07-14 14:10:31 -04:00
test_wrap_proxy_detach.py fix(wrap): detach the shared proxy on Windows so it survives an ungraceful agent close (#1464) 2026-06-30 13:49:28 -05:00
test_wrap_rtk_metrics.py fix(observability): G3 remediation — bound cardinality + wire dead metrics 2026-05-24 10:41:56 -07:00
test_wrap_rtk_on_path.py fix(rtk): link managed rtk onto PATH instead of mutating the hook (#1698) 2026-07-07 12:23:26 -05:00
test_wrap_stale_marker.py fix: detect and clear stale ANTHROPIC_BASE_URL from crashed wrap sessions (#1768) (#1837) 2026-07-06 08:35:40 -07:00
test_wrap_vibe.py feat: Add support for Mistral Vibe CLI (#935) 2026-06-16 14:59:51 -05:00
test_wrap_zcode.py fix(wrap): make RTK opt-in (off by default) across wrap subcommands (#2344) 2026-07-17 16:47:19 -07:00