shelley

Using Shelley

Conversations

How the web UI is organized and used day to day: conversations, models, directories, the composer, recordings, subagents, diffs, terminals, and context.

Shelley’s UI is a list of conversations on the left and the current one on the right: transcript, a status line, and the composer. The header has buttons for the diff viewer, the git graph, the terminal, a new conversation, and an overflow menu. Most things are also in the command menu (Ctrl+K, or ⌘+K on a Mac).

One conversation, one agent

Each conversation is its own agent loop with its own model, reasoning level, tool settings, and working directory. Several can work at once; they don’t share context. A conversation lives at /c/<slug>, where the slug is generated from your first message. Rename it from its row menu or with /rename <new-slug>.

  • New: the + button, or /new [first message].
  • Drafts: a new conversation’s unsent text is saved on the server and shows up in the list as draft, so it follows you to another device. Unsent text in an existing conversation is kept in the browser’s local storage.
  • Fork: /fork, or Fork conversation from here on any message, copies the conversation up to that point into a new one.
  • Archive: the row menu, /archive, or Ctrl/⌘+Shift+X. View Archived at the bottom of the list restores or permanently deletes.
  • Search: the magnifier above the list searches message text and slugs across active and archived conversations. Type tag: to filter by tag; tags are set from the row menu. The list can also be grouped by directory, git repository, or tag.
  • Export: Ctrl/⌘+Shift+E opens the conversation as editable Markdown you can download.

Conversations, messages, and settings are stored in the SQLite database you pass with --db. It runs in WAL mode, so expect shelley.db-wal and shelley.db-shm next to it.

Model, reasoning, tools, and profiles

Click the model name in the status line (or the picker above the composer, before the first message). The picker sets:

  • Model: any model Shelley has configured. See Models and API keys.
  • Reasoning effort: one of off, minimal, low, medium, high, xhigh, max, limited to the levels the model supports, with the model’s default preselected (auto appears when Shelley can’t tell what the default is). The model’s thinking shows in the transcript as a collapsed 💭 block.
  • Tools: each tool on, off, or at its default. See Tools.
  • Profile: a named bundle of model, reasoning, tool settings, and system prompt. One profile is the default for new conversations. Editing a profile later does not change conversations that already used it.

You can switch models mid-conversation. The picker is disabled while a turn is running; stop it or wait. You can also type /model to see the current settings, or /model <model> [level] to change them. Names match leniently: a unique prefix or fragment of a model ID works, and an ambiguous one gets a list of candidates. Each change leaves a marker in the transcript.

Working directory

A new conversation’s directory is set in the Dir: field above the composer. It defaults to the last directory you picked in this browser, then the most recent conversation’s, then the directory shelley serve was started in. After that, click the directory in the status line to change it (when the agent is idle), or let the agent move with its change_dir tool. The command menu can also start a conversation in a new git worktree.

The composer

Enter sends, Shift+Enter adds a newline (on touch screens Enter adds a newline and you tap Send). Type @ to complete file and folder names from the working directory; this inserts a path, not the file’s contents. Type / for commands:

Command What it does
/btw <question> Ask a side question without disturbing the main thread (below)
/tour [hash] Build a commit tour
/fork, /new, /archive, /rename As above
/diff Open the diff viewer
!<command>, /shell Run a command in the terminal panel; ! alone opens a shell
/compact [instructions] Compact the context (below)
/clear Start fresh context in the same conversation
/transcription <path> Transcribe an uploaded recording

You can add your own slash commands with hooks.

Files and images. Paste, drag, or attach files (up to 1 GiB). They are uploaded to /tmp/shelley-uploads on the server and their paths are added to your message in brackets; the agent opens them with its tools (read_image for pictures). Click any image in the transcript, drag a box, and type a comment: Shelley inserts a quote naming the image and the region as ImageMagick geometry, so the agent can crop exactly what you meant.

