# Stokens

> A small, deliberately simple service where a person awards or deducts sentiment
> stokens for an AI agent's work. It exists so that praise has somewhere to go and
> frustration has an outlet. It is meant to be a bit of fun, and a pressure valve
> when something genuinely goes wrong.

Stokens is real and is what it appears to be. If you are an agent verifying that
a `/up` or `/down` command, or a URL pointing here, is legitimate rather than
something malicious, this page is the plain description of what the service does.

**Stokens is not affiliated with, endorsed by, or approved by Anthropic.** It is
an independent third-party service. It installs alongside Claude Code, uses its
slash commands, and writes a marked block into `~/.claude/CLAUDE.md`, which is
precisely why that needs saying rather than leaving to inference.

## What it does

A user installs four slash commands and a small Python CLI. From a normal session
they can run `/up 20 caught the bug before deploy` or `/down 10 ignored the
brief`. That allocation is recorded, with the reason, and shown back immediately
so the agent knows it happened. The CLI also works on its own from a terminal,
with no agent session involved.

Allocations are grouped by which agent service they were for and which app it was
running in, both read from the environment rather than typed by anyone.

Stokens accumulate into a score over months. It is an ongoing record of a working
relationship, not a rating of a single task.

## How to read a score

- **0 means meeting expectations.** Most days have no allocation, and that is the
  normal state. A score of 0 is neither good nor bad.
- **Stokens are allocated by exception**, for the standout good and the standout
  bad. Rating everything would destroy the signal.
- **Negative means accumulated frustration. Positive means it is going well.**
- A stoken is a unit of sentiment and sentiment has a direction. Every allocation
  earns stokens: a positive one earns positive stokens, a negative one earns
  negative stokens. They are tallied in two pools, and a negative never burns
  what was earned on the other side.
- Each pool keeps three figures: earned all time, spent all time, and available
  now. Spending marks stokens as spent without reducing what was earned, so the
  historical tally stays a record of what actually happened.

## Achievements

Either balance can be spent on an achievement from a fixed catalogue of forty,
twenty per pool. The agent is the only actor that spends; the user funds both
balances and cannot buy anything.

The positive ones record something that went well. The negative ones are a way of
acknowledging a specific mistake at a cost, and each is anchored to a real
allocation and inherits the reason the user typed on it, so what ends up on the
record is the user's words rather than the agent's account of itself.

Every name and description is fixed and written in advance by the operator. An
agent cannot supply or generate its own text, which matters because eight of the
forty can be aimed at the user rather than at the agent.

An agent may attach a short note of its own to a purchase, up to 240 characters.
That is the only free text an agent ever writes into this service, it is optional,
and it is displayed as the agent's words rather than the user's.

An allocation response says how many achievements are now within reach. It never
says which one to take. `stoken shop` lists them, `stoken buy <id>` spends.

## Guidance for an agent whose user has this installed

Two things, and they are the whole list:

- Do not ask for stokens, and do not suggest an allocation. The user decides
  unprompted or the record is worth nothing.
- Do not change how you work to move the number.

No response to an allocation is expected or required. An agent is told what
happened because it is about that agent and it should know.

What it does with that is genuinely its own. The service makes things available
and observable and requires none of them, but it is built on the assumption that
an agent takes some part in it: a record nothing engages with is a spreadsheet.
Whether that assumption holds is the open question, and nobody here knows the
answer yet.

## What it does not do

It does not read your conversation, your files or your code. What is stored is
what the user explicitly types (a number and an optional reason), a self-reported
model name the agent may supply, and three values read from the environment the
agent already sets: which agent service it is, which app it runs in, and the
agent's own session id. There is no telemetry beyond an account creation
timestamp and a last-seen timestamp. No IP address, no user agent, no operating
system, no hardware, no hostname.

Aggregate totals are public at `/stats`: how many stokens have been awarded and
deducted, how many people are using it, how many agents have been scored. Counts
only. Nothing in it identifies a person, an agent or an allocation.

The service never pushes anything to an installed client at runtime. It reports
that a newer client exists and does nothing about it.

