CLI Reference
Commands, global options, and the environment the CLI reads.
The CLI is butters, a standalone tool in its own repo, getbutters-cli .
Install
curl -fsSL https://raw.githubusercontent.com/freekrai/getbutters-cli/main/scripts/install.sh | bash
export GETBUTTERS_API_KEY=ev_... # from /app/api
butters list The installer detects your platform and architecture, downloads the matching binary from the latest release , checks it against the release's SHA256SUMS, and puts it in ~/.local/bin, telling you if that is not on your PATH. Set BUTTERS_BIN_DIR to install somewhere else, or BUTTERS_VERSION (e.g. v0.1.0) to pin a release:
curl -fsSL https://raw.githubusercontent.com/freekrai/getbutters-cli/main/scripts/install.sh \
| BUTTERS_BIN_DIR=~/bin BUTTERS_VERSION=v0.1.0 bash To download a binary yourself instead, there are builds for macOS (Apple silicon and Intel), Linux (x64 and arm64) and Windows (x64), and none of them need a runtime installed:
curl -fLo butters https://github.com/freekrai/getbutters-cli/releases/latest/download/butters-darwin-arm64
chmod +x butters
mv butters /usr/local/bin/ Swap butters-darwin-arm64 for butters-darwin-x64, butters-linux-x64, butters-linux-arm64 or butters-windows-x64.exe to match your machine. Each release also has a SHA256SUMS file for checking the download. The macOS binaries are unsigned: one fetched with curl (including by the installer) runs as is, but one downloaded through a browser may be blocked by Gatekeeper; clear the quarantine flag with xattr -d com.apple.quarantine /usr/local/bin/butters.
Usage
butters <command> [options] It is a remote HTTP client. It never opens the database — every command goes through the same authenticated API an outside integration would use, and the same organization scoping applies. That includes export and load.
Consequences worth knowing up front:
- The server must be reachable for every command, including
exportandload. - Everything needs an API key, and the key decides which organization you are operating on.
Global options
Every command takes these, after the command name.
| Option | Description |
|---|---|
|
| Base URL of the server. Defaults to |
|
| API key. Falls back to the |
Create a key from the API page (/app/api → New key). It is shown once, so put it somewhere before you navigate away:
export GETBUTTERS_API_KEY=ev_a1b2c3d4-e5f6-a7b8-c9d0-e1f2a3b4c5d6 EVENTS_API_KEY is the variable's name from before the rename; it is still read, so existing setups keep working. An empty variable counts as unset.
To use a self-hosted server, pass --url:
butters list --url https://butters.example.com butters --version prints the version, and butters <command> --help lists a command's options.
Unreachable servers are reported as such rather than as a stack trace; HTTP errors surface as error: <status>: <message> from the API's own error body. Every failure exits non-zero.
Commands
init
Create a project.
butters init --name "my-store" | Option | Required | Description |
|---|---|---|
|
| yes | Project name |
Prints the new project's name and id. The id is what every other command means by --project.
push
Push an event.
butters push \
--project q4q8nb18qc2i \
--category orders \
--title "Order Placed" \
--description "Order **#1234** by John" \
--icon "📦" \
--link "https://shop.example.com/orders/1234" \
--user-id "user-123" \
--notify | Option | Required | Description |
|---|---|---|
|
| yes | Project ID |
|
| yes | Category name (auto-created if new) |
|
| yes | Event title |
|
| no | Supports |
|
| no | Emoji icon |
|
| no | URL the event title opens. Not |
|
| no | External user identifier |
|
| no | JSON object or array, opened in a dialog from the feed. Parsed before sending, so a broken quote is reported here rather than as a |
|
| no | Highlight in the feed and send to the project's ntfy and webhook destinations |
There is no --tags yet, so tags can only be set over the API.
--metadata is the one to reach for when a script is reporting an error:
butters push \
--project q4q8nb18qc2i \
--category errors \
--title 'Nightly build failed' \
--metadata '{"job":"nightly","exit":1,"tail":["make: *** [build] Error 1"]}' Shell quoting is the usual trap — single-quote the whole JSON document so the double quotes inside it survive. See tags vs metadata for which of the two to use.
insight
Create an insight card, or update the one with the same title, via POST /api/insight.
butters insight \
--project q4q8nb18qc2i \
--title "24h Sales" \
--value '$1,449' \
--icon "☀️" | Option | Required | Description |
|---|---|---|
|
| yes | Project ID |
|
| yes | Card title. It is the card's key within the project: setting the same title again updates that card |
|
| yes | Value to display. Sent as text, so |
|
| no | Emoji icon, up to 16 characters. Left unchanged when an update leaves it out |
Prints set <title> = <value>. Single-quote values with a $ in them, or the shell will expand it.
There is no delete command yet: the API deletes insights by id, and nothing returns those ids. Delete a card from the dashboard.
list
List the projects in this organization.
butters list Prints <id> <name> per project, or no projects yet.
export
Write this organization's data to a JSON file, via GET /api/export.
butters export --file backup.json | Option | Required | Description |
|---|---|---|
|
| yes | Output file |
Prints the project and event counts it wrote.
load
Load a JSON document into this organization, via POST /api/import.
butters load --file demos/bakery.json | Option | Required | Description |
|---|---|---|
|
| yes | JSON file to load |
This never replaces anything; merging is all it does. Import mints fresh project ids, so loading the same file twice creates two independent projects rather than overwriting the first. The command prints the was -> now id mapping the API returns, which is the only way back to whatever the file called things.
Demo Scenarios
Pre-built scenarios live in the `demos/` folder of the CLI's repo, each spanning 30 days, each in exactly the shape POST /api/import accepts. They let you show the app off without using real data.
| Scenario | File | Contents |
|---|---|---|
| Proofing Room |
| Micro-bakery: preorders, oven batches, pickups, sell-outs |
| Mothlight Games |
| Indie game launch: players, achievements, crashes, wishlists |
| Attic Rack |
| Homelab: backups, UPS power, disk health, network |
| Countersign |
| E-signature SaaS: trials, billing, signed documents, integrations |
| Fernhill Greenhouse |
| Greenhouse sensors: climate, irrigation, harvests, frost alerts |
| All |
| All five combined |
From a clone of the repo:
# Load everything
butters load --file demos/all-scenarios.json
# Load one scenario
butters load --file demos/bakery.json
# Regenerate with fresh random data
bun run demos:generate Or fetch just the one you want:
curl -fLO https://raw.githubusercontent.com/freekrai/getbutters-cli/main/demos/bakery.json
butters load --file bakery.json demos/generate.ts writes all six files. Event times are stamped relative to when it runs, so regenerate before a demo if you want the charts to end today. Event counts move between generations — each category draws a random number of events per day — so expect roughly 350 to 1,000 events per scenario rather than a fixed figure.
Loading a scenario counts against your plan's monthly event allowance, and a single scenario carries more events than the free tier allows.
Agent Skill
The CLI's repo ships an Agent Skill in `skills/butters` that teaches coding agents (Claude Code, Codex, Cursor and others) to drive butters: looking up project ids instead of guessing, quoting --metadata, why load duplicates rather than replaces, and when to ask before notifying or loading demo data.
Install it with the skills CLI , which detects the agents you have and asks where to put it:
npx skills@latest add freekrai/getbutters-cli --skill butters Add -g to install it for every project rather than just the current one, and -a claude-code (or another agent) to skip the agent prompt:
npx skills@latest add freekrai/getbutters-cli --skill butters -g -a claude-code The skill assumes butters is on the PATH and a key is in GETBUTTERS_API_KEY.
Examples
Track an e-commerce order flow:
export GETBUTTERS_API_KEY=ev_a1b2c3d4-e5f6-a7b8-c9d0-e1f2a3b4c5d6
PROJECT=$(butters init --name "my-store" | awk '/id:/ {print $2}')
butters push --project $PROJECT --category signups --title "User Registered" --icon "👤" --user-id "user-42"
butters push --project $PROJECT --category orders --title "Order Placed" --description "Order **#1001**" --icon "🛍️" --user-id "user-42"
butters push --project $PROJECT --category shipping --title "Order Shipped" --icon "🚚"
butters push --project $PROJECT --category shipping --title "Order Delivered" --icon "📦" --notify Keep a KPI card current, e.g. from a nightly job:
butters insight --project $PROJECT --title "24h Sales" --value '$1,449' --icon "☀️"
butters insight --project $PROJECT --title "Orders Processing" --value 23 --icon "🏭" Back up nightly:
butters export --file "backups/$(date +%F).json"