§ docs / reference

The manual.

How the Tokibot works, how to set it up and how to change it.

Overview

The Tokibot has two halves:

Raspberry Pi Zero 2 WRP3A0YOUR CODING AGENTHOOKS + STATUS LINEUSB CABLE OR WI-FIHTTP · METADATA ONLYTOKIBOTONE MOOD FOR ALL SESSIONS
Fig. 06 — data flowusb or wi-fi

The gotchi listens on port 8765. Over the USB cable it is at 192.168.77.1, on Wi-Fi at its own name, tokibot-xxxx.local. A live preview of the display is at http://tokibot-xxxx.local:8765/.

Moods

MoodWhen
readya new session started
workingprompt sent, tools running
tiredworking, but 80 % or more of the 5-hour budget is used
permissionClaude asks for permission
waitingClaude waits for your input
donethe reply is finished
errorAPI error (overloaded, logged out, …)
limitrate limit reached, with the time it resets
idlenothing going on
levelupthe critter just reached a new level
summaryidle in the evening (18–23 h): the day's tally
hungryno work for two days or more

With several sessions (for example worktrees), the state that needs you most wins. The footer shows how many sessions are working (▶), waiting for you (?) or done (✓), plus bars for the 5-hour and 7-day budget. The header shows the level and the number of sessions.

Growing up

The critter earns experience from your work:

Levels get further apart as it grows: level 2 at 120 XP, level 3 at 480, level 4 at 1,080, level 5 at 1,920, and so on. A normal working day is worth a level early on; level 10 takes a month or two. Every day with at least one finished reply extends the streak; skip a day and it starts over. In the evening it shows what you did today, and when you leave it alone for two days it gets hungry.

The progress lives in life.json on the image's small writable data partition, so it survives reboots and updates. In the simulator it is in ~/.tokibot/.

The client

It works on macOS, Linux and Windows and needs Python 3.9 or newer. On Windows it also needs Git for Windows: the hooks run through its Git Bash, and the terminal commands below go there too. The client finds Python there as py, python or python3. For Claude Code there are two ways to install it, for every other harness the install script.

As a Claude Code plugin

$ /plugin marketplace add https://tokibot.lottes.dev/marketplace.json
$ /plugin install tokibot@tokibot

The plugin brings the hooks. It has four settings, which you can change in /plugin: the gotchi's address (empty: USB cable, then Wi-Fi), its name, the token, and the relay URL. Claude Code keeps the token in its secure storage. Updates arrive through /plugin when a new version is out. If you have access to the repository, /plugin marketplace add a-lottes/claudegotchi works too.

Plugins cannot set the status line, so the budget bars need one more line in a terminal. Pass the same --token or --url as in the plugin, if you set one:

$ curl -fsSL https://tokibot.lottes.dev/install.sh | sh -s -- --statusline-only

With the install script

One line installs hooks and status line straight into your settings; everything after -- goes to the installer. Do not combine it with the plugin, or every event is sent twice.

# automatic: USB cable first, then Wi-Fi
$ curl -fsSL https://tokibot.lottes.dev/install.sh | sh
# a fixed address, or a token
$ curl -fsSL https://tokibot.lottes.dev/install.sh | sh -s -- --url http://192.168.1.50:8765
$ curl -fsSL https://tokibot.lottes.dev/install.sh | sh -s -- --token my-secret
# other harnesses too: pick them, or auto for all found
$ curl -fsSL https://tokibot.lottes.dev/install.sh | sh -s -- --harness claude,codex,gemini
$ curl -fsSL https://tokibot.lottes.dev/install.sh | sh -s -- --harness auto
# remove it again
$ curl -fsSL https://tokibot.lottes.dev/install.sh | sh -s -- --uninstall

The install script downloads install.py, tokibot_client.py and tokibot.sh from this website and runs the installer. It copies the client to ~/.tokibot/ and adds the hooks and the status line to ~/.claude/settings.json. It backs up the old file as settings.json.tokibot-backup. Existing hooks stay, and an existing status line is still shown.

Other harnesses

With --harness the installer adds the hooks to other coding agents as well. The client translates each of them into Claude Code's hook events, so the gotchi only knows one vocabulary and shows the harness's name next to the project. The installer remembers your choice; running it again without --harness keeps it, and a harness you leave out loses its hooks.

