544 lines
20 KiB
Markdown
544 lines
20 KiB
Markdown
# AGENTS.md — Klubhaus Doorbell
|
||
|
||
Multi-target Arduino/ESP32 doorbell alert system using ntfy.sh.
|
||
|
||
## Quick Reference
|
||
|
||
```bash
|
||
# Compile, upload, monitor
|
||
BOARD=esp32-32e-4 mise run compile # compile
|
||
BOARD=esp32-32e-4 mise run upload # upload (auto-kills monitor)
|
||
BOARD=esp32-32e-4 mise run monitor # start JSON monitor daemon
|
||
BOARD=esp32-32e-4 mise run log-tail # watch colored logs
|
||
BOARD=esp32-32e-4 mise run cmd COMMAND=dashboard # send command
|
||
BOARD=esp32-32e-4 mise run state # show device state
|
||
|
||
# Install libs (run after cloning)
|
||
mise run install-libs-shared # shared libs (ArduinoJson, NTPClient)
|
||
BOARD=esp32-32e-4 mise run install # shared + board-specific libs
|
||
```
|
||
|
||
**Default BOARD**: `esp32-s3-lcd-43` (set in mise.toml)
|
||
|
||
## Project Overview
|
||
|
||
Three board targets share business logic via a common library:
|
||
|
||
| Board | Display | Library | Build Command |
|
||
|-------|---------|---------|--------------|
|
||
| ESP32-32E | SPI TFT 320x240 (ILI9341) | TFT_eSPI | `BOARD=esp32-32e mise run compile` |
|
||
| ESP32-32E-4" | SPI TFT 320x480 (ST7796) | TFT_eSPI | `BOARD=esp32-32e-4 mise run compile` |
|
||
| ESP32-S3-Touch-LCD-4.3 | 800x480 RGB parallel | LovyanGFX | `BOARD=esp32-s3-lcd-43 mise run compile` |
|
||
|
||
## Essential Commands
|
||
|
||
All commands run via **mise**:
|
||
|
||
```bash
|
||
# Install all dependencies (shared libs + vendored display libs)
|
||
mise run install-libs-shared
|
||
mise run install # install shared + board-specific libs (requires BOARD env)
|
||
|
||
# Generic commands (set BOARD environment variable)
|
||
BOARD=esp32-32e mise run compile # compile for ESP32-32E
|
||
BOARD=esp32-32e mise run upload # upload to ESP32-32E
|
||
BOARD=esp32-32e mise run monitor # monitor ESP32-32E
|
||
|
||
BOARD=esp32-32e-4 mise run compile # compile for ESP32-32E-4"
|
||
BOARD=esp32-32e-4 mise run upload # upload to ESP32-32E-4"
|
||
BOARD=esp32-32e-4 mise run monitor # monitor ESP32-32E-4"
|
||
|
||
BOARD=esp32-s3-lcd-43 mise run compile # compile for ESP32-S3-LCD-4.3
|
||
BOARD=esp32-s3-lcd-43 mise run upload # upload to ESP32-S3-LCD-4.3
|
||
BOARD=esp32-s3-lcd-43 mise run monitor # monitor ESP32-S3-LCD-4.3
|
||
|
||
# Other useful tasks
|
||
mise run format # format code
|
||
mise run clean # clean build artifacts
|
||
mise run kill # kill running monitor/upload for BOARD
|
||
mise run log-tail # tail colored logs (requires BOARD)
|
||
mise run cmd COMMAND=dashboard # send command to device (requires BOARD)
|
||
mise run state # show device state (requires BOARD)
|
||
|
||
# LSP / IDE support
|
||
mise run gen-compile-commands # generate compile_commands.json for LSP
|
||
mise run gen-crush-config # generate .crush.json with BOARD-based FQBN
|
||
|
||
# Arduino maintenance
|
||
mise run arduino-clean # clear Arduino CLI cache (staging + packages)
|
||
|
||
# Raw serial access
|
||
mise run monitor-raw # raw serial monitor (arduino-cli)
|
||
mise run monitor-tio # show tio command for terminal UI
|
||
```
|
||
|
||
# Board Configuration Files
|
||
|
||
Each board directory contains `board-config.sh` which defines:
|
||
|
||
| Variable | Description |
|
||
|----------|-------------|
|
||
| `FQBN` | Fully Qualified Board Name for arduino-cli |
|
||
| `PORT` | Serial port for upload/monitoring (default: `/dev/ttyUSB0`) |
|
||
| `LIBS` | Vendor library path for `--libraries` flag |
|
||
| `OPTS` | Additional compiler flags (e.g., `-DDEBUG_MODE`) |
|
||
|
||
**Example** (`boards/esp32-32e-4/board-config.sh`):
|
||
|
||
```bash
|
||
FQBN="esp32:esp32:esp32:FlashSize=4M,PartitionScheme=default"
|
||
PORT="/dev/ttyUSB0"
|
||
LIBS="--libraries ./vendor/esp32-32e-4/TFT_eSPI"
|
||
OPTS="-DDEBUG_MODE -DBOARD_HAS_PSRAM"
|
||
```
|
||
|
||
**Port override**: `PORT=/dev/ttyXXX BOARD=esp32-32e mise run upload`
|
||
|
||
**Prerequisites**: arduino-cli with `esp32:esp32` platform installed, mise.
|
||
|
||
## Project Structure
|
||
|
||
```text
|
||
libraries/KlubhausCore/src/ Shared Arduino library
|
||
├── KlubhausCore.h Umbrella include (board sketches use this)
|
||
├── Config.h Constants, timing, WiFiCred struct
|
||
├── ScreenState.h State enums/structs
|
||
├── IDisplayDriver.h Pure virtual display interface
|
||
├── DisplayManager.h Thin wrapper delegating to IDisplayDriver
|
||
├── NetManager.* WiFi, HTTP, NTP
|
||
└── DoorbellLogic.* State machine, ntfy polling
|
||
|
||
boards/
|
||
├── esp32-32e/
|
||
│ ├── esp32-32e.ino Main sketch
|
||
│ ├── board_config.h Board-specific config
|
||
│ ├── secrets.h.example WiFi creds template (copy to secrets.h)
|
||
│ ├── tft_user_setup.h TFT_eSPI config
|
||
│ └── DisplayDriverTFT.* Concrete IDisplayDriver for TFT
|
||
├── esp32-32e-4/
|
||
│ ├── esp32-32e-4.ino Main sketch
|
||
│ ├── board_config.h Board-specific config
|
||
│ ├── secrets.h.example WiFi creds template (copy to secrets.h)
|
||
│ ├── tft_user_setup.h TFT_eSPI config
|
||
│ └── DisplayDriverTFT.* Concrete IDisplayDriver for TFT
|
||
└── esp32-s3-lcd-43/
|
||
├── esp32-s3-lcd-43.ino Main sketch
|
||
├── board_config.h Board-specific config
|
||
├── secrets.h.example WiFi creds template (copy to secrets.h)
|
||
├── LovyanPins.h Pin definitions
|
||
└── DisplayDriverGFX.* Concrete IDisplayDriver for LovyanGFX
|
||
|
||
vendor/ Vendored display libs (recreated by install-libs)
|
||
├── esp32-32e/TFT_eSPI/
|
||
├── esp32-32e-4/TFT_eSPI/
|
||
└── esp32-s3-lcd-43/LovyanGFX/
|
||
```
|
||
|
||
## Code Patterns
|
||
|
||
### Header Guards
|
||
|
||
Use `#pragma once` (not `#ifndef` guards).
|
||
|
||
### Formatting
|
||
|
||
- 4-space indentation, no tabs
|
||
- WebKit-based style (see `.clang-format`)
|
||
- Column limit: 100
|
||
- Opening brace stays on same line (`BreakBeforeBraces: Attach`)
|
||
|
||
### Naming Conventions
|
||
|
||
- Classes: `PascalCase` (e.g., `DisplayManager`, `IDisplayDriver`)
|
||
- Constants/enums: `SCREAMING_SNAKE` (e.g., `POLL_INTERVAL_MS`, `ScreenState::DASHBOARD`)
|
||
- Variables/functions: `camelCase` (e.g., `currentState`, `updateDisplay`)
|
||
- Member variables: prefix with `_` (e.g., `_screenWidth`, `_isConnected`)
|
||
|
||
### Types
|
||
|
||
- Arduino types: `int`, `uint8_t`, `uint16_t`, `size_t`
|
||
- Use fixed-width types for protocol/serialization (`uint8_t`, not `byte`)
|
||
- Avoid `bool` for pin states - use `uint8_t` or `int`
|
||
- Use `size_t` for sizes and array indices
|
||
|
||
### Imports Organization
|
||
|
||
- Arduino core headers first (`Arduino.h`)
|
||
- Standard C/C++ library (`<cstdint>`, `<String>`, `<vector>`)
|
||
- Third-party libraries (e.g., `TFT_eSPI.h`, `ArduinoJson.h`)
|
||
- Local project headers (e.g., `"Config.h"`, `"ScreenState.h"`)
|
||
|
||
### Error Handling
|
||
|
||
- Serial logging pattern: `Serial.println("[ERROR] message")`
|
||
- Use `Serial.printf()` for formatted debug output
|
||
- Return error codes, not exceptions (exceptions not available in Arduino)
|
||
- Log state transitions with `[STATE] → STATE` tags
|
||
|
||
### Class Design
|
||
|
||
- Pure virtual `IDisplayDriver` interface in shared library
|
||
- Each board implements a concrete driver (e.g., `DisplayDriverTFT`, `DisplayDriverGFX`)
|
||
- `DisplayManager` delegates to `IDisplayDriver` — no display-lib coupling in shared code
|
||
|
||
### Arduino Patterns
|
||
|
||
- `setup()` runs once at boot — call `begin()` on managers
|
||
- `loop()` runs continuously — call `update()` on managers
|
||
- Use `millis()` for timing (not `delay()`)
|
||
- Serial console at 115200 baud for debug commands
|
||
|
||
## Testing/Debugging
|
||
|
||
**No unit tests exist** - This is an embedded Arduino sketch. Verify changes by building and deploying to hardware:
|
||
|
||
```bash
|
||
BOARD=esp32-s3-lcd-43 mise run compile # compile for default board
|
||
BOARD=esp32-32e-4 mise run compile # compile for ESP32-32E-4"
|
||
```
|
||
|
||
**Serial commands** (type into serial monitor at 115200 baud):
|
||
|
||
| Command | Action |
|
||
|---------|--------|
|
||
| `alert` | Trigger a test alert |
|
||
| `silence` | Silence current alert |
|
||
| `dashboard` | Show dashboard screen |
|
||
| `off` | Turn off display |
|
||
| `status` | Print state + memory info |
|
||
| `reboot` | Restart device |
|
||
|
||
**Touch Test Commands** (ESP32-S3-LCD-4.3 only):
|
||
|
||
| Command | Action |
|
||
|---------|--------|
|
||
| `TEST:touch X Y press` | Inject synthetic press at raw panel coords (X,Y) |
|
||
| `TEST:touch X Y release` | Inject synthetic release at raw panel coords (X,Y) |
|
||
| `TEST:touch clear` | Clear test mode (required between touch sequences) |
|
||
|
||
Note: The S3 touch panel is rotated 180° relative to the display. Use raw panel coordinates:
|
||
|
||
- Display (100,140) → Raw (700, 340)
|
||
- Display (700,140) → Raw (100, 340)
|
||
|
||
## Monitor Daemon and Logging
|
||
|
||
The build system includes a Python-based monitor agent that provides JSON logging and command pipes.
|
||
|
||
- **JSON log**: `/tmp/doorbell-$BOARD.jsonl` – each line is `{"ts":123.456,"line":"..."}`
|
||
- **State file**: `/tmp/doorbell-$BOARD-state.json` – current device state (screen, alert status, etc.)
|
||
- **Command FIFO**: `/tmp/doorbell-$BOARD-cmd.fifo` – send commands via `echo 'dashboard' > /tmp/doorbell-$BOARD-cmd.fifo`
|
||
|
||
Commands to interact with the daemon:
|
||
|
||
```bash
|
||
BOARD=esp32-32e mise run monitor # Start monitor daemon (background)
|
||
BOARD=esp32-32e mise run log-tail # Tail colored logs
|
||
BOARD=esp32-32e mise run cmd COMMAND=dashboard # Send command
|
||
BOARD=esp32-32e mise run state # Show current device state
|
||
```
|
||
|
||
The monitor daemon automatically starts after upload and is killed before upload to avoid serial port conflicts.
|
||
|
||
## Gotchas
|
||
|
||
1. **secrets.h is gitignored**: Copy from `.example` before building:
|
||
|
||
```bash
|
||
cp boards/esp32-32e/secrets.h.example boards/esp32-32e/secrets.h
|
||
cp boards/esp32-32e-4/secrets.h.example boards/esp32-32e-4/secrets.h
|
||
cp boards/esp32-s3-lcd-43/secrets.h.example boards/esp32-s3-lcd-43/secrets.h
|
||
```
|
||
|
||
2. **Display libs are vendored**: Each board uses a different display library. The build system uses `--libraries` to link only the board's vendored lib — never link both TFT_eSPI and LovyanGFX in the same build.
|
||
|
||
3. **No unit tests**: This is an embedded Arduino sketch — no test suite exists. Verify changes by building and deploying to hardware.
|
||
|
||
4. **LSP errors are expected**: The LSP may show errors about missing Arduino types until `compile_commands.json` is generated. Run `mise run gen-compile-commands` first, then restart the LSP. The build works correctly via arduino-cli.
|
||
|
||
5. **Build artifacts in board dirs**: Build output goes to `boards/[board]/build/` — cleaned by `mise run clean`.
|
||
|
||
6. **WiFi credentials are per-board**: Each board directory has its own `secrets.h` because boards may be on different networks.
|
||
|
||
7. **Use BOARD environment variable**: All build commands require the `BOARD` environment variable (e.g., `BOARD=esp32-32e mise run compile`). The default BOARD is `esp32-s3-lcd-43` (set in mise.toml).
|
||
|
||
8. **Serial port contention**: The `upload`, `monitor`, and `monitor-raw` tasks automatically depend on `kill` which uses `fuser` to terminate any process using the serial port before starting.
|
||
|
||
9. **Monitor state parsing**: The monitor-agent parses serial output for state updates:
|
||
- `[STATE] → DASHBOARD` → updates state file to `"screen":"DASHBOARD"`
|
||
- `[STATE] → ALERT` → updates state file to `"screen":"ALERT"`
|
||
- `[STATE] → OFF` → updates state file to `"screen":"OFF"`
|
||
- `[STATE] → BOOT` → updates state file to `"screen":"BOOT"`
|
||
- `[ADMIN]` commands also update state accordingly
|
||
|
||
10. **Serial baud rate**: All serial communication uses 115200 baud.
|
||
|
||
11. **Serial port contention**: The `kill` task uses `fuser` to release the serial port. Both `upload` and `monitor` tasks depend on `kill` to ensure the port is free.
|
||
|
||
## Config Constants
|
||
|
||
Key timing and configuration values in `Config.h`:
|
||
|
||
| Constant | Default | Description |
|
||
|----------|---------|-------------|
|
||
| `FW_VERSION` | "5.1" | Firmware version string |
|
||
| `POLL_INTERVAL_MS` | 15000 | How often to poll ntfy.sh for new messages |
|
||
| `HEARTBEAT_INTERVAL_MS` | 300000 | NTP sync interval (5 min) |
|
||
| `ALERT_TIMEOUT_MS` | 120000 | Auto-clear alert after 2 min |
|
||
| `INACTIVITY_TIMEOUT_MS` | 30000 | Turn off display after 30s of inactivity |
|
||
| `HOLD_TO_SILENCE_MS` | 3000 | Hold duration to silence alert |
|
||
| `LOOP_YIELD_MS` | 10 | Yield to prevent Task Watchdog (configurable) |
|
||
| `BOOT_GRACE_MS` | 5000 | Grace period at boot before polling starts |
|
||
| `SILENCE_DISPLAY_MS` | 10000 | How long to show silence confirmation |
|
||
| `WIFI_CONNECT_TIMEOUT_MS` | 15000 | WiFi connection timeout |
|
||
| `HTTP_TIMEOUT_MS` | 10000 | HTTP request timeout |
|
||
| `HINT_ANIMATION_MS` | 2000 | Hint animation duration |
|
||
| `HINT_MIN_BRIGHTNESS` | 30 | Minimum brightness for hints |
|
||
| `HINT_MAX_BRIGHTNESS` | 60 | Maximum brightness for hints |
|
||
| `TOUCH_DEBOUNCE_MS` | 100 | Touch debounce delay |
|
||
|
||
## Screen States
|
||
|
||
The device operates in these states (defined in `ScreenState.h`):
|
||
|
||
- **BOOT** — Initializing
|
||
- **DASHBOARD** — Normal operation, showing status
|
||
- **ALERT** — Doorbell ring detected, display on
|
||
- **OFF** — Display backlight off (but polling continues)
|
||
|
||
## Serial Output Tags
|
||
|
||
The firmware outputs structured tags for the monitor agent:
|
||
|
||
- `[STATE] → DASHBOARD/ALERT/OFF/BOOT` — State transitions
|
||
- `[ADMIN]` — Admin commands received (dashboard, off, alert, silence, status, reboot)
|
||
- `[TOUCH]` — Touch events (x, y, pressed/released)
|
||
- `[ALERT]` — Alert triggered
|
||
|
||
## Reverted Changes Log
|
||
|
||
Track changes that were reverted to avoid flapping:
|
||
|
||
- 2025-02-18: Initially configured LSP via neovim/mason (`.config/nvim/lua/plugins/arduino.lua`) — user clarified they wanted Crush-native LSP config instead
|
||
|
||
## Troubleshooting
|
||
|
||
| Issue | Solution |
|
||
|-------|----------|
|
||
| "Another instance is running" error | Run `mise run kill BOARD=<board>` or `FORCE=1 mise run <task> BOARD=<board>` |
|
||
| Upload fails - port in use | Run `mise run kill` to stop monitor daemon and release port |
|
||
| Build fails - missing libraries | Run `mise run install-libs-shared` then `BOARD=<board> mise run install` |
|
||
| LSP shows errors but build works | Run `mise run gen-compile-commands` to generate compile_commands.json for your BOARD |
|
||
| No serial output | Check baud rate is set to 115200 in serial monitor |
|
||
| State file not updating | Ensure serial output contains `[STATE]` or `[ADMIN]` tags |
|
||
|
||
## Known Fixes
|
||
|
||
- **dashboard/off admin commands reset inactivity timer** (DoorbellLogic.cpp:234,240) — Admin commands like `dashboard` and `off` now reset the inactivity timer so the display doesn't turn off immediately after switching screens.
|
||
|
||
## Documentation Lookup Rule
|
||
|
||
When uncertain about CLI tool flags or argument syntax:
|
||
|
||
1. Run the tool with `-h` or `--help` first
|
||
2. If unclear, search for official documentation matching the tool version
|
||
3. Prefer checking the tool's own help/docs over guessing
|
||
4. For Arduino CLI, check `arduino-cli <command> --help` or official Arduino CLI docs
|
||
|
||
## LSP / IDE Configuration
|
||
|
||
The project uses **clangd** for C++ via the `compile_commands.json` generated by arduino-cli:
|
||
|
||
- `mise run gen-compile-commands` regenerates the compile database (automatically run as part of `compile`)
|
||
- The generated `compile_commands.json` includes all necessary includes, defines, and library paths for your BOARD
|
||
|
||
**Generate compile_commands.json** for accurate IDE diagnostics:
|
||
|
||
```bash
|
||
BOARD=esp32-32e-4 mise run gen-compile-commands
|
||
```
|
||
|
||
**Generate static .crush.json** for a specific board:
|
||
|
||
```bash
|
||
BOARD=esp32-32e-4 mise run gen-crush-config
|
||
```
|
||
|
||
## Hardware Research Log
|
||
|
||
### Hosyond ESP32-32E 4" (320x480) - Planned
|
||
|
||
**Source**: <https://www.lcdwiki.com/4.0inch_ESP32-32E_Display>
|
||
|
||
| Spec | Value |
|
||
|------|-------|
|
||
| Display Controller | ST7796S |
|
||
| Resolution | 320x480 |
|
||
| Touch | XPT2046 (resistive) |
|
||
| Library | TFT_eSPI V2.5.43 (same as 32E) |
|
||
|
||
**GPIO Pinout**:
|
||
|
||
| Function | GPIO |
|
||
|----------|------|
|
||
| LCD CS | 15 |
|
||
| LCD DC | 2 |
|
||
| LCD MOSI | 13 |
|
||
| LCD SCLK | 14 |
|
||
| LCD RST | EN |
|
||
| LCD BL | 27 |
|
||
| Touch CS | 33 |
|
||
| Touch IRQ | 36 |
|
||
|
||
**Quirks**:
|
||
|
||
- SPI pins shared between LCD and touch
|
||
- Touch IRQ on IO36 (input-only) triggers LOW on touch
|
||
- Backlight on IO27 (HIGH = on)
|
||
- Common anode RGB LEDs on IO16, IO17, IO22 (LOW = on)
|
||
<!-- rtk-instructions v2 -->
|
||
# RTK (Rust Token Killer) - Token-Optimized Commands
|
||
|
||
## Golden Rule
|
||
|
||
**Always prefix commands with `rtk`**. If RTK has a dedicated filter, it uses it. If not, it passes through unchanged. This means RTK is always safe to use.
|
||
|
||
**Important**: Even in command chains with `&&`, use `rtk`:
|
||
|
||
```bash
|
||
# ❌ Wrong
|
||
git add . && git commit -m "msg" && git push
|
||
|
||
# ✅ Correct
|
||
rtk git add . && rtk git commit -m "msg" && rtk git push
|
||
```
|
||
|
||
## RTK Commands by Workflow
|
||
|
||
### Build & Compile (80-90% savings)
|
||
|
||
```bash
|
||
rtk cargo build # Cargo build output
|
||
rtk cargo check # Cargo check output
|
||
rtk cargo clippy # Clippy warnings grouped by file (80%)
|
||
rtk tsc # TypeScript errors grouped by file/code (83%)
|
||
rtk lint # ESLint/Biome violations grouped (84%)
|
||
rtk prettier --check # Files needing format only (70%)
|
||
rtk next build # Next.js build with route metrics (87%)
|
||
```
|
||
|
||
### Test (90-99% savings)
|
||
|
||
```bash
|
||
rtk cargo test # Cargo test failures only (90%)
|
||
rtk vitest run # Vitest failures only (99.5%)
|
||
rtk playwright test # Playwright failures only (94%)
|
||
rtk test <cmd> # Generic test wrapper - failures only
|
||
```
|
||
|
||
### Git (59-80% savings)
|
||
|
||
```bash
|
||
rtk git status # Compact status
|
||
rtk git log # Compact log (works with all git flags)
|
||
rtk git diff # Compact diff (80%)
|
||
rtk git show # Compact show (80%)
|
||
rtk git add # Ultra-compact confirmations (59%)
|
||
rtk git commit # Ultra-compact confirmations (59%)
|
||
rtk git push # Ultra-compact confirmations
|
||
rtk git pull # Ultra-compact confirmations
|
||
rtk git branch # Compact branch list
|
||
rtk git fetch # Compact fetch
|
||
rtk git stash # Compact stash
|
||
rtk git worktree # Compact worktree
|
||
```
|
||
|
||
Note: Git passthrough works for ALL subcommands, even those not explicitly listed.
|
||
|
||
### GitHub (26-87% savings)
|
||
|
||
```bash
|
||
rtk gh pr view <num> # Compact PR view (87%)
|
||
rtk gh pr checks # Compact PR checks (79%)
|
||
rtk gh run list # Compact workflow runs (82%)
|
||
rtk gh issue list # Compact issue list (80%)
|
||
rtk gh api # Compact API responses (26%)
|
||
```
|
||
|
||
### JavaScript/TypeScript Tooling (70-90% savings)
|
||
|
||
```bash
|
||
rtk pnpm list # Compact dependency tree (70%)
|
||
rtk pnpm outdated # Compact outdated packages (80%)
|
||
rtk pnpm install # Compact install output (90%)
|
||
rtk npm run <script> # Compact npm script output
|
||
rtk npx <cmd> # Compact npx command output
|
||
rtk prisma # Prisma without ASCII art (88%)
|
||
```
|
||
|
||
### Files & Search (60-75% savings)
|
||
|
||
```bash
|
||
rtk ls <path> # Tree format, compact (65%)
|
||
rtk read <file> # Code reading with filtering (60%)
|
||
rtk grep <pattern> # Search grouped by file (75%)
|
||
rtk find <pattern> # Find grouped by directory (70%)
|
||
```
|
||
|
||
### Analysis & Debug (70-90% savings)
|
||
|
||
```bash
|
||
rtk err <cmd> # Filter errors only from any command
|
||
rtk log <file> # Deduplicated logs with counts
|
||
rtk json <file> # JSON structure without values
|
||
rtk deps # Dependency overview
|
||
rtk env # Environment variables compact
|
||
rtk summary <cmd> # Smart summary of command output
|
||
rtk diff # Ultra-compact diffs
|
||
```
|
||
|
||
### Infrastructure (85% savings)
|
||
|
||
```bash
|
||
rtk docker ps # Compact container list
|
||
rtk docker images # Compact image list
|
||
rtk docker logs <c> # Deduplicated logs
|
||
rtk kubectl get # Compact resource list
|
||
rtk kubectl logs # Deduplicated pod logs
|
||
```
|
||
|
||
### Network (65-70% savings)
|
||
|
||
```bash
|
||
rtk curl <url> # Compact HTTP responses (70%)
|
||
rtk wget <url> # Compact download output (65%)
|
||
```
|
||
|
||
### Meta Commands
|
||
|
||
```bash
|
||
rtk gain # View token savings statistics
|
||
rtk gain --history # View command history with savings
|
||
rtk discover # Analyze Claude Code sessions for missed RTK usage
|
||
rtk proxy <cmd> # Run command without filtering (for debugging)
|
||
rtk init --global # Add RTK to ~/.claude/CLAUDE.md
|
||
```
|
||
|
||
rtk init # Add RTK instructions to CLAUDE.md
|
||
|
||
## Token Savings Overview
|
||
|
||
| Category | Commands | Typical Savings |
|
||
|----------|----------|-----------------|
|
||
| Tests | vitest, playwright, cargo test | 90-99% |
|
||
| Build | next, tsc, lint, prettier | 70-87% |
|
||
| Git | status, log, diff, add, commit | 59-80% |
|
||
| GitHub | gh pr, gh run, gh issue | 26-87% |
|
||
| Package Managers | pnpm, npm, npx | 70-90% |
|
||
| Files | ls, read, grep, find | 60-75% |
|
||
| Infrastructure | docker, kubectl | 85% |
|
||
| Network | curl, wget | 65-70% |
|
||
|
||
Overall average: **60-90% token reduction** on common development operations.
|
||
<!-- /rtk-instructions -->
|