Tapoo is a maze runner hide-and-seek game with two interfaces built from the same codebase: a Go terminal game and a browser SPA with the same terminal-inspired feel.
Objective: Guide the blue player to the red destination before the score drops to zero.
go install github.com/dmigwi/tapoo@latest
tapoogo run .make frontend-install
make frontend-buildThen serve public/ and open /index.html.
Gameplay And Controls
Tapoo increases maze area as levels rise. Progress continues until the current terminal window or browser viewport can no longer fit the next maze cleanly.
Arrow keys: move the playerCtrl+B: cycle maze wall weightSpaceorEsc: pause the current runEnter: proceed after pause, win, or failureCtrl+C: quit
- Keyboard controls mirror the terminal controls
Ctrl+Alt+R: reset browser progress- On touch devices, on-screen controls are shown automatically
Highlights
- Terminal-first maze gameplay
- Browser SPA with the same black-and-green terminal feel
- Adjustable wall weights with live cycling during play
- Per-level scoring and progression
- Pause, resume, retry, and next-level flow
- HTTP-driven AI agent play against Ollama, OpenAI-compatible, and Anthropic APIs, with up to 6 (configurable) agent seats
- Best-effort persistence for terminal and browser sessions
- Manual GitHub Pages deployment for the web build
- Go and TypeScript test coverage in CI
Browser App
The browser build outputs a bundled file at public/js/tapoo.min.js and serves the SPA from public/index.html.
This compiles frontend/tapoo.ts with esbuild into a minified browser bundle.
Available pages:
/index.htmlfor the game/agents.htmlfor configuring and running HTTP-driven AI agents/prompts.htmlfor previewing the exact prompts and tool definitions sent to an agent/privacy.htmlfor the browser storage and agent data privacy notice
AI Agents
Instead of (or alongside) a human player, up to 6 agent seats can each be configured to play the maze by calling an HTTP chat-completions endpoint every turn.
- Ollama — native
/api/chatshape - OpenAI-compatible —
/v1/chat/completions(also covers self-hosted servers such as vLLM, LM Studio, and llama.cpp, and routers such as Hugging Face's Inference Providers) - Anthropic —
/v1/messages
Each seat is configured independently from the /agents.html overlay:
- player name, model, endpoint, and API provider
- credential (bearer token or API key) and custom extra headers, e.g.
anthropic-version - reasoning effort — how hard the model reasons before replying; the available levels and default depend on the provider, since reasoning support varies by model (e.g. Kimi K3 handles heavy reasoning well, Gemma 4 does not)
- echo back reasoning — whether prior reasoning content is replayed on the next request, off by default since guidance on this conflicts across reasoning models; locked off automatically whenever reasoning effort is set to
none, and has no effect for Anthropic agents
The /prompts.html page mirrors the exact system prompt, tool definitions, and required response format an agent receives, so its behavior can be inspected without capturing live traffic.
Persistence
Tapoo carries a semantic version (MAJOR.MINOR.PATCH), shown in the terminal intro banner and in the browser footer. Browser storage additionally carries its own separate schema version, independent of the app version above — see the browser storage note below.
The terminal version stores best-effort runtime state in a local file:
.tapoo.store
It keeps track of:
- current level
- selected wall weight
- last game progress state
If the persisted state cannot be read or validated, Tapoo falls back to default startup behavior.
The SPA stores gameplay state in browser storage:
localStoragefor durable preferences such as level and wall weight, and for configured agent seats (including credentials, endpoints, and per-agent reasoning settings)sessionStoragefor the active round snapshot
Every stored entry is tagged with the current storage schema version. On startup, Tapoo automatically discards any entries left over from an older schema version rather than attempting to migrate them — so upgrading Tapoo can silently reset previously stored preferences and agent configuration.
Privacy note: browser storage stays on the current device unless the user clears it, resets progress, or removes configured agent data. Browser storage is lightly obfuscated to discourage casual tampering, but it should not be treated as strong encryption for personal data. When AI Agent play is configured, gameplay context such as player name, current cell, destination cell, submitted moves, score, level, and traversal history may be sent to the configured agent API endpoint.
The deployed browser pages include a short privacy notice at privacy.html.
Development
- Go
1.25+ pnpm 11.7.0- Node.js
22 golangci-lint v2.12.2
make help
make frontend-install
make frontend-quality
make frontend-build
make test
make ciGo and TypeScript carve mazes independently from different random sources, so scripts/bench-report.mjs runs both ports' benchmark suites (maze/bench and frontend/bench) and statistically checks that the two generators still produce equivalent-distribution mazes rather than merely eyeballing the numbers. A flagged case means a reproducible behavioral gap between the ports, not just run-to-run noise.
make go-bench # Go maze generation only
make frontend-bench # TypeScript maze generation only
make ci-bench # both, with the cross-port parity checkEach run also writes bench-report.json with the full comparison.
Contributing
Contributions are welcome, but contributors should install the repository pre-commit hook before creating commits.
- Install the required toolchains:
Go 1.25+,Node.js 22,pnpm 11.7.0, andgolangci-lint v2.12.2 - Install frontend dependencies:
make frontend-install- Install the repository git hooks:
./scripts/install-hooks.shThe hook installer copies scripts/hooks/pre-commit into .git/hooks/pre-commit.
The pre-commit hook runs:
golangci-lint runThis is required so commits are checked locally before they are pushed. If golangci-lint is not installed, the hook installation script will warn you and show installation options.
make ciAt minimum, contributors should make sure:
- Go tests pass
- frontend typecheck, lint, and tests pass
golangci-lint runpassesgovulncheckpasses
make lint: rungolangci-lintmake govulncheck: rungovulncheckmake frontend-quality: run frontend typecheck, lint, and testsmake frontend-build: build the minified SPA bundlemake test: run frontend checks plus Go race tests with coveragemake ci: run the local equivalent of the main CI pipeline
Testing And Quality
go test ./...
go test -race -covermode=atomic -coverprofile=coverage.out ./...
golangci-lint runpnpm run typecheck:frontend
pnpm run lint:frontend
pnpm run test:frontend
pnpm run coverage:frontendCI And Deployment
The main CI workflow lives at .github/workflows/go.yml and runs:
- Go linting
govulncheck- frontend typecheck, lint, tests, and build
- Go race tests with coverage
- coverage uploads for Go and frontend reports
The Pages workflow lives at .github/workflows/pages.yml.
Pages deployment is manual-only.
To deploy:
- Open the repository on GitHub.
- Go to
Actions. - Choose
Deploy Pages Manually. - Click
Run workflow. - Select the branch you want to deploy.
Important:
- GitHub Pages should be configured to use
GitHub Actionsas the publishing source. - Since the workflow is manual, it deploys the branch selected at run time.
maze/ Go gameplay, rendering, persistence, and tests
frontend/app/ TypeScript SPA logic and tests
public/ Static site assets, HTML, CSS, images, and built JS
scripts/ Frontend build and hook helpers
This project is licensed under the Apache License 2.0. See LICENSE.
Tapoo is distributed on an AS IS basis, without warranties or guaranteed support.