Skip to main content

A Claude Code hook that opens a Lichess puzzle in your terminal while Claude is working.

Project description

hook-my-lichess

A Lichess puzzle that floats over the same terminal Claude Code is running in. While Claude is working, the puzzle hovers in the top-right corner. You play moves by typing p:<move> as a prompt — including while Claude is mid-response — and the board updates live, no PTY proxy, no wrapper binary in the launch path.

How it works (v6, sidecar architecture)

Claude Code owns its terminal end-to-end. There is no wrapper. The overlay lives in a sibling process:

  • Hook-launched daemon. A UserPromptSubmit hook calls hml-overlay start, which double-forks a Python daemon that opens /dev/tty for writes and emits Kitty graphics escapes. Claude is never resized, never has its I/O intercepted.
  • Independent 16 ms redraw clock. The daemon re-emits kitty_place(image_id, p=1) on its own timer, decoupled from Claude's stdout — so the image snaps back above scrolls without waiting for Claude to emit a byte.
  • Two input surfaces. A turn-boundary path via the UserPromptSubmit hook (p:<move> is intercepted with decision: "block" so the prompt never reaches Claude). And a mid-turn path via the daemon tailing Claude Code's session JSONL transcript at ~/.claude/projects/<project>/<session>.jsonl for queue-operation enqueue and attachment.queued_command records — Claude Code logs queued user input the moment you type it, so the daemon dispatches mid-turn moves with no documented hook involvement at all. An 8-second dedup window swallows the duplicate when UserPromptSubmit later replays the same prompt.

See docs/v5-wrapper-vs-v6-sidecar.md for the full architecture comparison and the bugs that drove the rewrite.

Install

hook-my-lichess is distributed as a Claude Code plugin. Two slash commands and you're done.

Prereqs (one-time):

# uv runs the Python daemon on demand and caches it
curl -LsSf https://astral.sh/uv/install.sh | sh

# Lichess personal token, see https://lichess.org/account/oauth/token
export LICHESS_TOKEN=lip_xxxxxxxxxxxxxxxx   # add to your shell rc

Install in Claude Code:

/plugin marketplace add 0JCRG0/hook-my-lichess
/plugin install hook-my-lichess@jcrg-tooling

That's it. The next prompt you submit will fire the hooks; uvx fetches hook-my-lichess from PyPI on first run (~2 s) and caches it. Subsequent invocations are instant.

The daemon auto-detects whether the terminal supports Kitty graphics (Ghostty / Kitty / WezTerm); on terminals that don't (iTerm2, Terminal.app, tmux), it exits silently — Claude works as normal.

Playing the puzzle

Submit any prompt to Claude. The board appears in the top-right within ~1 s.

Type a puzzle command as your prompt:

  • p:e2e4 — submit a UCI move
  • p:Nf3 — submit a SAN move (piece letters uppercase: Nf3, not nf3)
  • p:hint — hint (which square the piece moves from)
  • p:solve — give up and reveal the move
  • p:quit — close the puzzle

The hook intercepts these (decision: "block") so Claude never sees them. You can also type them while Claude is mid-response — they'll queue, the daemon's transcript tailer will pick them up within ~100 ms, and the board updates without waiting for Claude's turn to finish. (Anything that doesn't start with p: passes through to Claude untouched.)

When Claude finishes its turn, the banner flips to "✓ Claude is done" and you can keep solving at your own pace.

Customizing the board (size & position)

Generate a default settings file:

uvx --from hook-my-lichess hml-overlay init-config
# wrote default settings to ~/.config/hml/settings.json

Edit ~/.config/hml/settings.json:

{
  "size": "xxl",
  "position": "center"
}
  • size — one of "small" (0.75×), "medium" (1×, default), "large" (1.25×), "xl" (1.5×), "xxl" (2×), or any positive number for an exact scale (e.g. "size": 1.7).
  • position — one of "top-right" (default), "top-left", "bottom-right", "bottom-left", "center", or a [row, col] pair for an exact 1-indexed cell (e.g. "position": [3, 80]).

The daemon checks three locations in order: $HML_CONFIG, then <cwd>/hml.json, then ~/.config/hml/settings.json. The per-user file is the one you usually want.

Developing locally

If you want to hack on the overlay itself instead of just using it:

git clone https://github.com/0JCRG0/hook-my-lichess
cd hook-my-lichess
python3 -m venv .venv
.venv/bin/pip install -e .
cp .env.example .env   # put LICHESS_TOKEN here

The hooks in this repo's .claude/settings.json reference $CLAUDE_PROJECT_DIR/hooks/*.sh, and those scripts prefer the local .venv/bin/hml-overlay over uvx when present — so working inside this repo always uses your in-tree code, no rebuild needed.

If you also have the marketplace plugin installed, disable it for this repo (/plugin disable hook-my-lichess) so hooks don't double-fire.

Force-enable the overlay (debugging)

Set HML_FORCE_OVERLAY=1 to bypass the terminal-detection heuristic and always emit Kitty graphics escapes.

HML_DEBUG=1 writes diagnostic lines to /tmp/hml-sidecar-debug.log.

Standalone puzzle (no Claude, no overlay)

Same engine, plain stdin loop:

.venv/bin/lichess-puzzle

Useful for exercising engine.py, board.py, api.py, render.py without touching the overlay code path.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

hook_my_lichess-0.1.3.tar.gz (58.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

hook_my_lichess-0.1.3-py3-none-any.whl (24.0 kB view details)

Uploaded Python 3

File details

Details for the file hook_my_lichess-0.1.3.tar.gz.

File metadata

  • Download URL: hook_my_lichess-0.1.3.tar.gz
  • Upload date:
  • Size: 58.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for hook_my_lichess-0.1.3.tar.gz
Algorithm Hash digest
SHA256 7df0749037d54085c0070d620526b10a7f00c08b724af58c70c84c23f0b317fe
MD5 58147944f79740e134c52fb3f08df1cc
BLAKE2b-256 18775882d7fa4bac461fabdda98db3c064f0eb5d43dba7932e760cb2d4fb3375

See more details on using hashes here.

Provenance

The following attestation bundles were made for hook_my_lichess-0.1.3.tar.gz:

Publisher: release.yml on 0JCRG0/hook-my-lichess

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file hook_my_lichess-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: hook_my_lichess-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 24.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for hook_my_lichess-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 eee3ff4e7a32c3a7eb98594f0b7369e20a1493dd6dbe9d5f1fea4f7167b825f4
MD5 cc96d0c9a7a564fa7a87b21b021124ef
BLAKE2b-256 e577d82f21a0a5975849336800462f7f55d56252a38a63287fd1fb95b1415878

See more details on using hashes here.

Provenance

The following attestation bundles were made for hook_my_lichess-0.1.3-py3-none-any.whl:

Publisher: release.yml on 0JCRG0/hook-my-lichess

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page