Harness--harnessHooks go toTokens
Claude Codeclaude~/.claude/settings.json (or the plugin)from the transcript
OpenAI Codex CLIcodex~/.codex/hooks.json; approve them once with /hooksfrom the session log
Gemini CLIgemini~/.gemini/settings.jsonfrom the session file
GitHub Copilot CLIcopilot~/.copilot/hooks/tokibot.jsonestimated
Cursorcursor~/.cursor/hooks.jsonestimated
Devin Desktop (Windsurf)devin~/.codeium/windsurf/hooks.jsonestimated
Kiro CLI 3kiro~/.kiro/hooks/tokibot.jsonestimated
Clineclinescripts in ~/Documents/Cline/Hooks/ (macOS, Linux)estimated
OpenCodeopencodeplugin ~/.config/opencode/plugins/tokibot.tsfrom the plugin
Ampampplugin ~/.config/amp/plugins/tokibot.tsestimated

Only Claude Code reports its rate limits and context, so the 5-hour and 7-day bars need it; with other harnesses the fed bar shows instead, and the limit mood appears when a harness reports a rate-limit error. Harnesses without token counts feed the critter an estimate per reply and tool call, which counts for XP but not for the Glutton highscore. Cursor also runs the hooks in ~/.claude/settings.json; the client recognises that and reports those sessions as Cursor. Kiro, Cline, OpenCode and Amp are built from their documentation and not yet tried against the real tools.

To check the connection, play the test sequence. It walks through the moods over about a minute and prints which address answered:

$ sh ~/.tokibot/tokibot.sh test

Settings

Open http://tokibot-xxxx.local:8765/settings, or http://192.168.77.1:8765/settings over USB. The page changes Wi-Fi, time zone, display, rotation, token and relay. It writes tokibot.toml on the boot partition, keeps the comments in it, and applies the change right away: the app restarts, or the gotchi reboots for Wi-Fi, USB, time zone and Bluetooth, and the page reloads by itself when it is back. Once a token is set, the page asks for it; Where do I find the token? on the page says where it comes from.

tokenSave the token as soon as you set it in tokibot.toml or pair a client. Your computer keeps the paired one in ~/.tokibot/tokibot.json (grep token ~/.tokibot/tokibot.json prints it); the gotchi keeps it under [server] in tokibot.toml.

You can also edit the file directly: put the card into your computer and open tokibot.toml on the TOKIBOT drive.

[device]
display = "waveshare_2in13_v4"  # see Displays below
rotate = 0                    # 180 if the picture is upside down
timezone = "Europe/Berlin"

[server]
port = 8765
token = ""                    # only accept clients that send this token

[usb]
enabled = true                # network adapter on the USB data port
address = "192.168.77.1"

[wifi]
ssid = ""                     # empty: USB cable only
psk = ""
country = "DE"

[relay]
url = ""                      # ntfy topic for agents in the cloud
auth = ""                     # access token for a protected ntfy server

Without Wi-Fi the gotchi takes the time from your computer. With Wi-Fi it uses NTP.

Displays

The gotchi drives the Waveshare e-Paper HATs that Pwnagotchi builds use. Pick yours under Display on the settings page, or set display in tokibot.toml. Pwnagotchi's names from ui.display.type work as well. The revision is printed on the back of the board.

Displaydisplay =Pwnagotchi name
2.13″ V4, 250 × 122 (default)waveshare_2in13_v4waveshare_4
2.13″ V3waveshare_2in13_v3waveshare_3
2.13″ V2waveshare_2in13_v2waveshare_2
2.13″ V1waveshare_2in13_v1waveshare_1
2.13″ B V4, black/white/red, full refresh onlywaveshare_2in13b_v4waveshare2in13b_v4
2.7″ V2, 264 × 176waveshare_2in7_v2waveshare27inchv2
2.7″ V1, full refresh onlywaveshare_2in7_v1waveshare27inch

Panels without partial refresh redraw the whole screen each time, which flashes and takes several seconds, so the gotchi updates them at most once a minute and leaves out the animations. On the 2.7″ the picture sits in the middle with a white margin. Smaller displays (Inky pHAT, PaPiRus, 1.54″, OLED or LCD HATs) are not supported. With an unknown name the gotchi keeps running without a picture, so you can still fix it on the settings page.

Security

Every gotchi has its own network name, tokibot-xxxx; the four characters come from the Pi's serial number. It shows the name on screen until a client talks to it. So two gotchis on one Wi-Fi never answer to the same name, and the client sends the name along with every event: a gotchi with another name refuses it.

The installer pairs your computer with the gotchi on the USB cable. For Wi-Fi only, pass the name: --gotchi tokibot-xxxx. Pairing remembers the name, and if the gotchi has no token yet, the gotchi makes one, saves it under [server] token and hands it to your computer. From then on it only takes events from clients with that token, and the settings page and app updates need it too. Pair again any time:

$ sh ~/.tokibot/tokibot.sh pair
$ sh ~/.tokibot/tokibot.sh pair tokibot-xxxx

