>agentglass
The workspace for your coding agents
nvim
tmux
lazygit
lazydocker
ClickUp
GitHub PRs
Chrome
Claude
↑3 ↓14 shells2 waiting 5h 61%weekly 34%🔔 7
6 running · $8.41 today2 need you
orbitopus62$2.41
orbit-websonnet31$1.96
billing-apiopus44$0.87
docshaiku12$0.34
infraopus88$4.12
testssonnet9$0.11
scraperhaiku5$0.06
migrationssonnet17$0.44
orbit-apiopus53$3.08
changeloghaiku4$0.03
e2esonnet21$0.62
seedhaiku7$0.09
deployopus35$1.87
8 worktrees214 turns1.2M tokens$8.41
today · 4 projectssince 08:12
spend$8.41+$1.20
turns214+38
tokens1.2M+210k
errors3−2
spend by model
opus$5.38
sonnet$2.44
haiku$0.59
by project
orbit$3.87
orbit-web$2.27
infra$1.60
3 files · +18 −7reviewed 1 of 3
changed
scan.ts+11−4
App.tsx+5−1
db.ts+2−2
walk.ts+6−0
rail.tsx+3−5
staged
scan.ts
db.ts
commit
on feat/gateCommit →
@@ −38,9 +38,13 @@ scanRoots()
38
39
40
41−
42−
43+
44+
45+
46+
47
48
@@ −102,6 +106,9 @@ walkOne()
106
107
108−
109+
110+
111+
112
main ↑3 ↓14 staged · 2 changed
branches
main↑3
feat/gate↑2
fix/rail—
changes
Amodifiers.ts
Mkeys.ts
MkeyLayout.ts
Dold.ts
MTopBar.tsx
Afit.ts
MRail.tsx
Agate.ts
Mindex.css
Atree.ts
mainfeat/gatefix/rail
needs my review4 of 11 open
needs memineall
feat/gate12 ✓#594
fix/railrunning#596
chore/dep1 ✗#591
feat/keys9 ✓#588
docs/readme6 ✓#585
fix/scanqueued#583
feat/tree14 ✓#579
fix/gate3 ✗#576
chore/ci8 ✓#572
feat/themerunning#570
3 approved1 changes requested2 draft11 open
assigned to me5 open · 3 done
ORBITsprint 14
bug3Start →
feat5
bug2Start →
docs1
feat8
chore1
feat3
bug2Start →
feat5
docs1
chore3
ORBIT-1042 … 104920 ptsStart cuts a worktree
tmux · orbit2 panes · 4 shells
pane 0 — bun test
❯ bun test
scan.test.ts 18 pass
keys.test.ts 24 pass
gate.test.ts 31 pass
rail.test.ts 2 skip
gate.test.ts 19 pass
tree.test.ts 28 pass
fit.test.ts 20 pass
142 pass · 0 fail · 1.2s
❯ git status --short
M src/engine/scan.ts
?? src/engine/walk.ts
❯
pane 1 — nvim
38 export function scan(
39 root: string,
40 ) {
41 const out = [];
42 for (const e of walk(
43 root,
44 { depth: 6 },
45 )) {
46 if (skip(e)) continue;
47 out.push(e);
48 }
49 return out;
50 }
-- INSERT -- 41,17 Top
claude · opus-5turn 38 · $2.41
​
⌕Read src/engine/scan.ts · 218 lines
​
✎Edit src/engine/scan.ts+9−2
❯bun test scan.test.ts18 pass
​
​
⌕Grep "canHide" · 3 files
✎Edit src/ui/keyLayout.ts+4−1
​
38 turns142k in9.1k out$2.41
4 running · 1 unhealthycompose · orbit
nameimagecpumemport
postgres16-alpine5432
redis7.26379
workerorbit:dev—
apiorbit:dev8080
miniolatest9000
mailhogv1.08025
traefikv3.18081
otelcontrib4317
worker · last lines
localhost:4000driven by the agent
localhost:4000docsissue #1042
200 · 412ms
menu
click
orbit/342 files · 12 open
src
engine
scan.tsts
walk.tsts
db.tsts
ui
App.tsxtsx
Rail.tsxtsx
test
scan.test.tsts
keys.test.tsts
gate.test.tsts
docs
WORKSPACE.mdmd
package.jsonjson
tsconfig.jsonjson
scan.ts · 218 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
typescriptutf-8LF7.4 kB
One window. Nothing to jump to.
↓ agentglass v0.23.2 · six builds
✓ sha256 · attested build · MIT
✓ ready — the files are just below
or try it in your browser first — live demo ↗
The hold

Nothing dangerous runs until you say so.

The agent asks, and stops there. You see the whole command, the project and who is asking, with the clock running while it waits.

