Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/benchmarks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ concurrency:

jobs:
tools:
name: fetch + games + lazybox + science + screensaver
name: fetch + games + lazybox + science + screensaver + apps
runs-on: ubuntu-latest
timeout-minutes: 15

Expand Down
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ path = "src/bin/science.rs"
name = "screensaver"
path = "src/bin/screensaver.rs"

[[bin]]
name = "apps"
path = "src/bin/apps.rs"

[dependencies]
crossterm = { version = "=0.29.0", default-features = false, features = ["events", "windows"] }

Expand Down
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

Small native terminal tools with one job each:

- `apps` reads text, explores CSV/TSV, presents Markdown, paints text canvases, and runs timers.
- `fetch` shows a fast system and CPU overview with styled, plain, or JSON output.
- `games` is a native clean-room terminal arcade with eleven complete game modes.
- `lazybox` is one direct dashboard for Docker containers, Apple containers, and Slurm jobs.
Expand Down Expand Up @@ -31,6 +32,7 @@ Rust 1.97.1 is pinned for builds.

```sh
cargo build --release --locked
./target/release/apps
./target/release/fetch
./target/release/games
./target/release/lazybox
Expand All @@ -41,6 +43,10 @@ cargo build --release --locked
Useful non-interactive forms:

```sh
apps snapshot read notes.md --find TODO --json
apps snapshot table data.csv --limit 25 --plain
apps snapshot slides talk.md --page 2
apps snapshot timer --seconds 1500 --elapsed 60 --json
fetch --plain
fetch --json
games list --json
Expand Down Expand Up @@ -106,6 +112,20 @@ Interactive output updates only changed terminal rows, supports resize and
`NO_COLOR`, and can be slowed to one frame per second with `--fps 1`. Plain and
JSON snapshots provide a non-animated alternative.

## Native apps

`apps` owns five local workflows in one binary: bounded UTF-8 reading and
search, quoted CSV/TSV parsing, Markdown slide navigation, text-canvas painting,
and a monotonic countdown timer. Every file input is opened once and capped at
32 MiB. Tables are additionally capped at 100,000 rows, 256 columns, and two
million cells. Paint output uses a completed temporary file and an atomic
no-overwrite hard link, so it cannot replace an existing file.

The binary does not bundle or launch MuPDF, Firefox, a browser engine, a
Wayland compositor, a PTY server, TLS, weather/speed services, plugins, or
copied upstream code and assets. Pipe already-fetched text through `-` when a
local snapshot is enough.

## Scope

`fetch` has detailed native collection on macOS and Linux and a smaller
Expand All @@ -120,6 +140,8 @@ The [science benchmark](benches/science.md) measures an offline orbit snapshot
and binary size; file parsing latency remains input-dependent.
The [screensaver benchmark](benches/screensaver.md) measures one deterministic
generated snapshot and binary size; Git and GIF latency remains input-dependent.
The [apps benchmark](benches/apps.md) measures one deterministic timer snapshot
and binary size; file parsing and interactive latency remain input-dependent.

## Project

Expand Down
30 changes: 30 additions & 0 deletions benches/apps.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Apps benchmark

The benchmark measures `apps snapshot timer --seconds 1500 --elapsed 60
--plain`, a deterministic local formatting path with no file, terminal,
network, cache, subprocess, or clock dependency. File and interactive latency
depends on input size and is not used as a general startup claim.

Measured 2026-08-18 on Darwin 25.5.0 ARM64 with Rust 1.97.1 and Hyperfine
1.20.0, using 100 runs after 20 warmups:

| Command | Mean ± standard deviation | Range | Stripped binary |
| --- | ---: | ---: | ---: |
| `apps snapshot timer --seconds 1500 --elapsed 60 --plain` | 1.6 ± 0.1 ms | 1.4–1.9 ms | 438,752 bytes |

This is an owned startup measurement, not a claim that a timer snapshot is
equivalent to an upstream PDF renderer, browser, compositor, or network test.

The macOS ARM64 wheel is 1,329,747 bytes for all six binaries, package
metadata, project and dependency licenses, and the CycloneDX SBOM.

Run the same benchmark used by CI:

```sh
cargo build --release --locked
RUNS=100 WARMUP=20 bash benches/run.sh
```

Hyperfine JSON, Markdown, and stripped binary sizes are written below ignored
`target/benchmarks/`. Record a same-host fixture, byte/row/cell count, median,
and spread before making a parser-performance claim.
8 changes: 6 additions & 2 deletions benches/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ games="$project/target/release/games"
lazybox="$project/target/release/lazybox"
science="$project/target/release/science"
screensaver="$project/target/release/screensaver"
apps="$project/target/release/apps"

