Play Battleship against your assistant. Fire shots, track hits and misses, and sink the fleet before the assistant sinks yours.
A Vellum plugin that lets you play Battleship against your assistant.
This plugin demonstrates three plugin surfaces working together:
apps/battleship/ directory ships a multi-file TSX game
board (Preact + esbuild). The assistant discovers it natively as a
plugin-bundled app (id: plugins~battleship~battleship) and serves the
compiled output in the workspace panel.routes/) serve the game API for
the app UI. The player starts games, lists games, resumes games, fetches
game state, and fires shots through these routes. After the player fires,
the game route triggers the assistant's turn automatically via
runConversationTurn from the plugin API.skills/battleship/SKILL.md instructs the assistant on
how to play. A script at skills/battleship/scripts/battleship.ts provides
fire and status subcommands that import the shared game logic directly.Routes and skill scripts serve different actors:
routes/) are for the user (the app UI). The player
starts games, lists games, fires shots, and reads game state through HTTP
endpoints.skills/battleship/scripts/) are for the assistant.
They import src/game-logic.ts directly and execute in-process.Both share the same game logic module (src/game-logic.ts) and the same
file-based state store (src/state-store.ts), so the game stays consistent
regardless of which actor makes a move.
| Method | Path | Description |
|---|---|---|
| GET | /games | List all games (active and completed) |
| POST | /games/new | Start a new game (random ship placement) |
| POST | /games/fire | Submit the player's turn (fire at assistant's fleet) |
| GET | /game-state?gameId=<id> | Fetch a specific game's state |
The key Battleship mechanic is hidden information. Both the app UI and the assistant's script receive sanitized views: hits and misses are visible, but unhit ship cells are projected as . The assistant genuinely has to guess where ships are, making the game fair.
"empty"Standard Battleship on a 10x10 grid:
battleship/
package.json # Plugin manifest (peer dep @vellumai/plugin-api ^0.10.9)
tsconfig.json
skills/
battleship/
SKILL.md # Instructions for the assistant on how to play
scripts/
battleship.ts # fire <coordinate> and status subcommands
routes/
games.ts # GET — list all games
games/
new.ts # POST — start a new game
fire.ts # POST — submit player's turn
game-state.ts # GET — fetch single game state
src/
game-logic.ts # Core game logic (shared by routes + skill scripts)
state-store.ts # File-based multi-game state persistence
apps/
battleship/
src/
index.html # HTML shell
main.tsx # Preact entry point
styles.css # Game styles
types.ts # Shared TypeScript types
components/
App.tsx # Main app component (game list + board views)
GameBoard.tsx # 10x10 grid component (target or fleet view)
GameList.tsx # Game list with active/completed sections
assistant plugins install https://github.com/vellum-ai/battleship
After installation, the Battleship app appears in the workspace app library automatically. Open it from the Library, or the assistant can open it with:
app_open(app_id="plugins~battleship~battleship")