HELD · infra · claude · opus-5 0m 00s
$ kubectl delete namespace production
What it holdsrm -rf · git push --force · kubectl delete · drop table · credentials · anything outside the project
What it shows you firstthe literal command, the repo, the agent, the model, and how long it has been waiting
What it remembersonce, this session, or always for this project. The decision stays on your machine
In parallel

Start cuts a worktree. Four at once.

A task becomes a branch, a directory of its own, and an agent working in it. They never collide, and you never change folder.

orbit · main4 worktrees live
branchagentprogressstate
feat/gateopus12 ✓
fix/railsonnetrunning
docs/readmehaikureview
infra/tfopusheld
8 worktrees214 turns1.2M tokens$8.41 today
Away from the desk

The work waiting on you, in your pocket.

Pull requests, issues and cards — the three places work arrives from — counted and then listed. Terminal is one of the rows, and it is the machine at home: a held gate raises its band there, so you can clear it from the sofa. It pairs over your own wifi by a scanned code: no account, and nobody’s server in between.

21:10
Inbox···
4 things
are waiting on you.
4need you
2CI failing
2ready to merge
Machine
orbitConnected›
Go to
PRs›
Terminal›
Issues›
Cards›
Source control›
InboxHow many things are waiting, before the list of them.
21:10
orbit▾
My review 5
Mine 8
All 19
#412maintainer2h
Retry the rollup when GitHub answers 502
needs review2 failed3f +18 −7
fix/rollup-retry → main
#409acme-bot5h
Bump the pinned toolchain to 1.4.2
approvedgreen1f +4 −4
chore/toolchain-142 → main
#404someone2d
Fold worktrees into the repository they belong to
needs reviewchecks…7f +212 −96
feat/one-row-per-repo → main
#398other3d
Name the window after the checkout, not the session
draft2f +31 −12
feat/window-names → main
#391maintainer4d
Ask GitHub for the five counts in one call
changes asked1 running4f +86 −140
perf/prs-counts → main
Pull requestsCI, the review and the size on the row, so none of the three costs a tap.
21:10
1 orbit.AI
2 orbit.sh
4 infra·p2
$ agent run --resume

● Read server/src/prs.ts
● Read server/src/checks.ts
● Grep "rollup" — 9 hits, 4 files

  The rollup call answers 502 about one
  time in forty, and the row then says "no
  checks" rather than "checks…". Those are
  different claims and only one is true.

● Edit server/src/prs.ts
  @@ -118,7 +118,18 @@
  + for (let try_ = 0; try_ < 3; try_++) {
  + const answer = await rollup(ref);
  + if (answer.ok) return answer;
  + await sleep(240 << try_);
  + }

● Bash bun test test/rollup.test.ts
  12 pass 0 fail [1.84s]

● Bash bun run typecheck
  tsc --noEmit clean

$ git push -u origin fix/rollup-retry
To github.com:acme/orbit.git
 * [new branch] fix/rollup-retry

● Opened #412 — retry the rollup
  when GitHub answers 502

$
Esc^C↑↓Tab⇧Tab
Write a lineSend
TerminalThe shells already running on the computer, not a second empty prompt.
Download · v0.23.2 · MIT

Six files, and a way to check them.

Pick your platformEvery build is below.
All releases
Check what you downloaded sha256sum -c SHA256SUMS gh attestation verify <the file you downloaded> --repo SirAllap/agentglass