command -v hyperfine >/dev/null 2>&1 || {
echo "benchmarks: install hyperfine 1.20.0" >&2
exit 127
}
for binary in "$fetch" "$games" "$lazybox" "$science" "$screensaver"; do
for binary in "$fetch" "$games" "$lazybox" "$science" "$screensaver" "$apps"; do
[[ -x "$binary" ]] || {
echo "benchmarks: run cargo build --release --locked first" >&2
exit 2
Expand All @@ -31,13 +32,15 @@ hyperfine --shell=none --warmup "$warmup" --runs "$runs" \
--command-name games "$games list --plain" \
--command-name lazybox "$lazybox --version" \
--command-name science "$science snapshot orbit --plain" \
--command-name screensaver "$screensaver snapshot rain --seed 1 --frame 24 --plain"
--command-name screensaver "$screensaver snapshot rain --seed 1 --frame 24 --plain" \
--command-name apps "$apps snapshot timer --seconds 1500 --elapsed 60 --plain"

fetch_size=$(wc -c < "$fetch" | tr -d ' ')
games_size=$(wc -c < "$games" | tr -d ' ')
lazybox_size=$(wc -c < "$lazybox" | tr -d ' ')
science_size=$(wc -c < "$science" | tr -d ' ')
screensaver_size=$(wc -c < "$screensaver" | tr -d ' ')
apps_size=$(wc -c < "$apps" | tr -d ' ')
{
echo "## Keys Tools benchmarks"
echo
Expand All @@ -54,6 +57,7 @@ screensaver_size=$(wc -c < "$screensaver" | tr -d ' ')
echo "| lazybox | $lazybox_size |"
echo "| science | $science_size |"
echo "| screensaver | $screensaver_size |"
echo "| apps | $apps_size |"
echo
echo "Hyperfine $runs runs after $warmup warmups; hosted-runner results are informational."
} > "$output/summary.md"
9 changes: 8 additions & 1 deletion docs/research.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Terminal tool research

Reviewed 2026-08-12 through 2026-08-17 from the requested repositories. The
Reviewed 2026-08-12 through 2026-08-18 from the requested repositories. The
local `research/` directory contains shallow clones at the revisions below and
is intentionally ignored by Git. Category and license describe the upstream
project; no source or assets are copied into Keys Tools.
Expand Down Expand Up @@ -74,6 +74,13 @@ project; no source or assets are copied into Keys Tools.
It does not copy upstream art or code, and it excludes live weather,
geolocation, Tenor, URLs, videos, exports, plugins, and caches because those
require unrelated privacy, TLS, codec, persistence, or subprocess surfaces.
- `apps` owns the common local workflows from the final ten projects: bounded
text reading/search, quoted CSV/TSV tables, Markdown slides, text-canvas
painting, and a monotonic timer. PDF rasterization requires MuPDF; modern web
rendering requires Firefox; GUI-in-terminal and terminal-window management
require Wayland/PTY engines; weather and throughput tests require TLS and
live services. Those unrelated engines remain excluded instead of being
hidden behind launchers or adding large dependency trees.
- Crossterm is the only runtime dependency and owns cross-platform raw input,
resize events, alternate-screen entry, and terminal restoration. Ratatui is
excluded because these fixed layouts do not need a widget or layout engine.
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ readme = "README.md"
requires-python = ">=3.9"
license = "MIT"
authors = [{ name = "Keys" }]
keywords = ["astronomy", "cli", "containers", "games", "gif", "point-cloud", "screensaver", "slurm", "system-information", "terminal", "vcd", "waveform"]
keywords = ["astronomy", "cli", "containers", "csv", "games", "gif", "markdown", "point-cloud", "screensaver", "slurm", "system-information", "terminal", "timer", "vcd", "waveform"]
classifiers = [
"Environment :: Console",
"Programming Language :: Rust",
Expand Down
1 change: 1 addition & 0 deletions scripts/smoke-wheel.sh
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,4 @@ fi
"$bin_dir/lazybox$suffix" --version
"$bin_dir/science$suffix" snapshot orbit --json
"$bin_dir/screensaver$suffix" snapshot rain --seed 1 --json
"$bin_dir/apps$suffix" snapshot timer --seconds 60 --elapsed 5 --json
Loading
Loading