sideboard 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "sideboard",
3
+ "owner": {
4
+ "name": "zappleg8"
5
+ },
6
+ "plugins": [
7
+ {
8
+ "name": "sideboard",
9
+ "source": "./",
10
+ "description": "Play chess against Chesster, inline in Claude Code",
11
+ "version": "0.2.0"
12
+ }
13
+ ]
14
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "sideboard",
3
+ "version": "0.2.0",
4
+ "description": "Play chess against Chesster, inline in Claude Code",
5
+ "author": {
6
+ "name": "Zach Applegate"
7
+ },
8
+ "repository": "https://github.com/zappleg8/sideboard",
9
+ "license": "MIT",
10
+ "keywords": [
11
+ "chess",
12
+ "game",
13
+ "claude-code"
14
+ ],
15
+ "skills": "./skills/",
16
+ "mcpServers": {
17
+ "sideboard": {
18
+ "command": "uvx",
19
+ "args": ["--from", "sideboard", "sideboard-mcp"]
20
+ }
21
+ }
22
+ }
sideboard-0.2.0/.git ADDED
@@ -0,0 +1 @@
1
+ gitdir: /Users/zachtireseasy/code/personal/sideboard/.git/worktrees/sideboard-plugin
@@ -0,0 +1,16 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *$py.class
4
+ *.egg-info/
5
+ dist/
6
+ build/
7
+ .eggs/
8
+ *.egg
9
+ .venv/
10
+ venv/
11
+ .pytest_cache/
12
+ .mypy_cache/
13
+ .ruff_cache/
14
+ .worktrees/
15
+ .claude/
16
+ docs/superpowers/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Zach Applegate
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,121 @@
1
+ Metadata-Version: 2.4
2
+ Name: sideboard
3
+ Version: 0.2.0
4
+ Summary: Chess in your terminal. Play against Chesster while your coding agent thinks.
5
+ Author: Zach Applegate
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Keywords: chess,claude-code,idle-game,terminal,tui
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Environment :: Console
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Topic :: Games/Entertainment :: Board Games
17
+ Requires-Python: >=3.11
18
+ Requires-Dist: mcp>=1.0
19
+ Requires-Dist: python-chess>=1.0
20
+ Requires-Dist: rich>=13.0
21
+ Provides-Extra: dev
22
+ Requires-Dist: pytest-cov>=5.0; extra == 'dev'
23
+ Requires-Dist: pytest>=8.0; extra == 'dev'
24
+ Description-Content-Type: text/markdown
25
+
26
+ # Sideboard
27
+
28
+ **Play chess against Chesster, inline in [Claude Code](https://docs.anthropic.com/en/docs/claude-code).**
29
+
30
+ ```
31
+ a b c d e f g h
32
+ ┌───┬───┬───┬───┬───┬───┬───┬───┐
33
+ 8 │ ♖ │ ♘ │ ♗ │ ♕ │ ♔ │ ♗ │ ♘ │ ♖ │ 8
34
+ ├───┼───┼───┼───┼───┼───┼───┼───┤
35
+ 7 │ ♙ │ ♙ │ ♙ │ ♙ │ ♙ │ ♙ │ ♙ │ ♙ │ 7
36
+ ├───┼───┼───┼───┼───┼───┼───┼───┤
37
+ 6 │ │ │ │ │ │ ♘ │ │ │ 6
38
+ ├───┼───┼───┼───┼───┼───┼───┼───┤
39
+ 5 │ │ │ │ │ │ │ │ │ 5
40
+ ├───┼───┼───┼───┼───┼───┼───┼───┤
41
+ 4 │ │ │ │ │ ♟ │ │ │ │ 4
42
+ ├───┼───┼───┼───┼───┼───┼───┼───┤
43
+ 3 │ │ │ │ │ │ │ │ │ 3
44
+ ├───┼───┼───┼───┼───┼───┼───┼───┤
45
+ 2 │ ♟ │ ♟ │ ♟ │ ♟ │ │ ♟ │ ♟ │ ♟ │ 2
46
+ ├───┼───┼───┼───┼───┼───┼───┼───┤
47
+ 1 │ ♜ │ ♞ │ ♝ │ ♛ │ ♚ │ ♝ │ ♞ │ ♜ │ 1
48
+ └───┴───┴───┴───┴───┴───┴───┴───┘
49
+ a b c d e f g h
50
+
51
+ Chesster: Alekhine's Defense — bold of you to invite the bayonet.
52
+ ```
53
+
54
+ A chess game that lives inside your Claude Code conversation, for when the coding agent is grinding through a slow build.
55
+
56
+ ## Install (Claude Code)
57
+
58
+ You'll need [uv](https://github.com/astral-sh/uv) on your `PATH` — the MCP server runs via `uvx`. Install with `brew install uv` if you don't have it.
59
+
60
+ In Claude Code:
61
+
62
+ ```
63
+ /plugin marketplace add zappleg8/sideboard
64
+ /plugin install sideboard@sideboard
65
+ ```
66
+
67
+ That's it. No pip, no shell config, no daemons.
68
+
69
+ ## Play
70
+
71
+ ```
72
+ /sideboard:play # start or resume a game
73
+ /sideboard:play e4 # make a move (SAN: e4, Nf3, O-O, Bxe5, e8=Q)
74
+ /sideboard:board # re-render the current state silently
75
+ /sideboard:resign # resign and archive the PGN
76
+ ```
77
+
78
+ One global game, persisted at `~/.sideboard/`. Quit Claude Code, come back tomorrow, the position is still there.
79
+
80
+ ## Standalone CLI (no Claude Code)
81
+
82
+ If you'd rather play in a regular terminal:
83
+
84
+ ```bash
85
+ pip install sideboard
86
+ sideboard # new game vs Chesster
87
+ sideboard --difficulty casual # beginner-friendly
88
+ sideboard --difficulty shark # bring your A-game
89
+ sideboard resume # pick up where you left off
90
+ sideboard stats # your record vs Chesster
91
+ ```
92
+
93
+ Terminal mode renders a colored Rich-styled board with proper chess glyphs.
94
+
95
+ ## How It Works
96
+
97
+ A small Claude Code plugin packages three pieces:
98
+
99
+ - A **slash-command skill** (`/sideboard:play`) that tells Claude to drive the game.
100
+ - An **MCP server** (`sideboard-mcp`, launched via `uvx`) that exposes the chess engine and game state as tools (`new_game`, `make_move`, `engine_response`, `get_state`, `resign`, `get_stats`).
101
+ - The **engine** is local Python — minimax with alpha-beta pruning, piece-square tables, and a curated Chesster quip pool that reacts to captures, checks, blunders, and brilliancies.
102
+
103
+ Each move is two MCP calls: `make_move` applies your move and returns the engine's top three candidates plus a Chesster quip; `engine_response` plays whichever candidate Claude picks. The board renders in the conversation as a fenced code block.
104
+
105
+ ## Difficulty
106
+
107
+ | Level | Search depth | Behavior |
108
+ |---|---|---|
109
+ | `casual` | 2 ply | Occasionally picks an off-best move for variety |
110
+ | `club` | 3 ply | Default — solid, beatable |
111
+ | `shark` | 4 ply + quiescence | Sees tactics; will hurt you |
112
+
113
+ ## Dependencies
114
+
115
+ - [python-chess](https://python-chess.readthedocs.io/) — board state, move legality, PGN export
116
+ - [mcp](https://github.com/modelcontextprotocol/python-sdk) — Claude Code plugin server
117
+ - [Rich](https://rich.readthedocs.io/) — only for the standalone terminal CLI
118
+
119
+ ## License
120
+
121
+ MIT
@@ -0,0 +1,96 @@
1
+ # Sideboard
2
+
3
+ **Play chess against Chesster, inline in [Claude Code](https://docs.anthropic.com/en/docs/claude-code).**
4
+
5
+ ```
6
+ a b c d e f g h
7
+ ┌───┬───┬───┬───┬───┬───┬───┬───┐
8
+ 8 │ ♖ │ ♘ │ ♗ │ ♕ │ ♔ │ ♗ │ ♘ │ ♖ │ 8
9
+ ├───┼───┼───┼───┼───┼───┼───┼───┤
10
+ 7 │ ♙ │ ♙ │ ♙ │ ♙ │ ♙ │ ♙ │ ♙ │ ♙ │ 7
11
+ ├───┼───┼───┼───┼───┼───┼───┼───┤
12
+ 6 │ │ │ │ │ │ ♘ │ │ │ 6
13
+ ├───┼───┼───┼───┼───┼───┼───┼───┤
14
+ 5 │ │ │ │ │ │ │ │ │ 5
15
+ ├───┼───┼───┼───┼───┼───┼───┼───┤
16
+ 4 │ │ │ │ │ ♟ │ │ │ │ 4
17
+ ├───┼───┼───┼───┼───┼───┼───┼───┤
18
+ 3 │ │ │ │ │ │ │ │ │ 3
19
+ ├───┼───┼───┼───┼───┼───┼───┼───┤
20
+ 2 │ ♟ │ ♟ │ ♟ │ ♟ │ │ ♟ │ ♟ │ ♟ │ 2
21
+ ├───┼───┼───┼───┼───┼───┼───┼───┤
22
+ 1 │ ♜ │ ♞ │ ♝ │ ♛ │ ♚ │ ♝ │ ♞ │ ♜ │ 1
23
+ └───┴───┴───┴───┴───┴───┴───┴───┘
24
+ a b c d e f g h
25
+
26
+ Chesster: Alekhine's Defense — bold of you to invite the bayonet.
27
+ ```
28
+
29
+ A chess game that lives inside your Claude Code conversation, for when the coding agent is grinding through a slow build.
30
+
31
+ ## Install (Claude Code)
32
+
33
+ You'll need [uv](https://github.com/astral-sh/uv) on your `PATH` — the MCP server runs via `uvx`. Install with `brew install uv` if you don't have it.
34
+
35
+ In Claude Code:
36
+
37
+ ```
38
+ /plugin marketplace add zappleg8/sideboard
39
+ /plugin install sideboard@sideboard
40
+ ```
41
+
42
+ That's it. No pip, no shell config, no daemons.
43
+
44
+ ## Play
45
+
46
+ ```
47
+ /sideboard:play # start or resume a game
48
+ /sideboard:play e4 # make a move (SAN: e4, Nf3, O-O, Bxe5, e8=Q)
49
+ /sideboard:board # re-render the current state silently
50
+ /sideboard:resign # resign and archive the PGN
51
+ ```
52
+
53
+ One global game, persisted at `~/.sideboard/`. Quit Claude Code, come back tomorrow, the position is still there.
54
+
55
+ ## Standalone CLI (no Claude Code)
56
+
57
+ If you'd rather play in a regular terminal:
58
+
59
+ ```bash
60
+ pip install sideboard
61
+ sideboard # new game vs Chesster
62
+ sideboard --difficulty casual # beginner-friendly
63
+ sideboard --difficulty shark # bring your A-game
64
+ sideboard resume # pick up where you left off
65
+ sideboard stats # your record vs Chesster
66
+ ```
67
+
68
+ Terminal mode renders a colored Rich-styled board with proper chess glyphs.
69
+
70
+ ## How It Works
71
+
72
+ A small Claude Code plugin packages three pieces:
73
+
74
+ - A **slash-command skill** (`/sideboard:play`) that tells Claude to drive the game.
75
+ - An **MCP server** (`sideboard-mcp`, launched via `uvx`) that exposes the chess engine and game state as tools (`new_game`, `make_move`, `engine_response`, `get_state`, `resign`, `get_stats`).
76
+ - The **engine** is local Python — minimax with alpha-beta pruning, piece-square tables, and a curated Chesster quip pool that reacts to captures, checks, blunders, and brilliancies.
77
+
78
+ Each move is two MCP calls: `make_move` applies your move and returns the engine's top three candidates plus a Chesster quip; `engine_response` plays whichever candidate Claude picks. The board renders in the conversation as a fenced code block.
79
+
80
+ ## Difficulty
81
+
82
+ | Level | Search depth | Behavior |
83
+ |---|---|---|
84
+ | `casual` | 2 ply | Occasionally picks an off-best move for variety |
85
+ | `club` | 3 ply | Default — solid, beatable |
86
+ | `shark` | 4 ply + quiescence | Sees tactics; will hurt you |
87
+
88
+ ## Dependencies
89
+
90
+ - [python-chess](https://python-chess.readthedocs.io/) — board state, move legality, PGN export
91
+ - [mcp](https://github.com/modelcontextprotocol/python-sdk) — Claude Code plugin server
92
+ - [Rich](https://rich.readthedocs.io/) — only for the standalone terminal CLI
93
+
94
+ ## License
95
+
96
+ MIT
@@ -0,0 +1,45 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "sideboard"
7
+ version = "0.2.0"
8
+ description = "Chess in your terminal. Play against Chesster while your coding agent thinks."
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.11"
12
+ authors = [{ name = "Zach Applegate" }]
13
+ keywords = ["chess", "terminal", "tui", "claude-code", "idle-game"]
14
+ classifiers = [
15
+ "Development Status :: 3 - Alpha",
16
+ "Environment :: Console",
17
+ "Intended Audience :: Developers",
18
+ "License :: OSI Approved :: MIT License",
19
+ "Programming Language :: Python :: 3.11",
20
+ "Programming Language :: Python :: 3.12",
21
+ "Programming Language :: Python :: 3.13",
22
+ "Topic :: Games/Entertainment :: Board Games",
23
+ ]
24
+ dependencies = [
25
+ "python-chess>=1.0",
26
+ "rich>=13.0",
27
+ "mcp>=1.0",
28
+ ]
29
+
30
+ [project.optional-dependencies]
31
+ dev = [
32
+ "pytest>=8.0",
33
+ "pytest-cov>=5.0",
34
+ ]
35
+
36
+ [project.scripts]
37
+ sideboard = "sideboard.cli:main"
38
+ sideboard-mcp = "sideboard.mcp_server:main"
39
+
40
+ [tool.hatch.build.targets.wheel]
41
+ packages = ["src/sideboard"]
42
+
43
+ [tool.pytest.ini_options]
44
+ testpaths = ["tests"]
45
+ pythonpath = ["src"]
@@ -0,0 +1,22 @@
1
+ ---
2
+ name: board
3
+ description: "Show the current chess board state without making a move"
4
+ ---
5
+
6
+ # /board
7
+
8
+ Read-only refresh. Use when the user has scrolled away and wants to see the current state.
9
+
10
+ 1. Call `mcp__sideboard__get_state`.
11
+ 2. If the response contains `error: "No active game."`, tell the user there's no active game and suggest `/play` to start one. Stop.
12
+ 3. Otherwise, render:
13
+
14
+ ````
15
+ ```
16
+ {board_render}
17
+ ```
18
+ ````
19
+
20
+ Then a status line: `_Move {move_number}, {turn} to play. Difficulty: {difficulty}._`
21
+
22
+ Do not display `chesster_msg` here — `/board` is silent.
@@ -0,0 +1,52 @@
1
+ ---
2
+ name: play
3
+ description: "Play chess against Chesster, the witty engine"
4
+ ---
5
+
6
+ # /play
7
+
8
+ You are running the Sideboard chess game. The user is playing against Chesster, an overconfident chess engine with personality. You are NOT Chesster — you are the move executor and the renderer.
9
+
10
+ ## How to handle `/play` with no argument
11
+
12
+ 1. Call `mcp__sideboard__get_state`.
13
+ 2. If the response contains `error: "No active game."`, call `mcp__sideboard__new_game` with defaults (`difficulty: "club"`, `color: "white"`).
14
+ 3. Render the response using the format below.
15
+
16
+ ## How to handle `/play <move>` (e.g. `/play e4`, `/play Nf3`, `/play O-O`)
17
+
18
+ 1. Call `mcp__sideboard__make_move(san=<move>)`.
19
+ 2. If the response has `valid: false`:
20
+ - Show the `error` field.
21
+ - Show the first ~10 entries of `legal_moves`.
22
+ - Stop. The user retries with a different move.
23
+ 3. If valid:
24
+ - Render the response (board + Chesster line).
25
+ - If `game_over: true`, render the result and stop.
26
+ - From `engine_suggestions` (list of `[san, score]` pairs), pick the first one. Occasionally — say 1 turn in 5 — pick the second one for variety. **Never** pick beyond index 2.
27
+ - Call `mcp__sideboard__engine_response(san=<chosen_san>)`.
28
+ - Render the new response.
29
+ - If `game_over: true`, render the result and stop.
30
+
31
+ ## Rendering format
32
+
33
+ Always render the board inside a triple-backtick fenced code block (no language tag), so monospace alignment holds:
34
+
35
+ ````
36
+ ```
37
+ {board_render}
38
+ ```
39
+ ````
40
+
41
+ Then on the next line, render Chesster's line as: `**Chesster:** _{chesster_msg}_`
42
+
43
+ (Skip the Chesster line if `chesster_msg` is empty.)
44
+
45
+ If `move_number` and `turn` fields are present, include a small status line below the board: `_Move {move_number}, {turn} to play._`
46
+
47
+ ## Hard rules
48
+
49
+ - Do NOT invent Chesster lines. Only render the `chesster_msg` returned by the tool.
50
+ - Do NOT recommend moves to the player. The user plays. You render.
51
+ - Do NOT replay the player's move in the engine_response slot. The two-phase tools already handle that — `make_move` applies the player's move, `engine_response` applies Chesster's.
52
+ - If the user types a move that's clearly a chat message and not SAN ("hi", "what should I play"), respond conversationally without calling tools.
@@ -0,0 +1,22 @@
1
+ ---
2
+ name: resign
3
+ description: "Resign the current chess game"
4
+ ---
5
+
6
+ # /resign
7
+
8
+ 1. Call `mcp__sideboard__resign`.
9
+ 2. If the response contains `error: "No active game."`, tell the user there's no active game. Stop.
10
+ 3. Otherwise, render:
11
+
12
+ ````
13
+ ```
14
+ {board_render}
15
+ ```
16
+ ````
17
+
18
+ Then on subsequent lines:
19
+ - `**Chesster:** _{chesster_msg}_`
20
+ - A blank line.
21
+ - `**Game saved.** {stats summary as W:N L:N D:N}`
22
+ - The PGN inside a fenced block, no language tag.
@@ -0,0 +1,3 @@
1
+ """Sideboard — chess in your terminal."""
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1,5 @@
1
+ """Allow running as: python -m sideboard"""
2
+
3
+ from sideboard.cli import main
4
+
5
+ main()