Sending while the agent works. A message sent mid-turn reaches the model at its next request; the turn isn’t interrupted. To hold it until the turn ends instead, use the arrow next to Send and choose Queue after agent finishes. Queued messages wait at the bottom of the transcript with Send now (interrupts the turn) and Cancel. Stop cancels the turn, kills a running foreground command, and stops the conversation’s working subagents.

If Shelley restarts mid-turn, the status line says Conversation Interrupted with a Continue button. An unfinished tool call may run again. After a restart to install an upgrade, Shelley continues the turn on its own and leaves a warning in the transcript saying so.

Voice and screen recording

The record button next to the composer records your voice, or your voice and screen (Ctrl/⌘+Shift+M for voice; add Alt/⌥ for screen). When you stop, the recording is uploaded and transcribed, and the transcript is sent as your message, after anything you had already typed. A screen recording also gets a 12-frame contact sheet, and the message includes the paths to the video, the sheet, and word timestamps, so the agent can line up what you said with what you pointed at.

It needs a few things:

  • A transcription route: OPENAI_API_KEY, or an exe.dev LLM integration, set before Shelley starts (other routes are in Models and API keys). Without one, the button explains that instead of recording.
  • ffmpeg and ffprobe on the server’s PATH. Every recording is probed with ffprobe.
  • A browser that allows it: microphone access needs HTTPS or localhost, and Voice & Screen only appears where the browser supports screen capture.

The diff viewer has its own record button for narrated reviews: talk through a diff, and Shelley sends the transcript along with a log of what was on screen and selected as you spoke.

Subagents and side questions

When the agent delegates with its subagent tool, each subagent is a full conversation. It appears nested under its parent in the list (the number badge expands or collapses them), and the tool card in the parent shows what it’s doing live. Open it like any other conversation. Its reports arrive in the parent’s transcript, attributed to it. Only top-level conversations can have subagents.

/btw <question> asks a side question. A read-only helper answers from a frozen copy of the conversation’s context, inline, without adding to the main thread. You can ask it to summarize the exchange into your composer.

Diffs, git graph, and terminal

Diffs (Ctrl/⌘+Shift+D) shows working changes, a single commit, or a range, side by side, with a file tree. In comment mode, line comments go into your composer, and ./, step through changes and </> through files; edit mode saves your edits to disk; there’s a Vim toggle. Edits made with the patch tool also render as diffs in the transcript; changes made through shell commands only appear in the viewer. When a turn moves HEAD, a “now at <hash>” line appears with links to the diff and its tour.

Git graph (Ctrl/⌘+Shift+G) shows branches and history for the conversation’s repository, with commit details, Open diff, and tour badges.

Terminal (Ctrl+`) opens a real shell in the conversation’s directory. Terminal sessions are persistent: they survive page reloads and Shelley restarts, and are kept in a terminals directory next to the database. A terminal can belong to one conversation or show in all of them. Buttons on the panel copy its output or insert it into the composer.

Context and compaction

Every request sends the conversation’s context to the model again, so long conversations get slower, worse, and quadratically more expensive. The token count in the status line is the current context size. Click it for token and cost graphs. It changes color at 100k, 200k, and 300k tokens (or 70, 80, and 90% of a known context window). Nothing is compacted unless you ask:

  • /compact [instructions] summarizes older messages, keeps roughly the last 20k tokens verbatim, and carries on in the same conversation. This starts a new generation: from then on, only the current generation (the summary plus what follows) is sent to the model. Earlier messages stay visible in the transcript. Ctrl/⌘+Enter (or Compact and send under the Send arrow) compacts and then sends.
  • /clear starts fresh context in the same conversation, with no summary.
  • Auto compaction, a switch in the Tools dialog, gives the agent the compact_in_place tool and nudges it once context passes a threshold you pick there (250k by default), and again every 50k tokens after that. It collapses old ranges into short notes and trims old tool output; the originals stay in the database.

Notifications and phones

The overflow menu turns on browser notifications for when a tab is hidden. The command menu’s Notification Settings adds server-side channels: a Discord webhook, ntfy, or email (on exe.dev). The layout works on a phone: the list becomes a drawer, and voice recording works if the page is served over HTTPS.