| name | vx-agent-workflow |
| description | Token-efficient command execution patterns for AI agents using vx. Use when running builds, tests, linting, GitHub operations, or any command that produces verbose output. Teaches agents to filter output cross-platform using vx-managed tools (vx rg, vx jq) instead of platform-specific syntax (Select-String, grep, findstr). Includes token measurement, savings tracking, and deep recipes for cargo, gh, pytest, and more. |
VX Agent Workflow — Token-Efficient Command Execution
Core principle: Use vx rg as the universal cross-platform filter. Never use
platform-specific tools like Select-String (PowerShell), grep (Unix), or
findstr (cmd). One command, every OS.
Why This Matters
AI agents pay per-token for both input and output. A full cargo test run can
produce 500+ lines when you only need the 5 lines showing failures. Agents that
dump raw output waste 95% of their context window on noise.
The vx advantage: vx auto-installs rg (ripgrep), jq, fd, and other
filtering tools on every platform. Use them instead of shell-specific builtins.
Token Savings Per Operation (Measured)
Based on medium-sized Rust/Python/TypeScript projects:
| Operation | Frequency/30min | Raw tokens | Filtered | Savings |
|---|
vx cargo test | 5x | ~25,000 | ~2,500 | -90% |
vx cargo build | 5x | ~15,000 | ~1,500 | -90% |
vx cargo clippy | 3x | ~8,000 | ~800 | -90% |
vx uv run pytest | 4x | ~8,000 | ~800 | -90% |
vx gh pr view | 5x | ~3,000 | ~300 | -90% |
vx gh run view --log | 3x | ~30,000 | ~1,500 | -95% |
vx git status | 10x | ~3,000 | ~600 | -80% |
vx git diff | 5x | ~10,000 | ~2,500 | -75% |
vx npm test | 5x | ~20,000 | ~2,000 | -90% |
vx just quick | 3x | ~40,000 | ~2,000 | -95% |
| Session total | | ~162,000 | ~12,500 | -92% |
The Universal Filter Pattern
vx <command> 2>&1 | vx rg "<pattern>"
This works identically on:
- Windows PowerShell 5.1+ / 7+ (pwsh)
- Windows cmd.exe
- Linux Bash/Zsh
- macOS Bash/Zsh
Why NOT platform-specific tools
| Platform | Native filter | Problem |
|---|
| PowerShell | Select-String -Pattern "..." | Select-Object -Last 30 | Verbose syntax, outputs objects not text, breaks on Unix |
| Bash/Zsh | grep -E "..." | tail -30 | Not available on Windows without WSL |
| cmd.exe | findstr /R "..." | Limited regex, no tail equivalent, no context lines |
With vx, one line replaces all of them:
vx <command> 2>&1 | vx rg -m 30 "pattern"
Deep Recipe: vx cargo (Rust Build & Test)
Build — Progressive Disclosure
vx cargo build 2>&1 && echo "OK" || echo "FAIL"
vx cargo build 2>&1 | vx rg -c "^error"
vx cargo build 2>&1 | vx rg "^error\["
vx cargo build 2>&1 | vx rg "^error|^\s*--> "
vx cargo build 2>&1 | vx rg -B 1 -A 3 "^error\["
Test — Optimal Patterns
vx cargo test 2>&1 | vx rg "^test result:"
vx cargo test 2>&1 | vx rg "FAILED|panicked|thread .+ panicked|assertion"
vx cargo test -p vx-cli 2>&1 | vx rg "test result:|FAILED"
vx cargo test -p vx-cli test_parse_args 2>&1 | vx rg "test result:|FAILED|panicked"
vx cargo test -- -Z unstable-options --format json 2>&1 | vx jq -c 'select(.event == "failed")'
Clippy — Warnings & Errors
vx cargo clippy 2>&1 | vx rg -c "^(warning|error)\["
vx cargo clippy 2>&1 | vx rg -o "(warning|error)\[\w+\]" | sort | uniq -c
vx cargo clippy 2>&1 | vx rg "^(warning|error)\[|^\s*--> "
vx cargo clippy 2>&1 | vx rg "unused_variable|dead_code"
Build + Test Combined (vx just quick)
vx just quick 2>&1 | vx rg "^(error|warning)\[|test result:|FAILED|Finished|could not compile"
vx just quick 2>&1 | vx rg -m 5 "Finished|test result: ok|All checks passed"
Tee Pattern — Save Full Output for Failure Recovery
When a command fails, save full output to a file so you can dig deeper without
re-running (inspired by rtk's tee feature):
vx cargo test 2>&1 | vx tee .vx-last-output.log | vx rg "FAILED|error|panicked"
vx rg -C 5 "FAILED" .vx-last-output.log
vx cargo test > .vx-last-output.log 2>&1; vx rg "test result:|FAILED" .vx-last-output.log
Deep Recipe: vx gh (GitHub CLI)
PR Operations — JSON Field Selection
The single most effective token-saving technique for gh is --json with field selection:
vx gh pr view 123
vx gh pr view 123 --json title,state,mergeable,reviewDecision,headRefName
vx gh pr view 123 --json files --jq '.files[].path'
vx gh pr list --json number,title,state,headRefName --jq '.[] | "\(.number) \(.state) \(.title)"'
CI Checks — Status Only
vx gh pr checks 123
vx gh pr checks 123 --json name,state,conclusion --jq '.[] | "\(.name): \(.conclusion)"'
vx gh pr checks 123 --json name,state,conclusion --jq '.[] | select(.conclusion == "FAILURE") | .name'
vx gh pr checks 123 --json conclusion --jq 'all(.conclusion == "SUCCESS")'
CI Run Logs — Filtered
CI logs are the #1 token-waster (10,000-100,000+ tokens). Always filter:
vx gh run view 789 --log 2>&1 | vx rg -m 50 "^error|FAILED|panic|fatal|Error:"
vx gh run view 789 --log-failed 2>&1 | vx rg -m 50 "error|FAILED|panic"
vx gh run view 789 --json conclusion,status --jq '.conclusion'
vx gh run list --json databaseId,status,conclusion,headBranch -L 5 --jq '.[] | "\(.databaseId) \(.conclusion) \(.headBranch)"'
Issues — Selective Fields
vx gh issue view 456 --json title,state,labels,body --jq '{title,state,labels: [.labels[].name]}'
vx gh issue list --json number,title,state -L 10 --jq '.[] | "\(.number) \(.title)"'
API Calls — Always Use --jq
vx gh api repos/{owner}/{repo}/actions/runs --jq '.workflow_runs[:3] | .[] | {id,conclusion,head_branch}'
vx gh api repos/{owner}/{repo}/pulls/123/files --jq '.[].filename'
vx gh api repos/{owner}/{repo}/commits/{sha}/status --jq '.state'
Deep Recipe: Python Testing (pytest)
Basic Patterns
vx uv run pytest 2>&1 | vx rg "passed|failed|error" | vx rg "==="
vx uv run pytest 2>&1 | vx rg "^FAILED "
vx uv run pytest --tb=no -q 2>&1
vx uv run pytest --tb=short 2>&1 | vx rg -A 5 "^FAILED|^E "
vx uv run pytest -k "test_parse" --tb=short -q 2>&1
pytest Native Flags That Save Tokens
Use pytest's own flags before piping — they reduce output at source:
vx uv run pytest --tb=no -q 2>&1
vx uv run pytest --tb=line 2>&1
vx uv run pytest --tb=short 2>&1
vx uv run pytest -q 2>&1
vx uv run pytest --no-header -q 2>&1
vx uv run pytest -x --tb=short 2>&1
vx uv run pytest --no-header --tb=line -q 2>&1
pytest JSON Output
vx uv run pytest --json-report --json-report-file=- 2>&1 | vx jq '{summary: .summary, failed: [.tests[] | select(.outcome == "failed") | .nodeid]}'
vx uv run pytest --junitxml=- 2>&1 | vx rg "failures=|errors="
Coverage — Summary Only
vx uv run pytest --cov --cov-report=term-missing 2>&1 | vx rg "^TOTAL|^FAILED|passed"
vx uv run pytest --cov 2>&1 | vx rg "^TOTAL" | vx rg -o "\d+%"
Deep Recipe: vx git (Version Control)
Progressive Disclosure for Diffs
vx git diff --quiet && echo "clean" || echo "dirty"
vx git diff --name-only
vx git diff --stat
vx git diff -- src/specific_file.rs
vx git diff
Status — Compact Forms
vx git status --short --branch
vx git status --short | vx rg -c "."
Log — Bounded
vx git log --oneline -10
vx git log --oneline --stat -3
vx git diff --name-only origin/main...HEAD
vx git log --oneline origin/main...HEAD
vx Built-in Compact Mode (--compact / -u)
vx has a built-in RTK-style compact mode that automatically filters subprocess
output without manual piping. This is the easiest way to save tokens:
vx --compact cargo test
vx --compact cargo build
vx --compact git status
vx --compact gh pr view 123
vx -u cargo test
vx --compact --filter-level light cargo test
vx --compact --filter-level normal cargo test
vx --compact --filter-level aggressive cargo test
export VX_OUTPUT=compact
vx cargo test
vx cargo build
vx git status
Compact vs Manual Pipe — When to Use Which
| Approach | Use when | Example |
|---|
vx --compact <cmd> | Quick runs, standard filters are good enough | vx --compact cargo test |
<cmd> 2>&1 | vx rg "pattern" | Need custom filter pattern | vx cargo test 2>&1 | vx rg "my_test|FAILED" |
--json / --jq | Command has native JSON support | vx gh pr view N --json title,state |
The --compact Mode Tracks Token Savings Automatically
Every command run with --compact, --output-format toon, or --json is
automatically measured. Check cumulative savings with:
vx metrics tokens
vx metrics tokens --json
Token Measurement & Statistics
Built-in: vx metrics tokens
vx has built-in token savings tracking (similar to rtk gain). Every time you
use --output-format toon, --compact, or --json, vx automatically records
baseline vs actual token counts. Query the data with:
vx metrics tokens
vx metrics tokens --json
vx metrics tokens --last 20
How Tracking Works
vx records a TokenSavingsRecord for every command that uses a structured output
format (toon, json, compact). Each record captures:
| Field | Description |
|---|
baseline_tokens | Estimated tokens if output were unformatted text |
actual_tokens | Actual tokens in the structured/filtered output |
token_delta | Positive = tokens saved |
savings_ratio | Fraction saved (0.0–1.0) |
Token estimation: 1 token ≈ 4 UTF-8 bytes (heuristic, matches GPT/Claude tokenizers within ~10%).
Enabling Token Tracking
Token savings are tracked automatically when you use vx's built-in output modes:
vx list --output-format toon
vx check --json
vx --compact cargo test
export VX_OUTPUT=toon
Manual Measurement (for piped commands)
For commands piped through vx rg, track savings manually:
vx cargo test > /tmp/vx-raw.log 2>&1
vx rg "test result:|FAILED" /tmp/vx-raw.log > /tmp/vx-filtered.log
echo "Raw: $(wc -c < /tmp/vx-raw.log) bytes → Filtered: $(wc -c < /tmp/vx-filtered.log) bytes"
echo "Saved: $(echo "scale=1; 100 - $(vx cargo test 2>&1 | vx rg 'test result:|FAILED' | wc -c) * 100 / $(vx cargo test 2>&1 | wc -c)" | bc)%"
AI Summary (For Agent Introspection)
vx metrics --json
HTML Report (For Human Review)
vx metrics --html report.html
Expected Savings by Command Category
| Category | Raw output | Optimal filter | Tokens saved | Technique |
|---|
| Build (cargo/go/tsc) | 5K-20K | 50-500 | 90-99% | vx rg "^error" |
| Test (cargo/pytest/jest) | 2K-25K | 50-200 | 90-99% | vx rg "test result:|FAILED" |
| Lint (clippy/ruff/eslint) | 2K-10K | 100-500 | 85-95% | vx rg "^(error|warning)\[" |
| Git operations | 1K-10K | 100-500 | 75-90% | --stat, --name-only, --short |
| GitHub CLI | 500-5K | 50-200 | 80-95% | --json field1,field2 --jq |
| CI logs | 10K-100K | 200-1000 | 95-99% | --log-failed | vx rg -m 50 |
| File listing | 500-5K | 50-200 | 80-95% | vx fd with type filters |
Advanced Patterns
The Tee-on-Failure Pattern
Save full output only when commands fail (zero cost on success):
vx cargo test 2>&1 | vx rg "test result:|FAILED|panicked"; if [ $? -ne 0 ]; then vx cargo test 2>&1 > .vx-debug.log && echo "[full log: .vx-debug.log]"; fi
vx cargo test > .vx-last.log 2>&1; EXIT=$?; vx rg "test result:|FAILED" .vx-last.log; if [ $EXIT -ne 0 ]; then echo "[debug: .vx-last.log]"; fi
Deduplication — Collapse Repeated Lines
vx cargo clippy 2>&1 | vx rg "^warning\[" | sort | uniq -c | sort -rn
Cascading Filters — Cheap to Expensive
Always start with the cheapest check and only expand if needed:
vx cargo test 2>&1 > /dev/null && echo "PASS" || echo "FAIL"
vx rg -c "FAILED" .vx-last.log
vx rg "FAILED" .vx-last.log
vx rg -B 2 -A 5 "FAILED" .vx-last.log
vx rg -A 30 "failures:" .vx-last.log
JSON Projection for Structured Commands
Many tools support JSON output natively — use it with vx jq:
vx cargo metadata --format-version=1 2>&1 | vx jq '[.workspace_members[]]'
vx npm outdated --json 2>&1 | vx jq 'to_entries | .[] | "\(.key): \(.value.current) → \(.value.latest)"'
vx uv run pytest --json-report --json-report-file=- 2>&1 | vx jq '.summary'
Platform-Specific Notes
Stderr Redirection (2>&1)
The 2>&1 syntax works in all shells (PowerShell, Bash, cmd). It merges stderr
into stdout so vx rg can filter both streams. Always include it for build/test
commands that may emit errors on stderr.
PowerShell Pipe Encoding
PowerShell may convert pipe output to UTF-16. If vx rg shows garbled output:
$env:PYTHONIOENCODING="utf-8"
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
Or use vx's subprocess environment which handles encoding automatically.
Long Commands on Windows
Windows cmd.exe has a ~8191 character limit. For complex filter patterns:
echo "error|FAILED|panicked|could not compile" > .vx-filter.txt
vx cargo test 2>&1 | vx rg -f .vx-filter.txt
Decision Tree for Agents
Need to run a command?
│
├─ Is this a vx native command (list, check, versions)?
│ └─ Use --json or --output-format toon
│
├─ Is this `vx gh` (GitHub CLI)?
│ └─ ALWAYS use --json field1,field2 --jq 'projection'
│
├─ Is this a test command?
│ ├─ cargo test → vx cargo test -p <crate> 2>&1 | vx rg "test result:|FAILED"
│ ├─ pytest → vx uv run pytest --no-header --tb=line -q 2>&1
│ ├─ jest → vx npm test 2>&1 | vx rg "Tests:|FAIL"
│ └─ go test → vx go test ./... 2>&1 | vx rg "^(ok|FAIL)"
│
├─ Is this a build command?
│ └─ vx cargo build 2>&1 | vx rg "^error|could not compile"
│
├─ Is this a lint command?
│ └─ vx cargo clippy 2>&1 | vx rg "^(error|warning)\["
│
├─ Will output be small (<20 lines)?
│ └─ Run directly: vx <command>
│
├─ Will output be large or unknown?
│ ├─ Just pass/fail? → && echo "PASS" || echo "FAIL"
│ ├─ Error details? → 2>&1 | vx rg "error|FAILED|panic"
│ ├─ Count only? → 2>&1 | vx rg -c "pattern"
│ └─ Context? → 2>&1 | vx rg -C 3 "error|FAILED"
│
└─ CI log?
└─ vx gh run view N --log-failed 2>&1 | vx rg -m 50 "error|FAIL"
Anti-Patterns
vx just test 2>&1 | Select-String -Pattern "FAILED"
vx just test 2>&1 | grep -E "FAILED"
vx just test 2>&1 | findstr /R "FAILED"
vx just test 2>&1 | vx rg "FAILED"
vx cargo test
vx gh run view 789 --log
vx gh pr view 123
vx uv run pytest
vx cargo test 2>&1 | vx rg "test result:|FAILED"
vx gh run view 789 --log-failed 2>&1 | vx rg -m 30 "error"
vx gh pr view 123 --json title,state,mergeable
vx uv run pytest --no-header --tb=line -q 2>&1
vx uv run pytest --cov
vx npm list
vx uv run pytest --cov 2>&1 | vx rg "^TOTAL"
vx npm list --depth=0 2>&1
if ($IsWindows) { ... | Select-String ... } else { ... | grep ... }
vx <cmd> 2>&1 | vx rg "pattern"
Quick Reference Card
| Task | Token-efficient command | ~Tokens |
|---|
| Rust test pass/fail | vx cargo test 2>&1 && echo OK || echo FAIL | 2 |
| Rust test summary | vx cargo test 2>&1 | vx rg "test result:" | 10 |
| Rust test failures | vx cargo test 2>&1 | vx rg "FAILED|panicked" | 20-100 |
| Rust build errors | vx cargo build 2>&1 | vx rg "^error" | 20-200 |
| Clippy count | vx cargo clippy 2>&1 | vx rg -c "^(error|warning)\[" | 2 |
| Clippy issues | vx cargo clippy 2>&1 | vx rg "^(error|warning)\[" | 50-200 |
| pytest summary | vx uv run pytest --no-header --tb=line -q 2>&1 | 10-50 |
| pytest failures | vx uv run pytest --tb=short -q 2>&1 | vx rg "FAILED|^E " | 50-200 |
| Node test summary | vx npm test 2>&1 | vx rg "Tests:|FAIL" | 10-50 |
| Go test summary | vx go test ./... 2>&1 | vx rg "^(ok|FAIL)" | 10-50 |
| Just quick-check | vx just quick 2>&1 | vx rg "error|FAILED|Finished" | 20-100 |
| Git changes | vx git diff --name-only | 10-30 |
| Git status | vx git status --short --branch | 10-50 |
| PR status | vx gh pr view N --json title,state,mergeable | 30-50 |
| PR files | vx gh pr view N --json files --jq '.files[].path' | 20-50 |
| CI status | vx gh pr checks N --json name,conclusion --jq '...' | 30-100 |
| CI errors | vx gh run view N --log-failed 2>&1 | vx rg -m 30 "error" | 100-500 |
| Search code | vx rg -n -m 20 "pattern" src/ | 50-200 |
| Find files | vx fd "pattern" --type f | 10-50 |