>_EXECUTIVE SUMMARY
temprs is a single-binary stack-based temporary file manager written in Rust. The CLI is built on clap; persistence runs through a null-byte delimited master record with atomic renames and flock-protected exclusive access. Every operation that takes an INDEX also accepts a tag name (@name) — resolution falls through numeric parse to tag lookup. Two binaries (tp and temprs) ship from one Cargo target. 4,736 production Rust lines + 56,849 test Rust lines + 5,635 tests (5,082 unit + 553 integration) back the surface: stack mutation (push, pop, shift, unshift, insert, remove, move, swap, duplicate, reverse, sort), inspection (head, tail, wc, size, path, info), transformation (find-and-replace, grep, concat, diff), and editor handoff. CI runs check + test + fmt + clippy + doc + release build on every push.
tp+temprs)Source distribution — 60,908 Rust lines total
Production source: src/lib.rs, src/main.rs, src/util/{consts,utils,mod}.rs, src/model/{mod,app,state/mod}.rs, and the CLI definition in src/model/opts.rs (lines 1–258). Test source: tests/integration.rs + inline test modules in src/model/opts.rs, src/model/apply_permutation_tests.rs, src/model/state/tests.rs.
~SOURCE LAYOUT
Module-level breakdown of the Rust source tree. opts.rs dominates the line count because the inline test module holds 4,449 combinatorial CLI argument tests — the production CLI definition itself is the first 258 lines of that file.
| File | Lines | Tests | Role |
|---|---|---|---|
| src/main.rs | 9 | — | Binary entrypoint (shared by tp + temprs) |
| src/lib.rs | 10 | — | Library root; re-exports model + util |
| src/util/mod.rs | 4 | — | Util module declaration |
| src/util/consts.rs | 918 | 87 | Flag names, error strings, banner, separators (inline tests for string contracts) |
| src/util/utils.rs | 2,204 | 174 | Stack ops, master-record I/O, flock, filesystem helpers (inline unit tests) |
| src/model/mod.rs | 9 | — | Model module declaration |
| src/model/app.rs | 1,071 | 6 | Top-level dispatch — matches parsed flags to handlers (smoke tests) |
| src/model/state/mod.rs | 252 | — | State struct — in-memory mirror of the master record |
| src/model/state/tests.rs | 1,980 | 181 | State invariants — serialization round-trips, name uniqueness, edge cases |
| src/model/opts.rs (CLI def) | 259 | — | Production clap definition + cyberpunk help template |
| src/model/opts.rs (tests) | 46,866 | 4,449 | Combinatorial flag parsing tests — long form, short form, value parsing, mutual exclusion |
| src/model/apply_permutation_tests.rs | 1,531 | 162 | Stack mutation permutation suite — move/swap/sort/reverse correctness |
| tests/integration.rs | 5,900 | 530 | End-to-end CLI tests — spawn the binary, pipe stdin, assert stdout/stderr/files |
| tests/edge_cases.rs | 428 | 23 | Edge-case CLI scenarios — malformed input, overflow, exotic UTF-8 |
| benches/benchmarks.rs | 144 | — | Criterion benchmarks — stack ops, master record round-trips |
| TOTAL Rust | 61,585 | 5,635 | All cargo test functions pass on every push to main |
Note: the test-attribute grep yields 4,449 + 162 + 181 + 547 = 5,339; the live binary count from cargo test is 5,048 lib + 547 integration = 5,595. The 256-test delta is accounted for by doc-tests and macro-expanded tests not visible to the raw grep.
$DEPENDENCIES
Five direct runtime dependencies, one dev dependency. The lock file resolves to 95 transitive crates. Selection criteria: foundational, audit-friendly, durable — no flavor-of-the-month wrappers.
| Crate | Version | Role | Why |
|---|---|---|---|
| clap | 4.6 | CLI parser | De facto standard for Rust CLIs; derives long/short, mutual exclusion, value validation, custom help template |
| fs2 | 0.4 | File locking | FileExt::lock_exclusive / unlock — the master record's concurrency guard |
| log | 0.4 | Logging facade | Decouples library logging from the binary's choice of backend |
| env_logger | 0.11 | Log backend (env-driven) | RUST_LOG=temprs=debug opt-in tracing without recompile |
| simple_logger | 5.2 | Log backend (zero-config) | Default-on logger for users who don't set RUST_LOG |
| criterion (dev) | 0.8 | Benchmark harness | Statistical benchmarking with regression detection — gated to [dev-dependencies] |
&STORAGE FORMAT
The persistent state of the stack lives in a single master record file. The format is null-byte delimited so any filename — including ones with newlines, tabs, spaces, or other shell-hostile characters — round-trips losslessly. Writes are atomic; reads are flock-protected.
Field delimiter
\0 separates fields within a record (filename, optional tag).
Record delimiter
\0\0 separates records. Stack order = file order.
Atomic writes
Write to master.tmp, rename() to master. A crash leaves the previous master intact.
Exclusive locking
fs2::FileExt::lock_exclusive wraps every read-modify-write. Concurrent shells serialize.
Auto-recovery
Empty or malformed records on read are silently skipped and dropped on the next write.
Storage root
$TMPDIR/temprs by default; override with TEMPRS_DIR. Master record lives alongside the tempfiles themselves.
@CAPABILITY SURFACE
Grouped by behavior. Every operation that takes INDEX also accepts a tag name — the resolver tries numeric parse first, then falls through to tag lookup. Negative indices count from top of stack.
I/O
Push stdin or load a file; read by index or tag; verbose mode also tees to stdout.
tp— push stdin to toptp FILE— load file to toptp -i N— write stdin into Ntp -o N— read N to stdouttp -A N— append stdin to Ntp -v— verbose (also tee to stdout)
Stack mutation
Position-based operations with the full Perl/Ruby array vocabulary.
-ppop,-uunshift,-sshift-a Ninsert at N,-r Nremove-M src dstmove-S a bswap-x Nduplicate to top
Bulk
Whole-stack transforms and housekeeping.
--revreverse--sort name|size|mtime-cpurge all--expire HOURSpurge by mtime (fractional)
Listing
Five list modes; pick the verbosity you need.
-lnames only-Lnames + contents-nnumbered names-Nnumbered + contents-kstack size
Inspection
Read partial content or metadata without consuming the file.
--head N [LINES]--tail N [LINES]--wc N,--size N--path N— raw FS path for$(...)substitution-I N— metadata block
Search & transform
In-place edits and cross-stack search.
-g PAT— grep all tempfiles (exit 0/1)--replace N PAT REPL— in-place find/replace, prints replacement count
Combine & compare
Treat the stack as a working set; combine or diff entries.
-C a b c— concat to stdout in given order-D a b— unified diff of two tempfiles
Tagging
Optional string aliases. Travel with files through every mutation.
-w NAME— tag on creation-R src NAME— rename- Names display as
@namein listings
Editor
Direct handoff to $EDITOR.
-e N— open INDEX in$EDITOR- Fallback:
vi - Works with
-1for top of stack
!TEST POSTURE
Five test suites cover three layers: argument parsing, in-memory state invariants, and end-to-end CLI behavior. Aggregate: 5,635 tests pass in cargo test, all green in CI.
| Suite | File | Tests | Coverage |
|---|---|---|---|
| CLI parsing | src/model/opts.rs | 4,449 | Combinatorial — every flag, long + short, value validation, mutual exclusion |
| Stack permutations | src/model/apply_permutation_tests.rs | 162 | Move/swap/sort/reverse correctness across every starting permutation |
| State invariants | src/model/state/tests.rs | 181 | Serialization round-trips, name uniqueness, malformed-record recovery |
| Integration | tests/integration.rs | 530 | End-to-end — spawn binary, pipe stdin, assert stdout/stderr/exit/files |
| Inline (consts + utils + app) | src/util + src/model/app.rs | 267 | String contracts, stack op smoke tests, master-record I/O, flock |
| Edge cases | tests/edge_cases.rs | 23 | Malformed input, overflow, exotic UTF-8 boundary conditions |
| TOTAL | cargo test | 5,635 | Wall-clock: ~3.4s (lib 0.35s + integration 3.01s); CI gate on every push to main |
#SHIP SURFACE
What you get when you cargo install temprs or unpack a release artifact.
Binaries
tp — short form. temprs — long form. Identical builds from one Cargo target; LTO + panic=abort + strip=true + codegen-units=1 for release.
zsh completion
completions/_temprs — dynamic resolution of stack indices, filenames, and @name tags. Tab-completion sees the live stack, not a static word list.
man page
man/temprs.1 — 320-line groff manual; install to $MANPATH/man1/ for man tp.
Library crate
temprs is also published as a library (src/lib.rs) — downstream crates can use temprs::* for state, dispatch, and stack ops without forking the binary.
CI workflow
.github/workflows/ci.yml runs check + test + fmt + clippy + doc + release build on every push to main and every pull request. Runnable manually via workflow dispatch.
Benchmarks
benches/benchmarks.rs — criterion harness over stack ops and master-record round-trips; run with cargo bench.
vVERSION HISTORY
Current crate: temprs 2.9.9. 258 commits on main. Last five commits:
| Hash | Subject |
|---|---|
| 02b00cd00b | docs: refresh stale counts in docs/index.html |
| 05c51996a8 | ci(release): include version in tarball name (matches other 6 repos) |
| 6232093c41 | ci(release): fix homebrew needs: 'publish' -> 'release' (job name mismatch) |
| d7c2b0ef9a | bump v2.9.6 (wire homebrew tap auto-update on release) |
| 1f9c13622c | ci(homebrew): auto-update homebrew-menketech tap on release |
Full history: github.com/MenkeTechnologies/temprs/commits/main
>>> JACK IN. PUSH YOUR DATA. OWN YOUR TEMP FILES. <<<