A NetHack-style ASCII fishing roguelike to play in a second terminal window while Claude Code is busy. When Claude finishes, the game pings you to reel in.
π£ NETHOOK β Lake TaupΕ π§rain Β· autumn Β· πdusk Β· 12Β°C Β· πfeeding
...........~~~~~~..........
........~~~~ββββ~~~~,......
......~~ββββββββββ~~"......
=@~~ββββ F ββββββββ~~......
......~~βββββ# ββββ~~......
......$..~~~~βββ~~~~.......
β Land a trophy catch (+35c) β Log a new species (+25c)
π TROPHY Rainbow Trout β 3.1kg, grade S! +186 pts
β ββββββββββββββββ π£Heirloom Rod πͺ±Spinner Lure β240c β
186 β
Claude ready β reel in!
move: hjkl/arrows Β· f+dir: cast Β· $: shanty Β· q: quit
The spinner-stare while Claude works is dead time. Nethook fills it with a quick, glanceable fishing roguelike β and tells you the moment Claude is done.
A plugin can't render a live game inside Claude Code's own terminal (Claude owns that TTY), so Nethook runs as a standalone game in its own window. That's the authentic roguelike model anyway.
- Claude Code (the CLI) β to install it as a plugin.
- Node.js β₯ 18 β the game is plain Node, zero dependencies.
- A real terminal you can open a second window/tab/pane in (the game runs in its own window β see Why). Works on macOS, Linux, WSL, and Windows Terminal.
Run these two slash commands inside Claude Code β no build, no npm install, no
marketplace approval needed:
/plugin marketplace add ClickClickMedia/Nethook # 1. register this repo's marketplace
/plugin install nethook@nethook # 2. install the plugin (name@marketplace)
That's it. Now, any time Claude is busy and you want something to do:
/gofish # opens Nethook in a NEW terminal window
/gofish "Lake TaupΕ" # β¦or jump straight into a specific spot
- If
/gofishcan't auto-open a window (headless or an unrecognised terminal) it prints a copy-paste command instead β paste it into any separate tab/pane. /nethook:spot "<real place>"has Claude generate a playable Spot Pack for a real location (ASCII map, real species, real tackle, real strategy) and installs it; then/gofish "<place>".
While Claude works, a Stop hook flips the game's status bar to "β
Claude ready
β reel in!" (with a terminal bell), and a PreToolUse hook nudges you to go fish
when Claude kicks off a long command (once per session).
To update later: /plugin marketplace update nethook then re-run /plugin install nethook@nethook. To remove it: /plugin uninstall nethook@nethook.
You don't need Claude Code to play β clone and run:
git clone https://github.com/ClickClickMedia/Nethook && cd Nethook
node game/index.mjs # play the procedural lake
node game/index.mjs "Lake TaupΕ" # β¦or a named built-in spot
(The plugin's only extra is the /gofish window-launcher and the Claude-ready
status handshake; the game itself is the same.)
- Move with
hjklor arrows; you walk the shore/dock (@). - Fish: press
fthen a direction to cast at adjacent water. On a bite, a reel fight begins βrto reel,eto ease. Keep tension in the safe band: let it hit 100% and the line snaps, but let it sit too low and the line goes slack until the hook slips β so you can't just coast. Fights come in three flavours (rarer fish pick the nastier ones): a steady haul, a runner that bolts in bursts (ease while it runs, reel when slack), and a pendulum where you reel only while the sweeping lure sits in the green zone. - Water: shallow
~, deepβ, reeds", lilypads,, rocks#(no fish). Different species favour different depths. - Shanty (
$): spend coins on better rods and bait to unlock deeper water and rarer fish, or deploy a π¦ crab pot. Gear and coins persist. - Crab pot (idle): once deployed, it accrues a little catch in real time while you're away and pays out the next time you launch β but the haul decays Fresh β Stale β Rotting if you leave it too long, so check in regularly. Upgrade it at the shanty (Mk 1 β 2 β β¦) for bigger hauls β a late-game coin sink.
- Complete the logbook: catch every (non-junk) species at a spot and you earn the Golden Rod β the best rod in the game, granted once and kept for good.
- Trips: each launch is one bounded daylight session; at dusk it scores.
- Bounties: every trip rolls two goals (land a trophy, log a new species, hook an aberrationβ¦) that pay a coin + score bonus β a fresh objective each launch.
- Grades & trophies: every catch is graded FβSSS by how big it is for its species. A top-of-range specimen (or a rare gold strike) lands a π trophy worth a value bonus β the logbook remembers your best grade and trophy count.
- Aberrations: now and then β mostly at dusk or in fog β something wrong takes the hook. π Aberrant variants fight harder and pay far more.
- Logbook (persistent): species dex, biggest catches, best grades, trophies,
totals, best score β saved under
$XDG_DATA_HOME/nethook(or~/.local/share/nethook).
A Spot Pack is JSON describing a real location: an optional ASCII map, a species
table with real behaviour, tackle, and strategy. Three ship built-in
(game/packs/): Lake TaupΕ, The Everglades, Lofoten Fjord. Generate
more with /nethook:spot. The engine validates every pack (game/pack.mjs) so a
bad one can never crash the game; with no pack it builds a procedural lake.
Environment gating: each trip rolls a season and weather, and the
day-phase moves with the daylight clock (dawn β day β dusk). Species can gate
themselves by time, season, weather, and preferred bait, so a spot plays
differently trip to trip β the skrei cod run shows up in winter, the kraken only
at foggy dusk. Dawn/dusk and rain bite better. Gates are sanitized on load, never
trusted.
Grounded bite model (optional realism): a species can declare a water-temp
preference (tempOptimum / tempRange Β°C); the engine derives the trip's water
temperature from the season around the spot's annual mean (hints.baseTemp), so
cold-water fish fade in a summer heatwave. The bite also follows solunar
feeding β computed in-engine from the moon phase on the trip's real date (no API,
no network) β strongest around the new and full moon. The header shows the
trip's Β°C and a πππ feeding indicator.
Zero runtime dependencies (pure Node + ANSI). The game core is split so it's testable without a TTY:
npm test # node game/selftest.mjs β 110 assertions over the pure core
node game/launch.mjs --dry-run # show the window-spawn plan for your env
node game/packcheck.mjs <pack.json> # validate a Spot Pack
game/core.mjs, world.mjs, render.mjs, pack.mjs, logbook.mjs are pure;
game/index.mjs is the only file that touches the terminal.
Trying it out? See TESTING.md for what to look for and how to report. Want to add a Spot Pack, a species, or a fix? CONTRIBUTING.md has the dev setup and the one rule that matters (keep the core pure). PRs welcome β new real-world Spot Packs especially. MIT licensed.