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
236 changes: 236 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ path = "src/bin/fetch.rs"
name = "games"
path = "src/bin/games.rs"

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

[profile.release]
codegen-units = 1
lto = true
opt-level = "z"
panic = "abort"
strip = true
43 changes: 18 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
Small native terminal tools with one job each:

- `fetch` shows a fast system and CPU overview with styled, plain, or JSON output.
- `games` lists and launches terminal games already installed on the machine.
- `games` is an original native terminal arcade with eleven complete game modes.

The binaries share no third-party runtime dependencies and never download or
install software.
The binaries never download or install software. `games` uses Crossterm for
raw keyboard input and terminal restoration; no upstream game code, assets, or
runtime is bundled.

## Install

Expand All @@ -28,7 +29,7 @@ Rust 1.97.1 is pinned for builds.
```sh
cargo build --release --locked
./target/release/fetch
./target/release/games list
./target/release/games
```

Useful non-interactive forms:
Expand All @@ -37,38 +38,30 @@ Useful non-interactive forms:
fetch --plain
fetch --json
games list --json
games info 2048
games run 2048
games info merge
games run merge --seed 1
```

`NO_COLOR=1` disables decoration. `games run` executes the resolved program
directly, never through a shell.
`NO_COLOR=1` disables decoration. Interactive play needs a real terminal and
restores raw mode, cursor state, wrapping, and the main screen when it exits.

## Game packs
## Native arcade

`games` reads optional `*.game` files from directories in `TOOLS_GAME_PATH`
and from the user data directory (`$XDG_DATA_HOME/keys-tools/games`, or
`~/.local/share/keys-tools/games`). A manifest is five bounded, single-line
fields:

```ini
name=maze
command=maze
summary=Small terminal maze
source=https://example.com/maze
license=MIT
```

Names cannot shadow bundled entries. Commands contain one executable and no
shell syntax; arguments are supplied explicitly to `games run`.
`games` contains eleven clean-room modes: `delve`, `orbit`, `serpent`,
`merge`, `vector`, `cards`, `seedling`, `sprint`, `keybed`, `glyphs`, and
`scout`. They use an original implementation, maps, words, prose, and ASCII art
informed only by the high-level behavior of the research projects. Sessions
are finite and seeded; v1 has no network, audio, persistence, plugins, external
executables, or copied assets.

## Scope

`fetch` has detailed native collection on macOS and Linux and a smaller
environment-backed view on Windows. It is intentionally not a configurable
replacement for every Fastfetch module. See [research](docs/research.md) and
[fetch benchmarks](benches/fetch.md) for the measured comparison and limits.
The [games benchmark](benches/games.md) measures only launcher-owned work.
The [games benchmark](benches/games.md) measures the native arcade's owned
non-interactive path and binary size.

## Project

Expand Down
2 changes: 2 additions & 0 deletions benches/fetch.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ shell, and terminal categories. They are not identical: `fetch` additionally
prints architecture, CPU topology, and physical/logical core counts. For this
bounded overview, `fetch` used 70.5% less mean launch time than Fastfetch and
84.1% less than Macchina. Its binary was 79.2% and 80.0% smaller, respectively.
The current unwind-safe build is 336,224 bytes, 192 bytes larger than the
measured build; its collection path is unchanged.

The requested combined workflow was also measured through the same shell:

Expand Down
31 changes: 24 additions & 7 deletions benches/games.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,34 @@
# Games benchmark
# Native arcade benchmark

`games` owns only discovery and safe process launch; the selected game owns
its runtime. The repository benchmark therefore measures `games list --plain`
against the built-in catalog with empty extension directories. It does not
misrepresent a downstream game's startup time as launcher performance.
The benchmark measures the owned non-interactive contract
(`games list --plain`) and the stripped release binary size. Gameplay is
event-driven and terminal-bound; comparing whole sessions with unrelated
upstream games would not be equivalent.

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

| Version | Mean ± standard deviation | Stripped binary |
| --- | ---: | ---: |
| External launcher (`3b618dd`, reference only) | 1.8 ± 0.1 ms | 354,496 bytes |
| Native eleven-game arcade | 1.5 ± 0.1 ms | 438,992 bytes |

The two list commands are not equivalent workloads, so their timing difference
is not a performance claim. The native binary adds 84,496 bytes (about 24%)
for eleven game engines and cross-platform terminal input.
The macOS ARM64 wheel is 410,899 bytes, including both binaries, package
metadata, project and dependency licenses, and CycloneDX SBOM; that is 67,191
bytes (about 20%) over
the prior 343,708-byte wheel.

Run the same benchmark used by CI:

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

Hyperfine JSON, Markdown, and binary sizes are written to
`target/benchmarks/`. Hosted-runner timings are diagnostic evidence, not a
stable regression threshold; compare performance claims on the same host.
No claim is made that one original mode is faster or more feature-complete
than an upstream inspiration: they are different games.
4 changes: 1 addition & 3 deletions benches/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ for binary in "$fetch" "$games"; do
}
done

mkdir -p "$output/empty"
export TOOLS_GAME_PATH="$output/empty"
export XDG_DATA_HOME="$output/empty"
mkdir -p "$output"

hyperfine --shell=none --warmup "$warmup" --runs "$runs" \
--export-json "$output/tools.json" \
Expand Down
Loading
Loading