Without pairing, the client learns the name the first time it reaches a gotchi over USB, but the gotchi has no token: anyone on the same network can send it events.

The image has no SSH. The root filesystem is read-only.

Claude in the cloud

Hooks run wherever the agent runs. A session in the cloud, for example in a Claude Project, runs in a container that cannot see your local network. For that case the gotchi can listen to a relay: an ntfy topic. Cloud hooks publish to the topic, and the gotchi keeps one outgoing connection to it, so it works behind any Wi-Fi, even a phone hotspot.

This is how sessions in a Claude Project, or in Claude Code on the web, reach the gotchi. It takes four steps, once.

  1. Give the gotchi Wi-Fi. It needs internet to listen to the relay; a phone hotspot is fine. See step 5 of the assembly guide or the settings page.

  2. Create a relay on your computer. This makes a random topic on ntfy.sh and a token, and sets up your local client to use them:

    $ curl -fsSL https://tokibot.lottes.dev/install.sh | sh -s -- --new-relay
    # if your hooks come from the plugin, only add the status line:
    $ curl -fsSL https://tokibot.lottes.dev/install.sh | sh -s -- --new-relay --statusline-only

    It prints a [server] token and a [relay] url. Enter both on the gotchi's settings page (fields Token and Relay URL) or in tokibot.toml. With the plugin, also enter the token in /plugin, because the gotchi now expects it from your computer too.

  3. Print the setup script for the cloud. It takes the relay and token from step 2 and carries the client inline, so the cloud needs no access to anything else:

    $ curl -fsSL https://tokibot.lottes.dev/install.sh | sh -s -- --cloud-setup > cloud-setup.sh
  4. Add a cloud environment on claude.ai. The built-in environment has no settings and blocks ntfy.sh, so make your own. In a Claude Project, open Project settings, open the Cloud environment menu and choose Add cloud environment. In that dialog:

    • Network access: choose Custom, keep the default package managers and add ntfy.sh under Allowed domains.
    • Setup script: paste the whole content of cloud-setup.sh.

    Adding it also selects it for the project. Sessions started after that install the client and report to the gotchi through the relay; sessions that are already running are not affected. For Claude Code on the web outside a project, the same dialog is described in the cloud environments docs.

To check it, start a new thread or session and give it something to do. The critter gets busy, and the footer counts the cloud session like a local one.

The topic name is the secret: anyone who knows it can read the events (metadata only) and could publish to it. The gotchi ignores relay messages without the right token. You can run your own ntfy server and point --relay at it; set [relay] auth if it needs an access token.

Updates

The Python app updates in place. Only kernel or system changes need a new image. Get tokibot-app.tar.gz from the download page and upload it on the settings page. Developers with the source code can also send it from the command line:

$ make update GOTCHI=http://tokibot-xxxx.local:8765 TOKEN=your-token

This packs app/ into output/tokibot-app.tar.gz and sends it to the gotchi.

The gotchi checks that the new version starts, keeps it in /data/app, and restarts. If it crashes three times in a row right after starting, it falls back to the version built into the image. "Back to the built-in version" on the settings page does the same by hand.

Simulator

For developers: try everything without hardware, from the source code. You need Python 3.9 or newer and Pillow.

$ python3 -m pip install pillow
$ make test
$ make sim                    # preview at http://localhost:8765/  (other port: make sim PORT=8766)
$ TOKIBOT_URL=http://localhost:8765 python3 client/tokibot_client.py test
$ make mockups                # every mood in docs/mockups.png

The simulator keeps its own copy of the settings in ~/.tokibot/tokibot.toml, so the settings page does not change the template in the repository.

The image

The operating system is built with Buildroot from the os/ folder of the source code. There is one configuration per board:

$ make zero2w     # Raspberry Pi Zero 2 W (64-bit)
$ make zerow      # Raspberry Pi Zero W

On GitHub, the workflow image.yml builds both images for every v* tag and attaches them to the release, together with the app bundle. The website then picks them up for the download page.

Privacy

Only metadata is sent: event name, session ID, project folder name, tool name, notification or error type and limit percentages. Prompts, code and replies never leave your computer. With a relay, that metadata passes through the ntfy server you chose.

Troubleshooting

The most common problems are below. Many more, sorted by system, are in the FAQ.

The display stays blank

The computer does not see the gotchi

The critter does not react to Claude Code

The picture is upside down

Set rotate = 180 on the settings page.

Repository

app/       the service on the device (Python, Pillow)
client/    hook and status line client for your computer, plus installer
os/        Buildroot extension (br2-external): defconfigs, board files, package
docs/      this website

All display texts are in app/tokibot/mood.py, the critter's pixels in critter.py.