-
Notifications
You must be signed in to change notification settings - Fork 968
docs: consolidate to user-facing guide only (removes duplicates and legacy flat docs) #1029
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from 9 commits
927daef
51939a5
b812a0e
bff0258
e51be7a
45d8dca
9c9879c
25438b2
974db2f
a94e949
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,3 @@ | ||
| { | ||
| ".": "0.34.1" | ||
| ".": "0.34.3" | ||
| } |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| # RTK Documentation — Interface Contract | ||
|
|
||
| This directory is the source of truth for user-facing and contributor documentation. | ||
| It feeds the RTK website via the `prepare-docs.mjs` pipeline in `rtk-ai/rtk-website`. | ||
|
|
||
| ## Structure | ||
|
|
||
| ``` | ||
| docs/ | ||
| README.md <- This file (interface contract — do not remove) | ||
| guide/ -> User-facing documentation (Tab "Guide") | ||
| reference/ -> Contributor/technical documentation (Tab "Reference") | ||
| architecture/ -> Conceptual/visual documentation (Tab "Architecture") | ||
| ``` | ||
|
|
||
| ## Frontmatter (required on every .md) | ||
|
|
||
| Every markdown file under `docs/guide/`, `docs/reference/`, and `docs/architecture/` | ||
| must include this frontmatter block at the top: | ||
|
|
||
| ```yaml | ||
| --- | ||
| title: string # Page title (used in sidebar + search) | ||
| description: string # One-line summary for search results and SEO | ||
| sidebar: | ||
| order: number # Position within the sidebar group (1 = first) | ||
| --- | ||
| ``` | ||
|
|
||
| The `prepare-docs.mjs` pipeline validates this contract at build time and **fails fast** | ||
| with a clear error message if frontmatter is missing or malformed. | ||
|
|
||
| ## Conventions | ||
|
|
||
| - **Filenames**: kebab-case, `.md` only (e.g., `getting-started.md`, `quick-start.md`) | ||
| - **Subdirectories**: become sidebar groups in Starlight (directory name = group label) | ||
| - **Internal links**: relative within the same tab (`./foo.md`, `./getting-started/installation.md`) | ||
| - **Cross-tab links**: full path from `docs/` root (`../../reference/internals/command-routing.md`) | ||
| - **Diagrams**: Mermaid in fenced code blocks (` ```mermaid `) | ||
| - **Code samples**: always specify the language (`rust`, `toml`, `bash`, `shell`) | ||
| - **Language**: English only | ||
|
|
||
| ## Tabs overview | ||
|
|
||
| | Tab | Path | Audience | | ||
| |-----|------|----------| | ||
| | Guide | `docs/guide/` | End users installing and using RTK | | ||
| | Reference | `docs/reference/` | Contributors, maintainers, integrators | | ||
| | Architecture | `docs/architecture/` | Readers exploring design decisions and diagrams | | ||
|
|
||
| ## Root files (do not move or modify structure) | ||
|
|
||
| The following files live at the repository root and are **not** managed by this pipeline. | ||
| They are the canonical source for GitHub display and remain unchanged. | ||
|
|
||
| - `README.md` — Project overview | ||
| - `INSTALL.md` — Installation reference (full) | ||
| - `CONTRIBUTING.md` — Contribution guide | ||
| - `SECURITY.md` — Security policy | ||
| - `ARCHITECTURE.md` — Full architecture document | ||
| - `CHANGELOG.md` — Release history | ||
|
|
||
| The guide files in `docs/` are derived, English-only, structured versions intended | ||
| for the website. They reference root files as source material but do not replace them. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| --- | ||
| title: Proxy Architecture | ||
| description: ADR — why RTK uses a CLI proxy pattern instead of shell aliases or wrappers | ||
| sidebar: | ||
| order: 2 | ||
| --- | ||
|
|
||
| # ADR: Proxy Architecture | ||
|
|
||
| ## Decision | ||
|
|
||
| RTK is a CLI proxy: a single binary that intercepts commands, executes them as subprocesses, filters the output, and exits. Users invoke `rtk git status` instead of `git status`. | ||
|
|
||
| Hooks extend this by making the interception transparent — the AI agent's command is rewritten before execution, so neither the agent nor the user types `rtk`. | ||
|
|
||
| ## Alternatives considered | ||
|
|
||
| ### Shell aliases | ||
|
|
||
| ```bash | ||
| alias git='rtk git' | ||
| alias cargo='rtk cargo' | ||
| ``` | ||
|
|
||
| **Rejected because:** | ||
| - Requires shell configuration per-user, per-machine, per-shell | ||
| - Doesn't work for non-interactive contexts (scripts, CI, AI agents) | ||
| - Can't be installed programmatically without modifying shell dotfiles | ||
| - Breaks if the user has other aliases or functions with the same name | ||
|
|
||
| ### Shell function wrappers | ||
|
|
||
| Similar to aliases but more fragile. Same problems. | ||
|
|
||
| ### `LD_PRELOAD` / dynamic linking interception | ||
|
|
||
| **Rejected because:** | ||
| - Platform-specific (Linux only with glibc) | ||
| - Security restrictions (macOS SIP, container environments) | ||
| - Complex to implement, maintain, and debug | ||
|
|
||
| ### Hook-only approach (no explicit `rtk` prefix) | ||
|
|
||
| Make RTK entirely invisible — install hooks and never expose `rtk <cmd>` as a user-facing interface. | ||
|
|
||
| **Rejected because:** | ||
| - Users need a way to invoke RTK explicitly for debugging (`rtk git status -vvv`) | ||
| - `rtk gain` and `rtk discover` need a namespace | ||
| - Transparent hooks are additive, not a replacement for the explicit interface | ||
|
|
||
| ## Why the proxy pattern works | ||
|
|
||
| **Single binary, no configuration:** `rtk git status` works identically on macOS, Linux, and Windows. No dotfiles. No shell-specific setup. | ||
|
|
||
| **Explicit and debuggable:** `-v`/`-vv`/`-vvv` flags expose what RTK is doing at each phase. `RTK_DISABLED=1` bypasses it for one command. | ||
|
|
||
| **Exit code preservation:** RTK propagates the underlying tool's exit code. CI pipelines that check `$?` work correctly. | ||
|
|
||
| **Fail-safe:** If RTK's filter fails, it falls back to raw output. The user always gets a result. | ||
|
|
||
| **Hook interception as an enhancement:** The hook layer adds transparency on top of the proxy pattern — it rewrites `git status` to `rtk git status` before the agent sees it. But the proxy interface remains available for direct use, debugging, and tools that can't be hooked. | ||
|
|
||
| ## Consequences | ||
|
|
||
| - Every supported command needs a module in `src/cmds/` | ||
| - Unsupported commands pass through transparently (no breakage) | ||
| - The binary grows as new commands are added (~5MB currently, well within the `<5MB` soft target after stripping) | ||
| - Adding a new command = adding a module + registering in `main.rs` + adding rewrite pattern in `discover/registry.rs` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| --- | ||
| title: Why No Async | ||
| description: ADR — why RTK is single-threaded and does not use tokio or async runtimes | ||
| sidebar: | ||
| order: 1 | ||
| --- | ||
|
|
||
| # ADR: Why No Async | ||
|
|
||
| ## Decision | ||
|
|
||
| RTK is single-threaded. No `tokio`, `async-std`, or `futures`. All I/O is blocking. | ||
|
|
||
| ## Context | ||
|
|
||
| RTK is a CLI proxy that runs for milliseconds and exits. The typical invocation: | ||
|
|
||
| 1. Parse CLI arguments (~0.1ms) | ||
| 2. Spawn one subprocess and capture its output (~2-5ms) | ||
| 3. Filter the output (~0.1ms) | ||
| 4. Print and exit | ||
|
|
||
| There is no concurrent I/O, no network server, no parallel request handling. | ||
|
|
||
| ## Consequences | ||
|
|
||
| **Why async would hurt:** | ||
|
|
||
| - `tokio` adds 5-10ms to startup time from runtime initialization. RTK's target is `<10ms` total. Async would consume half the budget before the first useful line of code. | ||
| - The entire value proposition of RTK is zero-overhead transparency. If developers perceive any delay, they disable it. | ||
| - One subprocess. One output stream. No concurrency needed. | ||
|
|
||
| **Why blocking I/O is correct here:** | ||
|
|
||
| - `std::process::Command::output()` captures stdout + stderr in one blocking call. This is exactly what RTK needs. | ||
| - No event loop required. No `.await` noise in filter code. | ||
| - Binary stays under 5MB. No runtime dependencies. | ||
|
|
||
| ## Tradeoffs | ||
|
|
||
| **What we give up:** | ||
| - Hypothetical future parallelism (e.g., running multiple filters in parallel). Not needed today. | ||
| - Async ecosystem crates (reqwest, sqlx). RTK uses `rusqlite` (sync) and `ureq` (sync) instead. | ||
|
|
||
| **What we gain:** | ||
| - `<10ms` startup, always. | ||
| - Simple, readable filter code with no `.await` punctuation. | ||
| - No runtime initialization path that can fail. | ||
|
|
||
| ## Rule | ||
|
|
||
| If you add a dependency that pulls in `tokio` or any async runtime, the PR will be rejected. Check before adding: `cargo tree | grep tokio`. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| --- | ||
| title: Command Flow | ||
| description: End-to-end diagram of how a command flows through RTK from agent to LLM | ||
| sidebar: | ||
| order: 1 | ||
| --- | ||
|
|
||
| # Command Flow | ||
|
|
||
| End-to-end flow from the AI agent issuing a command to the filtered output reaching the LLM. | ||
|
|
||
| ## With hook (transparent rewrite) | ||
|
|
||
| ```mermaid | ||
| flowchart TD | ||
| A["AI Agent\n(Claude Code, Cursor, etc.)"] -->|"runs: cargo test"| B | ||
|
|
||
| subgraph HOOK ["Hook Interception (PreToolUse)"] | ||
| B["Hook reads JSON input\nextract command string"] --> C | ||
| C["rtk rewrite 'cargo test'"] --> D | ||
| D{"Registry match?"} | ||
| D -->|"yes"| E["returns 'rtk cargo test'"] | ||
| D -->|"no match"| F["returns original unchanged"] | ||
| end | ||
|
|
||
| E --> G | ||
| F --> G | ||
|
|
||
| subgraph RTK ["RTK Binary"] | ||
| G["Phase 1: Parse\nClap → Commands::Cargo"] --> H | ||
| H["Phase 2: Route\ncargo::run(args)"] --> I | ||
| I["Phase 3: Execute\nstd::process::Command::new('cargo')\n.args(['test'])"] --> J | ||
| J["Phase 4: Filter\nfailures only\n200 lines → 5 lines"] --> K | ||
| K["Phase 5: Print\nprintln!(filtered)"] --> L | ||
| L["Phase 6: Track\nSQLite INSERT\n(input=5000tok, output=50tok)"] | ||
| end | ||
|
|
||
| K -->|"filtered output"| M["LLM Context\n~90% fewer tokens"] | ||
| ``` | ||
|
|
||
| ## Without hook (direct usage) | ||
|
|
||
| ```mermaid | ||
| flowchart LR | ||
| A["Developer\ntype: rtk git status"] --> B["RTK Binary"] | ||
| B --> C["git status (subprocess)"] | ||
| C -->|"20 lines raw"| B | ||
| B -->|"5 lines filtered"| D["Terminal\n(or LLM context)"] | ||
| ``` | ||
|
|
||
| ## Filter lookup (TOML path) | ||
|
|
||
| ```mermaid | ||
| flowchart LR | ||
| CMD["rtk my-tool args"] --> P1 | ||
| P1{"1. .rtk/filters.toml\n(project-local)"} | ||
| P1 -->|"match"| WIN["apply filter → print"] | ||
| P1 -->|"no match"| P2 | ||
| P2{"2. ~/.config/rtk/filters.toml\n(user-global)"} | ||
| P2 -->|"match"| WIN | ||
| P2 -->|"no match"| P3 | ||
| P3{"3. BUILTIN_TOML\n(binary)"} | ||
| P3 -->|"match"| WIN | ||
| P3 -->|"no match"| P4[["exec raw\n(passthrough)"]] | ||
| ``` |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,71 @@ | ||||||
| --- | ||||||
| title: Filter Pipeline | ||||||
| description: How a TOML filter goes from file to execution — build pipeline and runtime stages | ||||||
| sidebar: | ||||||
| order: 2 | ||||||
| --- | ||||||
|
|
||||||
| # Filter Pipeline | ||||||
|
|
||||||
| ## Build pipeline | ||||||
|
|
||||||
| ```mermaid | ||||||
| flowchart TD | ||||||
| A[["src/filters/my-tool.toml\n(new file)"]] --> B | ||||||
|
|
||||||
| subgraph BUILD ["cargo build"] | ||||||
| B["build.rs\n1. ls src/filters/*.toml\n2. sort alphabetically\n3. concat → BUILTIN_TOML"] --> C | ||||||
| C{"TOML valid?\nDuplicate names?"} -->|"❌ panic"| D[["Build fails\nerror points to bad file"]] | ||||||
| C -->|"✅ ok"| E[["OUT_DIR/builtin_filters.toml\n(generated)"]] | ||||||
| E --> F["rustc embeds via include_str!"] | ||||||
| F --> G[["rtk binary\nBUILTIN_TOML embedded"]] | ||||||
| end | ||||||
|
|
||||||
| subgraph TESTS ["cargo test"] | ||||||
| H["test_builtin_filter_count\nassert_eq!(filters.len(), N)"] -->|"❌ wrong count"| I[["FAIL"]] | ||||||
| J["test_builtin_all_filters_present\nassert!(names.contains('my-tool'))"] -->|"❌ name missing"| K[["FAIL"]] | ||||||
| L["test_builtin_all_filters_have_inline_tests\nassert!(tested.contains(name))"] -->|"❌ no tests"| M[["FAIL"]] | ||||||
| end | ||||||
|
|
||||||
| subgraph VERIFY ["rtk verify"] | ||||||
| N["runs [[tests.my-tool]]\ninput → filter → compare expected"] | ||||||
| N -->|"❌ mismatch"| O[["FAIL\nshows actual vs expected"]] | ||||||
| N -->|"✅ pass"| P[["All tests passed"]] | ||||||
| end | ||||||
|
|
||||||
| G --> H & J & L & N | ||||||
| ``` | ||||||
|
|
||||||
| ## Runtime stages | ||||||
|
|
||||||
| ```mermaid | ||||||
| flowchart TD | ||||||
| CMD["rtk my-tool args"] --> LOOKUP | ||||||
|
|
||||||
| subgraph LOOKUP ["Filter Lookup"] | ||||||
| L1{".rtk/filters.toml"} -->|"match"| APPLY | ||||||
| L1 -->|"no match"| L2 | ||||||
| L2{"~/.config/rtk/filters.toml"} -->|"match"| APPLY | ||||||
| L2 -->|"no match"| L3 | ||||||
| L3{"BUILTIN_TOML"} -->|"match"| APPLY | ||||||
| L3 -->|"no match"| RAW[["exec raw (passthrough)"]] | ||||||
| end | ||||||
|
|
||||||
| APPLY --> EXEC["exec command\ncapture stdout"] | ||||||
| EXEC --> PIPE | ||||||
|
|
||||||
| subgraph PIPE ["8-stage filter pipeline"] | ||||||
| S1["1. strip_ansi"] --> S2 | ||||||
| S2["2. replace"] --> S3 | ||||||
| S3{"3. match_output\nshort-circuit?"} | ||||||
| S3 -->|"✅ match"| MSG[["emit on_match\nstop"]] | ||||||
|
||||||
| S3 -->|"✅ match"| MSG[["emit on_match\nstop"]] | |
| S3 -->|"✅ match"| MSG[["emit rule message\nstop"]] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PR description says “No existing files were modified” and “All changes are additive”, but this PR changes the crate version (and also updates CHANGELOG/Cargo.lock/release manifest). If the version bump is intentional, please update the PR description; otherwise, consider dropping these release/version changes from this docs-only PR.