npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

poker-lan-cli

v0.3.0

Published

Texas Hold'em in your terminal (Ink) with a browser GUI — single player vs equity-based bots, or LAN multiplayer with save/resume.

Readme

poker-lan-cli

No-limit Texas Hold'em in your terminal, built with Ink. Every game also opens a browser GUI on localhost that mirrors the table and lets you act from there. The GUI shows the table from above in one of three scenes, picked at random each time you open it (a live-TV arena with a square stage, cameras, cheering fans, sponsor billboards and a casino hallway; a ski lodge with a fireplace and round windows onto snowy mountains; or a little garden lawn on the beach with deck chairs and a busy boardwalk). It also has chip and card animations, sound effects, and a cartoon avatar in sunglasses for every player.

  • Single Player — you against 4 bots that decide with equity, pot odds and hand ranges
  • Host — run a table other people on your LAN can join, plus up to 4 bots. Progress is saved so you can resume unfinished games
  • Join on LAN — hosts on your network are found automatically, or you can type an address

Install

With npm (needs Node.js 22+):

npx poker-lan-cli
# or
npm install -g poker-lan-cli
poker-lan

Without npm or Node (Linux and macOS). This downloads a standalone executable from the GitHub releases:

curl -fsSL https://raw.githubusercontent.com/samnayak1/lan-cli-poker/main/install.sh | sh

It installs to ~/.local/bin/poker-lan. Use PREFIX=/usr/local to choose another location, or VERSION=v0.1.0 for a specific release.

From source with make (needs Bun, or npm as a fallback):

git clone https://github.com/samnayak1/lan-cli-poker && cd lan-cli-poker
make install            # builds bin/poker-lan and copies it to ~/.local/bin
make release            # executables for every platform, in release/

The executables bundle the runtime, the game and the browser GUI into one file (60–85 MB), so they run with nothing else installed.

Options

-n, --name <name>     Your player name (skips the name prompt)
    --port <port>     Port to host LAN games on (default 47777)
    --web-port <port> Port for the local browser GUI (default 8347)
    --no-browser      Serve the browser GUI but don't open it automatically
    --no-gui          Terminal only

Controls

There are only three actions, in the terminal and in the browser:

| Key | Action | | --- | --- | | F | Fold | | C | Call (this checks when there's nothing to call) | | R | Raise. Type an amount or use ←/→ (±1 BB) and ↑/↓ (±5 BB), then Enter. Raising your whole stack is going all in |

Q quits to the menu (hosts: the game is saved) and O reopens the browser GUI. The next hand is dealt automatically a few seconds after the last one ends.

In the lobby the host presses B to add a bot (at most 4), X to remove one, and S to start.

LAN play

  1. One person picks Host a LAN game. The lobby shows addresses such as 192.168.1.20:47777.
  2. Everyone else picks Join a LAN game. Tables on the network are found through UDP broadcast on port 47778. If none appears, choose Enter address manually.
  3. The host can add bots to fill seats and then starts the game.

The host's machine is the source of truth. Clients only ever receive their own hole cards, so a modified client can't see other players' hands. If a player's connection drops, their seat checks or folds until they rejoin with the same name. Each turn has a 60-second limit.

Firewall: the host must allow inbound TCP 47777 (game) and UDP 47778 (discovery). On WSL2, LAN broadcast usually doesn't reach Linux, so joiners should type the Windows host's IP. The host may also need to set up port forwarding or mirrored networking.

Saved games

Hosted games are saved to ~/.poker-lan-cli/saves/ after every hand and when the host quits. You can change the location with POKER_LAN_HOME. If a game is closed mid-hand, that hand is replayed from its starting stacks.

To resume, choose Host → Resume "…". Saved players get their seats and chips back when they rejoin with the same name. The host can press F to give unclaimed seats to bots. Seats beyond the 4-bot limit are closed. A save is deleted when its game finishes. Press D in the host menu to delete one manually.

The bots

Every bot plays the same strong, GTO-inspired strategy and adapts to how you play. Each decision uses only information a real player would have:

  • Preflop charts: solver-style opening, re-raising and calling ranges for each seat, with mixed frequencies for borderline hands.
  • Postflop play: the bot estimates its equity with a Monte Carlo simulation (about 700 run-outs) against what each opponent likely holds. Facing a bet, it calls whenever that beats the pot odds. Otherwise it value-bets at mixed sizes, semi-bluffs draws, bluffs rivers at a measured rate, and sometimes slow-plays monsters.
  • Learning the table: a shared tracker records how every player plays: how often they enter pots, raise, re-raise, bet after the flop, and fold to bets. The bots bluff players who fold too much, value-bet players who call too much, call down players who bet too much, and widen or tighten their preflop charts to match.

In simulated heads-up play the current bot beats the previous version, wins 2–4× as much as before from players who always call or always fold, and defends against players who raise and bet every hand instead of folding to them.

The full walkthrough, with worked examples and every tuning constant, is in docs/BOT.md.

How hands are ranked (with bitmasks for straights and flushes) is explained in docs/HAND_EVALUATOR.md.

Architecture

src/
  engine/            pure game rules, no I/O
    Card.ts          rank/suit, codes like "As"
    Deck.ts          shuffle (crypto RNG), draw
    HandEvaluator.ts best 5 of 7 → comparable score + name
    Player.ts        stack and per-hand betting state
    Pot.ts           main/side pot construction
    GameState.ts     all table data, per-viewer views, snapshots for saving
    Game.ts          betting rounds, streets, showdown (a state machine)
  ai/                ranges.ts · equity.ts · Bot.ts
  TableSession.ts    runs a table: seats, bot turns, timeouts, pacing, saving
  net/               protocol, HostServer (WebSocket), RemoteConnection, UDP discovery
  web/WebServer.ts   localhost GUI server (token-protected WebSocket)
  persistence/       SaveManager
  ui/                Ink screens
public/index.html    the browser GUI (vanilla JS, no build step)

The terminal UI and the browser GUI both talk to a TableConnection. That connection is either local (single player or host, where the table runs in this process) or remote (join, over WebSocket), so each screen is written only once.

Development

npm install
npm run dev        # run from source with tsx
npm test           # engine, AI, and network integration tests
npm run build      # compile to dist/
npm publish        # runs typecheck + tests + build first
make release       # standalone executables for every platform

Pushing a version tag (npm version patch && git push --follow-tags) runs .github/workflows/release.yml, which builds the executables and attaches them to a GitHub release. install.sh downloads from those releases.

Contributing

Any problems or want to contribute? Contact [email protected]

License

MIT