shelley

Getting started

Installation

Get the binary, give it a model, serve it, keep it up to date, and run it as a service.

Shelley is a single executable for macOS and Linux, on amd64 or arm64. The web UI is embedded in it. Getting it running takes about three minutes, give or take a download: get the binary, give it a model, serve it.

Rather not install anything? Shelley comes running on exe.dev VMs: a machine of its own, already behind auth, no API keys required. Try it.

Get the binary

curl

This grabs the latest release for your OS and CPU:

os=$(uname -s | tr '[:upper:]' '[:lower:]')
arch=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
url=https://github.com/boldsoftware/shelley/releases/latest/download
curl -fLo shelley "$url/shelley_${os}_${arch}"
chmod +x shelley

Each release also has a checksums.txt. To check the download, in the same shell (use sha256sum if you don’t have shasum):

curl -fsSL "$url/checksums.txt" | grep "shelley_${os}_${arch}$"
shasum -a 256 shelley

The two hashes should match. Then put it on your PATH; the agent runs shelley itself to load skills and reach MCP servers:

sudo mv shelley /usr/local/bin/

Prefer clicking? Binaries and checksums are on the releases page.

Homebrew

The cask works on macOS and Linux and puts shelley on your PATH:

brew install --cask boldsoftware/tap/shelley

From source

You need Go (the version in go.mod), Node.js, and Python 3. The Makefile fetches the pinned pnpm through npx and downloads a pinned exe-scroll release from GitHub, so it needs network access too.

git clone https://github.com/boldsoftware/shelley.git
cd shelley
make

The binary lands in bin/shelley; copy it onto your PATH (for example, sudo cp bin/shelley /usr/local/bin/). If you’re hacking on Shelley itself, make serve builds the UI and runs Shelley from source.

Give it a model

Shelley picks up API keys from the environment. Set one or more:

export ANTHROPIC_API_KEY=sk-ant-...
export OPENAI_API_KEY=sk-...      # also enables voice recordings
export GEMINI_API_KEY=...
export FIREWORKS_API_KEY=...

Check what it found with shelley models. Self-hosted and other compatible endpoints can be added later from Manage… in the model picker. See Models and API keys for the details.

No key yet? shelley --predictable-only serve runs against a built-in fake model, so you can kick the tires for free.

Serve it

mkdir -p ~/.shelley
shelley --db ~/.shelley/shelley.db serve

Then open http://localhost:9000.

  • Pick a database path. --db defaults to shelley.db in the current directory, so starting Shelley from somewhere else gets you a fresh, empty database. Hence the fixed path above.

  • Flag order matters. Global flags (--db, --config, --default-model, --predictable-only, --debug) go before serve. Server flags (--port, -socket, -require-header) go after it. One dash or two, either works:

    shelley --db ~/.shelley/shelley.db serve --port 8080
    

    --port 0 picks a free port; add --port-file <path> to have Shelley write down the one it got.

  • Working directory. Your first conversation starts in the directory you launched Shelley from; after that, new ones default to the last directory you picked. You can change it per conversation.

  • The browser tool drives a local Chrome or Chromium if it can find one.

  • More flags. shelley -h and shelley serve -h list the rest; see also Command line.

Mind the door. Shelley is single-user and ships with no authentication and no sandbox. It runs commands as you, and it listens on all network interfaces. On a laptop, keep it behind a firewall, or put it behind something that does auth (a VPN like Tailscale, an authenticating proxy). Better yet, give it a machine of its own. See Running it safely.

Upgrading

A new release is cut automatically on every push to main that passes tests. Tags look like v0.N.9OCTAL, where N is the commit count and the digits after the 9 are the short (six-hex-digit) commit SHA in octal. shelley version prints what you’re running.

Shelley checks for new releases itself: the server fetches release metadata from boldsoftware.github.io/shelley when the UI loads (cached for six hours). If the latest release is five or more days newer than yours, a dot appears on the ⋮ menu.