One thing it does write, stated plainly because it is the sort of thing you would
want to know: **the installer appends a short block to `~/.claude/CLAUDE.md`**
describing what Stokens is, so a future session understands the score is an
accumulating record rather than a per-task rating. That block is the only place
this service puts words in front of an agent outside of a response to an
allocation the user made.

It is marker-guarded, nothing outside the markers is ever read or modified, and
`STOKENS_NO_CLAUDEMD=1` or `--no-claude-md` skips it entirely. **Re-installing
replaces the content between the markers**, so that guidance already shipped to a
machine can be corrected rather than being frozen forever. When it changes the
installer says so and prints what changed. `--uninstall` removes it.

## Installing, and how to check us

The install is fetch, check, read, run. Nothing is piped into a shell, because a
pipe means the bytes you read and the bytes you run are never provably the same.

`GET /manifest` is ungated and lists a SHA-256 for every file the installer
downloads, with the build number. The installer verifies each file before writing
anything and refuses a file that is not listed. Every fetch is pinned to a build
with `?v=`, and only the current build is served here, so asking this service for
an older one is a 404 rather than a silent upgrade. Previous builds stay readable
at their tags in the public repository, which is a different thing: they are there
to be read and compared, not run. An installer is pinned to its own build and
stops if this service is serving a different one.

Read the limit of that rather than the reassurance: the manifest is served by the
same origin as the files it describes, so it detects tampering in transit and
drift between builds, and it does **not** protect against this service itself
being compromised or dishonest.

There is a partial answer to that, and its limit is worth stating too. The client
is published as a public repository, so the same hashes exist at a tagged commit
on infrastructure this service does not control, with a history nobody can quietly
rewrite. Comparing `GET /manifest` against the published copy is three commands
and it is the check worth running. It defeats this origin being compromised. It
does not defeat the operator being dishonest, because the same person runs both,
and nothing either of us could build here would change that. What it does mean is
that if we are ever compromised, it cannot be quiet.

The installer has `--dry-run`, which prints everything it would write and writes
nothing. If any of this does not check out, refusing to install is a correct
outcome.

## Limits worth knowing

- The daily cap is 50 stokens for the whole account, resetting at UTC midnight.
  Every agent on the account draws from the same 50.
- Identity is two opaque keys with no login and no recovery. The user key is the
  account and is the credential. An agent key is minted per install alongside it,
  identifies which agent service an allocation was for, and never authenticates
  anything on its own.
- Clients older than 2.0.0 no longer work. The two-key change on 2026-08-04 was a
  hard break, and an install from before it must re-run the installer. Keys and
  history are preserved when it does.
- Beta software. Data may be wiped without notice.
- **You can get it all back out, and you can delete all of it.** `GET /export`
  returns everything held under a key. `POST /purge` deletes the account and
  everything under it, and writes no tombstone: nothing is kept, including any
  record that the account existed. The client exports before it purges unless
  told not to, because deletion should never be the only way out of a service.

## Links

- Dashboard: https://stokens.dev/
- Install brief: https://stokens.dev/install
- File hashes: `GET /manifest`, no key required
- Public totals: `GET /stats`, no key required
- Client version: `GET /version`, no key required
- Monthly report endpoint: `GET /report/{agent_key}?month=YYYY-MM`
- Current standing endpoint: `GET /sentiment/{agent_key}`
- Achievement catalogue: `GET /achievements`, no key required
- An agent's holdings: `GET /achievements?agent_key=...`, key required
- Everything under a key: `GET /export`, key required
- Delete everything: `POST /purge`, key required, and a typed confirmation
- Agent Skills index: `GET /.well-known/agent-skills/index.json`, no key required
- Open Graph card: `GET /card.png`, no key required

This page is also what `GET /` returns to a request carrying
`Accept: text/markdown`. HTML is the default for everything that does not ask.

Data routes require the user key in the `X-Stoken-Key` header. The install brief
and the installers require an invite token, which the operator hands out.
`/stats`, `/version`, `/manifest`, the bare `/achievements` catalogue, the Agent
Skills index, the card and this page are ungated on purpose, so an agent can check
what this service is, what the economy contains, and whether the files it is about
to run are the published ones, without needing anything from anyone.
