Shelley: a web-based coding agent you talk to from a phone
Shelley is a coding agent
At a glance
- What is it?
- Shelley is a Go and TypeScript coding agent with a browser UI, server-sent events for live updates and SQLite for storage, built for but not limited to exe.dev. It suits a developer who wants a coding agent that runs next to the compute, and it is the wrong choice for anyone who needs authorization or sandboxing, since the project explicitly ships neither.
- Who is it for?
- Shelley fits a developer who wants a coding agent with a mobile-friendly web interface, several conversations in flight at once and the ability to swap the underlying model, especially on a host where the agent should run close to the compute it is driving.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A coding agent as a web app, and the design choices behind that
Shelley is described as a mobile-friendly, web-based, multi-conversation, multi-modal, multi-model, single-user coding agent, built for but not exclusive to exe.dev. The project description puts the caveat in the same breath as the feature list: it does not come with authorization or sandboxing, bring your own.
Each adjective in that list is a design decision with a reason attached, and the reasons are given in the project documentation in a tone that suggests they have been argued over.
Mobile-friendly because ideas can come any time. Web-based because terminal-based scroll back is described as punishment, and the project notes that this is shoplifting in some countries, which is a specific and non-negotiable constraint for some of its users. Multi-modal because screenshots, charts and graphs are necessary. Multi-model to benefit from all the innovation going on. Single-user because it makes sense to bring the agent to the compute.
That last one is the most consequential. A single-user agent that runs on the same machine as the work has no need for a multi-tenant permission model, and the project is direct about the consequence: there is no authorization and no sandboxing, and you supply them. Any deployment plan that assumes the agent is reachable from an untrusted network needs a layer in front of it, and the project does not provide one.
The lineage is stated too. Shelley is partially based on the same team's previous coding agent effort, Sketch, and the project says much of Shelley is written by Shelley, Sketch, Claude Code and Codex. It is Apache licensed and requires a CLA for contributions, and there is a .clabot file in the repository for that purpose.
Conversations, messages and a server-sent event feed
The technical stack is Go for the backend, SQLite for storage, and TypeScript with Vue 3 and PrimeVue for the interface. The data model is described in one sentence: conversations have messages, and a message might be from the user, the model, the tools, or the harness. All of that is stored in the database.
The live update path is a server-sent event endpoint. That choice matters for anyone reasoning about the implementation. SSE is a one-way server-to-client channel over plain HTTP, which is exactly the shape of a coding agent's output stream: the agent talks, the browser listens. It also means the browser reconnects on its own, which is the behaviour you want when a phone loses signal for a minute and the user comes back to find the agent still working.
The data model has a consequence worth noting. A message can come from the tools or from the harness as well as from the user or the model, so the conversation is a full transcript of the session rather than a request and response pair. That is what makes the history feature possible and what makes compaction necessary, since a long agent session produces a lot of message rows.
The repository layout backs the picture up. There are directories for llm/, loop/, mcp/, modelproviders/, modelsources/, models/, skills/, server/, ui/, client/, db/, cmd/, plus specialised ones such as gitstate/, exeenv/, sockdial/, lazycue/, slug/, subpub/, dtach/ and committour/. The go.mod file names the module shelley.exe.dev and requires a Go toolchain of 1.27.2, with modernc.org/sqlite as the database driver, coder/websocket for websockets, modelcontextprotocol/go-sdk for MCP, chromedp for browser automation, sashabaranov/go-openai for model access, and tailscale.com, which is a plausible fit for a single-user agent that has to be reachable from a phone without exposing a port to the internet.
Compaction, the idle nudge, and a warm provider cache
The most interesting mechanism in the project has nothing to do with code generation. It is context management, and the documentation describes it in unusual detail.
A profile carries an idle_compaction_minutes setting. Once a top-level conversation has been idle that long after a turn, an idle nudge starts a turn in which the agent compacts its own context, using a behaviour called compact_in_place, which has to be enabled and is on by default. In other words the agent is prompted to summarise its own history when nobody is talking to it, which is how a long-running session stays inside a context window without the user having to start a new conversation.
The mechanics of the nudge are global, while idle_compaction_prompt adds the profile's own guidance about what to keep. That split is deliberate: the trigger and the timer behave the same way for every profile, but what survives compaction is a per-profile decision, since a research profile and a coding profile have different ideas about what matters.
Two behaviours complete the picture. New input cancels the pending timer, so a user who comes back to a conversation does not get a compaction turn triggered under them. And cache_keep_warm_minutes keeps the provider prompt cache warm while the conversation sits idle, which is a cost and latency decision rather than a correctness one.
This is a level of detail that most agent frameworks do not publish, and it is the most reusable part of the project. Whether or not you run Shelley, the shape of the mechanism is a reasonable answer to the question of how an agent session survives being left alone overnight.
Installing it, and the three routes the project offers
There is a prebuilt binary for macOS and Linux, fetched with a single curl command that works out the platform name and architecture at the shell level:
curl -Lo shelley "https://github.com/boldsoftware/shelley/releases/latest/download/shelley_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')" && chmod +x shelleyThe same binaries are on the releases page. On macOS there is a Homebrew cask:
brew install --cask boldsoftware/tap/shelleyOr you can build it, which needs Go and Node:
git clone https://github.com/boldsoftware/shelley.git
cd shelley
makeThe Makefile shows what a build involves. There is a target that fetches a pinned exe-scroll release for the current build target, with the fetcher caching immutable, SHA-256-verified assets outside the worktree, a target that builds the UI and the Go binary, and a target that turns the directories under templates/ into tarballs. The Go binary is produced with go build -o bin/shelley ./cmd/shelley, and the UI is built with pnpm through the packageManager field in the ui/package.json. There is also a build-custom target, documented as producing a customised binary that stamps the release tag the branch diverged from, so the version dialog knows the build has diverged from mainline and offers rebase-style upgrades rather than binary self-updates.
To run it locally the project says to run make, and make serve to start Shelley. There is a development trick for the mobile view: on a home network with working mDNS, you can forward a port to the local server with socat:
socat TCP-LISTEN:9001,fork TCP:localhost:9000The Makefile also carries test, test-go and test-e2e targets, plus serve, clean, help, templates, demo and exe-scroll-all.
A release per commit, and what that means for pinning
New releases are created automatically on every commit to main. The version numbers follow the pattern v0.N.9OCTAL, where N is the total commit count and 9OCTAL is the commit SHA encoded as octal with a 9 prefix. The published tags show the pattern at work: v0.1432.911311506 and v0.1431.940623510 on the same day, 2026-10-20, with an earlier one at 03:11 the same morning.
This is a deliberate choice with real consequences. On the plus side, a specific commit is always addressable, and a bug can be bisected precisely because the tag encodes the commit. The go.mod confirms the same idea, since the self-update dependency and the release tooling are part of the same approach to shipping continuously.
On the other side, there is no stable channel in the usual sense. There is no LTS release, and no version number that a consumer can pin and expect to keep working, because the version encodes a moving commit count rather than a compatibility promise. A team that vendors the binary or depends on it as a library has to decide for itself whether to track main or to hold a specific tag.
The version scheme also has an internal use, since the custom build path reads the divergence point from the merge base with origin/main, and the release automation carries the SHA in octal so the mapping between a tag and a commit stays mechanical.
The rest of the repository is a set of documents rather than code, which tells you what the project considers worth writing down: AGENTS.md and AGENT_TESTING.md, API.md, ARCHITECTURE.md, FILE_COMPLETION.md and HOOKS.md, alongside a sqlc.yaml for the database layer and a .goreleaser.yml for the release builds.
Where Shelley is the wrong choice
The absence of authorization and sandboxing is the headline limitation and it is not a missing feature so much as a refusal. A coding agent that can run commands is a remote code execution capability with a chat interface, and this one is explicitly shipped without either containment layer. For a developer running it on a personal machine next to a checkout, that is a reasonable position. For a team that wants to expose an agent to people who are not the operator, it is a non-starter, and the answer is to put a layer in front of it rather than to expect the agent to provide one.
The second limit is the single-user assumption baked into the design. A profile, an idle timer, a compaction prompt, a warm provider cache: these are all shaped around one person using one agent. There is no shared queue of conversations, no handoff, no notion of two people looking at the same session, and no audit trail designed for a team.
The third is the platform reach. The prebuilt binaries are for macOS and Linux, so a Windows user builds from source, and the build needs both Go and Node with a pnpm-driven UI step. The mobile-friendly web interface is a genuine advantage over a terminal, but it is a browser talking to a local server, so the phone still has to reach the machine, and the project offers the socat and mDNS route rather than a hosted deployment.
The fourth is the dependency surface of a Go program that ships a web UI, a browser automation layer, an MCP client, a SQLite database and a model provider client. The go.mod names the large dependencies directly, chromedp for browser control, the MCP Go SDK, go-openai, tailscale, modernc.org/sqlite. A project with this many moving parts and a release cut on every commit will move, and the operational question for an adopter is how much of that movement they are willing to absorb.
Editorial conclusion
Shelley fits a developer who wants a coding agent with a mobile-friendly web interface, several conversations in flight at once and the ability to swap the underlying model, especially on a host where the agent should run close to the compute it is driving. It is the wrong choice for a shared or multi-user deployment, because authorization and sandboxing are not included and the project says to bring your own, and it is the wrong choice if you need a stable release cadence, since a new tag is cut on every commit to main. Before running it, decide where it will listen and what will reach it, since there is no auth layer in the box, and check the version scheme, because v0.1432.911311506 encodes the commit count and the commit SHA, with the last push on 2026-10-20.
Frequently asked questions
How do I install Shelley?
On macOS or Linux you can fetch the prebuilt binary with the curl command in the project documentation, install the Homebrew cask with brew install --cask boldsoftware/tap/shelley, or build from source with git clone, cd shelley and make, which needs Go and Node.
Does Shelley include authorization and sandboxing?
No. The project states that it does not come with authorization or sandboxing and that you should bring your own, and it describes itself as a single-user agent.
What technology does Shelley use?
Go for the backend, SQLite for storage, and TypeScript with Vue 3 and PrimeVue for the user interface. Live updates reach the browser through a server-sent event endpoint.
How are Shelley releases versioned?
A new release is created automatically on every commit to main, with versions following the pattern v0.N.9OCTAL, where N is the total commit count and 9OCTAL is the commit SHA encoded as octal.
How do I run Shelley locally?
Run make and then make serve to start it. For viewing the mobile interface on a home network with working mDNS, the project documentation suggests forwarding a port with socat TCP-LISTEN:9001,fork TCP:localhost:9000.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/boldsoftware-shelley)Was this useful?