A small command-line filesystem tool that reads and edits any project on Earth — code, configs, docs, data — using the real structure of the file rather than guessing at strings. It's AST-grounded for code (tree-sitter), and structure-aware for everything else. Zero dependencies on any hum infrastructure; it's a single binary you can install anywhere.
You use it to answer "what's in this file?" and to make surgical edits without touching anything you didn't mean to touch.
cargo install runuzor build it yourself:
make build # target/release/runuz
make install # copies it into ~/.local/binThat gives you a program called runuz. If your terminal can't find it,
add this to your ~/.zshrc or ~/.bashrc:
export PATH="$HOME/.local/bin:$PATH"Check which build you're on with runuz --version.
runuz has two halves, and each one is dead simple:
- Reading.
runuz readopens a file and gives you a symbol outline: the functions, classes, structs, and fields inside it, one line each. Point it at a directory or a glob and it inventories what's there. Ask for a specific symbol, a fuzzy name, or a regex over the content. - Editing.
runuz create / replace / insert_before / insert_after / deletemake AST-grounded, symbol-scoped edits. You say which symbol and what new source, and runuz splices exactly that byte range — not a text search-and-replace that can hit the wrong spot. Non-code files (.env, TOML, JSON, markdown, READMEs) get linguistic-scope edits:word,phrase,sentence,paragraph.
Every write is re-parsed before it lands. A broken edit is rejected and the original file is left untouched.
# A code file: get its symbol outline
runuz read --file-path src/main.rs
# Just one symbol
runuz read --file-path src/main.rs --symbol main
# A fuzzy name match
runuz read --file-path src/main.rs --query auth
# A regex over the content
runuz read --file-path src/ --pattern 'TODO'read decides the framing itself: a file gets an outline, a directory or
glob gets an inventory, configs and docs get an anchor outline. It skips
junk directories (node_modules, .git, target, ...) so a read('/')
doesn't explode.
All edits are symbol-scoped — you name the symbol, runuz swaps its exact byte range:
# Create a new file (fails if it already exists)
runuz create --file-path src/main.rs --new-source 'fn main() {}'
# Replace a symbol's whole body
runuz replace --file-path src/main.rs --symbol main \
--new-source 'fn main() { run(); }'
# Splice a helper right before / after a symbol
runuz insert_before --file-path src/main.rs --symbol main \
--new-source 'fn helper() {}'
runuz insert_after --file-path src/main.rs --symbol main \
--new-source 'fn helper() {}'
# Drop a symbol entirely
runuz delete --file-path src/main.rs --symbol helper
# Or replace / delete several symbols in one atomic write
runuz replace --file-path src/main.rs --symbols main,helper \
--new-source 'fn main() { run(); }'The top-of-file import block is addressable as the synthetic symbol
imports. Symbols nest with dots (Class.method), and you can walk into
sub-parts of a symbol (main.body, main.loop) — the full vocabulary is
in grammar.md.
Omit --symbol on replace to rewrite the whole file. write does a
whole-file create or overwrite, auto-routing by extension.
For non-code files the scopes are linguistic — you name the smallest unit and replace it:
# Swap one word
runuz word --file-path .env DATABASE_URL --replace 'postgres://new/db'
# Swap a phrase — structure-aware: JSON keys/values, env vars,
# markdown headings, TOML sections
runuz phrase --file-path README.md runuz --replace runuz2
# Sentence = the single line holding the text
runuz sentence --file-path notes.txt 'fix the bug' --replace 'done'
# Paragraph = the whole blank-line block
runuz paragraph --file-path notes.txt 'old paragraph' --replace 'new'Omit --replace to delete the resolved scope. JSON files are re-validated
as JSON after the edit; a broken result is rejected.
Add --json anywhere and runuz prints {is_error, output, title, metadata} instead of text.
AST-backed today: rs, py/pyi, go, js/jsx/mjs/cjs,
ts, tsx. Everything else is handled by the structure-aware
non-code path. bash is intentionally not part of the standalone CLI.
runuz was extracted from hum's filesystem-forager surface. The standalone form here is the installable-anywhere version of the same tool surface.
MIT. See LICENSE.