To upgrade, open the ⋮ menu and choose Check for New Version. The Version dialog shows what changed and offers an upgrade button. Upgrading downloads the release binary for your platform, checks it against the release’s checksums.txt, and replaces the running executable in place. If you can’t write to that file, Shelley tries passwordless sudo. Then the process exits:

  • Under systemd, the button says Upgrade Shelley & Restart, and with a setup like the one below, systemd starts it again.
  • Otherwise it says Upgrade & Kill Shelley Server, and you start it again yourself.

Either way, conversations that were in the middle of a turn carry on once the new version is up.

The same dialog has an Auto-upgrade when idle (checks daily) checkbox, off by default. With it on, Shelley checks a minute after starting and then daily, waits up to an hour for a moment when no conversation is working, upgrades, and exits. That’s only useful if something restarts it.

On exe.dev, shelley install <vmname> in the exe.dev shell also works; see Shelley on exe.dev.

You can also upgrade by hand: download the new binary the same way you got the first one (or brew upgrade --cask shelley), and restart. To turn update checks off entirely, set SHELLEY_SKIP_VERSION_CHECK=true in Shelley’s environment.

Running it as a service

Shelley doesn’t ship a service file, but serve supports systemd socket activation with -systemd-activation: systemd owns the listening socket and hands it to Shelley. That is also the only way to have Shelley listen on one address, such as 127.0.0.1, rather than all of them. A minimal pair of units, modeled on how exe.dev runs Shelley (replace you with your user):

# /etc/systemd/system/shelley.socket
[Unit]
Description=Shelley socket

[Socket]
ListenStream=127.0.0.1:9000

[Install]
WantedBy=sockets.target
# /etc/systemd/system/shelley.service
[Unit]
Description=Shelley
BindsTo=shelley.socket
After=shelley.socket

[Service]
Type=exec
User=you
WorkingDirectory=/home/you
EnvironmentFile=/home/you/.shelley/env
ExecStart=/usr/local/bin/shelley --db /home/you/.shelley/shelley.db serve -systemd-activation
Restart=on-failure
KillMode=process

[Install]
WantedBy=multi-user.target

Put your API keys in the EnvironmentFile, one NAME=value per line, and chmod 600 it. Then:

sudo systemctl daemon-reload
sudo systemctl enable --now shelley.socket shelley.service
journalctl -u shelley -f

A few notes on those choices:

  • ListenStream=127.0.0.1:9000 keeps Shelley on loopback. Reach it through an SSH tunnel or a proxy (Running it safely), or use ListenStream=9000 for all interfaces.
  • WorkingDirectory is where your first conversation starts.
  • KillMode=process means restarting Shelley doesn’t kill the processes the agent started, like the dev server it just spun up.
  • Commands the agent runs inherit the service’s environment, including systemd’s short default PATH. Add an Environment=PATH=... line if your tools live elsewhere.
  • After an upgrade Shelley exits cleanly, so Restart=on-failure leaves it stopped. The socket stays open, and the next request starts it again.

Where files live

What Where
Conversations, settings, custom models, MCP servers The --db file, plus its -wal and -shm files
Terminal sessions terminals/, next to the database
Unix socket for the CLI ~/.config/shelley/shelley.sock (honors $XDG_CONFIG_HOME)
Hooks ~/.config/shelley/hooks/
Skills you create ~/.config/shelley/<name>/SKILL.md
Your customized Shelley’s source ~/.config/shelley/shelley-customization
Your AGENTS.md ~/.config/shelley/AGENTS.md, among other places
History of AGENTS.md edits made in the UI ~/.local/state/shelley/agents-md.git
Uploads, screenshots, recordings, browser downloads /tmp/shelley-*
Terminal helper binary (macOS only) ~/Library/Caches/shelley/

Uninstalling

Stop Shelley (and sudo systemctl disable --now shelley.socket shelley.service if you set up the units), then remove the binary and its data. Look before you delete ~/.config/shelley: your hooks, skills, AGENTS.md, and any customizations to Shelley itself live there.

sudo rm /usr/local/bin/shelley    # or: brew uninstall --cask shelley
rm -rf ~/.shelley                 # the --db directory used above
rm -rf ~/.config/shelley ~/.local/state/shelley
rm -rf /tmp/shelley-*
rm -rf ~/Library/Caches/shelley   # macOS only