The release publishes SHA256SUMS beside the binaries, and every desktop build carries a build attestation from the workflow that made it. macOS is unsigned, so Gatekeeper wants right-click → Open the first time; Windows builds and passes CI but nobody has run it on real hardware yet (#231).

Guide

Install it, point it at your machine, and extend it.

agentglass is a desktop app with its own server bundled inside. There is nothing to run in a terminal and no port to open in a browser.

Getting it running

Take the installer for your platformSix files on the release. Linux gets an AppImage or a .deb; macOS has a separate build for Apple silicon and Intel; Windows is an NSIS .exe. The desktop builds are attested — gh attestation verify <file> --repo SirAllap/agentglass names the commit and the workflow that produced yours.
Launch it. That is the installThe cockpit opens with the server inside it. On first open the transcript scanner has already read ~/.claude/projects, so every Claude Code session on the machine is listed with no wiring at all.
Wire the hooks, once, if you want liveThe scanner shows history; the hooks add live streaming and PreToolUse gating — the hold. Settings ▸ Hooks writes them into ~/.claude/settings.json and takes them out again, and says whether they are in right now.
Pair the phone, if you want the queue with youTurn on remote access on the computer, scan the code from the Android app, type the six digits, accept on the desktop. It pairs over your own wifi: no account, and nobody's server in between.

What it expects to find

It drives the tools you already have rather than bundling its own, so the list is about what each feature shells out to — and what quietly stands down when it is missing. Settings ▸ Requirements checks every one of these on your machine and says what breaks without each.

gitneededSource control, file changes, pull requests, worktrees, and deciding where the terminal opens.
Claude Code CLIneededThe chat panel runs claude. Without it sessions still appear — the scanner reads the transcripts either way — you just cannot chat from the app.
Python 3neededThe hook forwarder.
tmuxper featureChats as live panes, your tmux windows as tabs, theme sync.
GitHub CLIper featureThe pull-requests panel — and logged in, which is the step people miss.
Dockerper featureContainers, images, volumes, logs.

Plugins

A plugin is a program somebody else wrote that watches or drives agentglass over HTTP. It is a folder with a plugin.json, and installing it, reading what it asks for, and switching it on are three separate acts you perform in Settings ▸ Plugins.

Nothing runs at install. When you enable one, the server mints a token at the scope you granted and starts the entrypoint as its own process, with exactly four variables in its environment: PATH, HOME, AGENTGLASS_URL and AGENTGLASS_READ_TOKEN. Nothing is loaded into the server or the desktop window. Disabling it kills the process and revokes the token; tokens live in memory and are never written to disk.

A plugin can also draw: a panel in the Plugins view, a page in Settings, notes in a pull request and a button in its header. It sends what to show as data, and agentglass draws it with its own parts. Browse the plugins.

readAlmost every GET route, including /stream: live output, costs, diffs, pull requests, the board. Writes nothing through the app's API, and cannot read another plugin's settings or screen. The plugin itself runs as you: the scope limits its token, not the process.
answerEverything read gets, plus replying to a session already running. It cannot release a gate.
fullEverything this machine can do: a terminal, git writes, Docker, merging pull requests, installing other plugins.

The manifest is a request, not a grant: you see the scope and decide whether to enable it at all. A plugin cannot get full by writing "full" and being believed.

Finding one

A catalogue is a plain JSON file at an https:// URL, fetched fresh every time you browse it. It is a list, not a registry — nothing in it is cached as trustworthy between reads, and a catalogue that is unreachable or malformed is shown as exactly that, never as an empty list.

{
  "name": "community-plugins",
  "owner": "someone",
  "plugins": [{
    "id": "someone.hello-stream",
    "source": { "kind": "git", "url": "https://example.com/someone/hello-stream.git" },
    "description": "Writes a line to its log when an agent finishes.",
    "categories": ["monitoring"]
  }]
}

Full detail in PLUGINS.md and EXTENDING.md.

Questions

The things people ask before installing.

Short answers. Every one of them is also somewhere in the repository, linked where it matters.

Does it replace Claude Code, or my agent?

No. It attaches to the tmux sessions and repositories already open on your machine. It does not launch your agents and it does not proxy them — close agentglass and every agent keeps running.

Does anything leave my machine?

No account, no cloud, no telemetry. Everything lives in a SQLite file on your own disk.

Two paths can leave and both are off by default: a webhook you configure yourself, and the Explain button, which sends the hunks you point at to a model. SECURITY.md lists every switch.

What do I actually need installed?

Needed: git, the Claude Code CLI, and Python 3.

Per feature: tmux for chats as live panes and your tmux windows as tabs; the GitHub CLI for the pull-requests panel, logged in; Docker for containers, images and logs.

Settings ▸ Requirements checks all of it and says what stands down without each one.

Which agents, and which providers?

Agents: Claude Code, Codex, Gemini CLI and OpenCode.

Providers, for pointing Claude Code at something else: Kimi, OpenAI, Gemini and Bedrock.

Why does macOS say the app is damaged?

It is not damaged — the build is not signed yet, and Gatekeeper says that about anything unsigned. Once:

xattr -dr com.apple.quarantine /Applications/agentglass.app

Signing and notarization are the first item on the roadmap.

Can a plugin approve a held gate for me?

No, and it is turned away by name rather than by scope. A plugin's token is minted by this server and sits in the environment of a child process of it, readable by anything else running as the same user — which is exactly the kind of caller the gate exists to hold.

Releasing a gate is reserved for a credential no process on the machine could have minted for itself: a paired phone's, or a person at the desktop.

Can a plugin add a panel to the window?

Yes, within a closed vocabulary. A plugin declares where it draws — a panel in the Plugins view, a page in Settings, notes inside a pull request, a button in a pull request's header — and sends what to show as data. agentglass draws it with its own parts: there is no HTML, no stylesheet, no image by URL and no script. A tone is a word the app maps onto the current theme.

What is still not there is a surface of its own: an iframe with its own capability grants, where a plugin could draw anything it liked. That is a real design problem and it is undesigned, so it is not shipped under cover of "plugins". A plugin that needs one opens its own window today — it is a separate process and can start a terminal UI or a web page, talking over the same HTTP.

Is Windows supported?

It builds and passes CI, and nobody has run it on real hardware yet — #231 is open for exactly that. macOS builds are unsigned for now. Linux is the best-travelled path.