Docs
Glyph is one zsh file. It names your terminal session at launch, then gets out of the way. Everything it can do is on this page.
Getting started
zsh, and at least one agent CLI on your PATH. Nothing else.
The installer copies one file to ~/.config/glyph/glyph.zsh and adds one source line to ~/.zshrc. Re-running it is safe.
source, not ./install.shRun as a path it is a child process, and a child cannot define functions in the shell that started it, so glyph would not exist until you reloaded. Sourcing installs and loads in one step. Already ran it the other way? . ~/.config/glyph/glyph.zsh catches you up without opening a new shell.
Check it without launching anything
GLYPH_DRYRUN=1 prints the exact argv Glyph would run and stops there. Nothing starts, nothing is recorded.
Then launch for real
That string is the session name. On Claude Code it is the real session name and rides Remote Control to the web app and your phone. On every other agent it lands on the terminal title, the tmux window, and glyph ls.
How a name is built
Six tokens joined by ·, all lowercase, hyphens inside words.
| Token | Comes from | Example |
|---|---|---|
| Label | the one bare word you typed | billing |
| Project | the git repo directory you launched from | acme-api |
| Agent | which wrapper ran | claude-code |
| Machine | scutil --get ComputerName on macOS, hostname elsewhere | mbp |
| Date | launch date | 2026-09-12 |
| Time | launch time | 0556 |
The rule for arguments
One bare word is a label. Anything with a space is a prompt.
Flags like -p and subcommands like claude mcp or codex resume pass through untouched, so scripts and CI behave exactly as before.
Machine tags
Normalised to lowercase hyphenated form. Rivers MacBook Pro becomes rivers-macbook-pro, DESKTOP-8KQ2LM1 becomes desktop-8kq2lm1. Glyph never guesses a model or an OS release. If yours reads badly, set it:
Project overrides
One tab-separated line per directory in ~/.config/glyph/names.tsv. Overrides are normalised the same way.
Preview any name
Launching agents
Keep typing the command you already type. Glyph only adds the name.
Claude Code
The one agent that can name its own session, so the name becomes the real session name and reaches Remote Control.
Turn Remote Control off with GLYPH_RC=0.
Everyone else
No agent but Claude has a session-name flag, so the name goes on the terminal title, the tmux window and the registry instead.
Agents may overwrite the terminal title after launch. Fleet keeps its own pane-border labels, which they cannot touch.
See what you have running
Sessions already open
Glyph names a session from argv, so a session you started without it never got a name.
glyph mark applies everything Glyph can still reach from outside the agent, and
prints the one line only the agent itself can run.
set the terminal title
renamed the Herdr pane
recorded it in glyph ls
this Claude session is still called 'fru-3e'
an agent can only rename itself. paste this into it:
/rename hotfix·acme-api·claude-code·mbp·2026-09-12·2107
/remote-control
It reports only the surfaces it actually reached. No terminal, no tmux, no Herdr, or
GLYPH_TITLE=0 and the matching line is simply absent.
Let it type the commands for you
Add --send and Glyph types the /rename into the pane itself, over
herdr pane send-text or tmux send-keys, following it with
/remote-control when the bridge is off.
It refuses outside an agent session, where the keystrokes would land in your shell instead. If the agent is mid-answer the text queues until it is ready.
Inside Herdr
Herdr sets no TMUX, so the tmux path never applies there. Glyph renames the
Herdr pane instead, through herdr pane rename. That label belongs to Herdr, which
is the point: an agent cannot overwrite it with its own terminal title, and Codex and AGY both
do exactly that a second after they start.
This applies to normal launches too, not just glyph mark. In plain
tmux Glyph now also turns off allow-rename and automatic-rename on the
window, for the same reason.
What it cannot do
| Surface | After launch |
|---|---|
| Terminal title | Yes. Written straight to /dev/tty, so it never lands in a pipe. |
| tmux window and pane label | Yes. |
glyph ls registry | Yes, recorded as a mark row. |
| The agent's own session name | Only from inside it. Glyph prints the /rename line to paste. |
| Remote Control bridge | Not from outside, but Claude Code can switch it on from inside with /remote-control. Glyph reads bridgeSessionId and offers that line only when the bridge is actually off. |
Inside Claude Code it detects the agent from CLAUDECODE and reads the live session
name out of ~/.claude/sessions/<pid>.json, so you can see what the session is
called before you change it. For any other agent, name it yourself:
What is running
glyph ls is a log of launches Glyph performed. glyph ps is the other
question: what is alive right now, including sessions Glyph never started.
claude billing·acme-api·claude-code·mbp glyph on 60129
claude fru-3c auto off 96624
11 live, 10 without a glyph name or without Remote Control
NAMED is glyph when the name has Glyph's shape, user when
someone set it by hand, auto when the agent derived it. RC is whether Remote
Control is on, so you can see at a glance which sessions your phone cannot reach.
Reads the live session files and checks each pid, so it lists only what is actually running. Claude Code today: the other agents do not publish a session registry.
Usage and quota
How much is left, and when it comes back, across agents.
codex plus weekly █████░░░░░░░░░░░ 31% resets in 5d 20h
claude - 5h/wk quota is server side, add --live
agy not exposed
Each agent is a different story, and Glyph says which is which rather than blending them:
| Agent | Quota and reset | Token counts |
|---|---|---|
| Codex | Exact and offline. Every rollout carries a rate_limits record with the window, percent used and reset time, so both the 5h and weekly windows come straight off disk. | Yes |
| Claude Code | Not on disk. Window boundaries are decided server side, so --live asks Anthropic directly, authorised from the Keychain. | Yes, from the transcripts |
| AGY | Not exposed. No usage flag on the CLI, no token fields in its transcripts. | No |
Detail for one agent
They are what your own transcripts recorded, which is useful for seeing where the volume went, but it is not the number your plan is measured against. For that, use --live.
Reading a large transcript history takes a few seconds, so the result is cached
for ten minutes. --refresh rescans now, GLYPH_USAGE_TTL changes the
window. --live is the only part of Glyph that makes a network request; the token is
passed to curl over stdin so it never appears in ps.
Auto-approve
Every agent has a flag meaning "stop asking me to approve each tool call", and they all spell it differently. GLYPH_YOLO=1 sends whichever one is right for the agent you are launching.
Naming always happens. Auto-approve never happens unless you ask for it.
Make it the default
Setting it per command gets old. Export it once and every agent you launch through Glyph gets its own auto-approve flag, with nothing to remember:
Be clear about what that means: every agent will run every tool call without asking you first, in every project, until you unset it. That is the point of the flag, and it is why Glyph will not turn it on for you.
Check what any agent would actually get, without launching it:
Agents
A wrapper is defined only for agents actually on your PATH. Run glyph agents to see yours.
| Agent | Command | Carries the name as | GLYPH_YOLO=1 sends |
|---|---|---|---|
Claude Code | claude | real session name | --dangerously-skip-permissions |
Codex | codex | title | --dangerously-bypass-approvals-and-sandbox |
AGY | agy | title | --dangerously-skip-permissions |
Cursor | cursor-agent | title | --force |
Crush | crush | title | --yolo |
cortex | title | --dangerously-allow-all-tool-calls | |
| Hermes | hermes | title | --yolo |
| omni | omni | title | none |
opencode | title | --dangerously-skip-permissions | |
pi | real session name | none |
Add your own
Any CLI, without waiting for a release. One tab-separated line per agent in ~/.config/glyph/agents.tsv: command, auto-approve flag, label. Leave the flag empty if it has none.
These merge over the built-ins, so you can also correct a flag Glyph gets wrong.
Fleet
One preset launches several agents at once, each in its own marked pane. Fleet is the only part of Glyph that opens anything.
The presets fleet init writes
It only adds what is missing, so it never touches presets you already wrote. Replace studio with one of your own machines.
| Preset | Slots | What it is for |
|---|---|---|
| solo | claude | one agent, named. the everyday case |
| review | claude codex | two vendors on the same diff, for a second opinion |
| duo | claude agy | Anthropic and Google side by side |
| ci | claude agy codex | the three-up bench |
| bench | claude codex agy cursor-agent | everything local, one pane each |
| pair | claude cursor-agent | a terminal agent beside an editor-native one |
| deep | claude cortex | a coding agent next to a warehouse-native one |
| light | crush opencode | lightweight runners for cheap, quick passes |
| split | claude codex:studio | one local, one on a remote box |
| spread | claude claude:studio | the same agent on two machines |
| cloud | claude:studio codex:studio | both agents on the remote box |
Without a preset
Name the agents directly and Fleet runs them as an ad-hoc group.
Preview before opening panes
Prints the backend, the session, and one line per pane. Opens nothing.
Presets live in ~/.config/glyph/fleet.conf as name = slot slot slot. Edit it by hand any time.
Moving between panes
On the tmux backend a Fleet is one session, one window, and one tiled pane per slot. Glyph leaves you in the first pane and turns the mouse on for that session, so a click moves between them. Each pane border carries its index and its label.
| Move | Keys |
|---|---|
| Click a pane | Mouse, on by default for the Fleet session only |
| Next pane | ctrl-b o |
| By direction | ctrl-b then an arrow key |
| By number | ctrl-b q, then the digit shown |
| Zoom one pane | ctrl-b z, again to unzoom |
Set GLYPH_FLEET_MOUSE=0 to leave the mouse alone. Glyph only ever
sets it on the Fleet session, never on your global tmux config.
Remote agents
A slot is <agent> or <agent>:<machine>. For a remote slot Glyph opens SSH in that pane, changes to the same working directory, and launches the agent through the remote Glyph wrapper, so it gets that agent's own flags and its own name.
How a machine name resolves
First hit wins.
| Order | Source | Example |
|---|---|---|
| 1 | An entry in ~/.ssh/config | Host mini |
| 2 | A name in ~/.ssh/known_hosts, so the pane never stalls on a fingerprint prompt | mac-mini |
| 3 | Tailscale, where a short name expands to its MagicDNS name | mini → mini.tailnet.ts.net |
| 4 | Anything else, passed to SSH untouched | user@10.0.0.5 |
Run ssh <host> by hand the first time. After that, remote panes start clean.
Tailscale is optional and detected automatically; nothing changes if you do not use it. Remote slots work on every backend, because they all build the same SSH command.
Workspace backends
Backends decide where Fleet opens panes. They change nothing about launching a single agent.
| Backend | What it does |
|---|---|
| auto | Herdr, then cmux, then Zellij, then WezTerm, then tmux. |
| herdr | One Herdr tab per slot, each running in the tab's own pane. Glyph also ships a Herdr plugin that puts agent quota in a pane: herdr plugin install fru-dev3/glyph/herdr-plugin |
| cmux | One cmux workspace per slot. |
| zellij | One named Zellij pane per slot. |
| wezterm | One WezTerm tab per slot. |
| tmux | Tiled panes in a new tmux session. |
Glyph is not tied to any one workspace tool. With none running, Fleet falls back to tmux.
Command reference
| Command | What it does |
|---|---|
glyph name [label] | Print the session name this directory would produce. Nothing is launched. |
glyph ps | Every agent session alive right now, named or not, with Remote Control state. |
glyph usage [agent] | Quota and token counts across agents. --live, --json, --refresh. |
glyph doctor | Check the install and report what is wrong. Non-zero exit when something needs attention. |
glyph mark [label] [agent] --send | As below, but types the /rename into the agent instead of printing it. |
glyph mark [label] [agent] | Name a session that is already open: terminal title, tmux, registry, and the /rename line to paste. |
glyph ls [n] | The last n recorded sessions (default 20): time, agent, name, machine. |
glyph agents | Every agent found on your PATH, its label, and its auto-approve flag. |
glyph hosts | Machines you can put after a colon in a Fleet slot: SSH config entries, then tailnet peers. |
glyph presets | The Fleet presets currently defined. |
glyph fleet init | Write the example presets, keeping any you already have. Safe to re-run. |
glyph fleet <preset> | Launch a preset, one marked pane per slot. |
glyph fleet <agent> [<agent>...] | Launch an ad-hoc fleet without defining a preset first. |
glyph update | Fetch the latest glyph.zsh from GitHub. |
glyph version | The installed version. |
Configuration
Behaviour
| Variable | Default | Effect |
|---|---|---|
GLYPH_YOLO=1 | off | Send each agent's auto-approve flag. |
GLYPH_DRYRUN=1 | off | Print the argv that would run. Launch nothing, record nothing. |
GLYPH_OFF=1 | off | Keep the label and project, drop the machine and time. |
GLYPH_SEP | · | Separator between tokens. |
GLYPH_FMT | %Y-%m-%d·%H%M | date(1) format for the stamp. |
GLYPH_MACHINE | computer name | Machine tag, when the hostname does not read well. |
GLYPH_RC=0 | on | Do not add Claude's --remote-control. |
GLYPH_TITLE=0 | on | Leave the terminal and tmux titles alone. |
GLYPH_LOG=0 | on | Do not record sessions locally. |
GLYPH_FLEET_MOUSE=0 | on | Do not turn the mouse on for the Fleet tmux session. |
GLYPH_FLEET_BACKEND | auto | auto, herdr, cmux, zellij, wezterm or tmux. |
Paths
| Variable | Default | Points at |
|---|---|---|
GLYPH_USAGE_TTL | 600 | Seconds to cache the transcript scan behind glyph usage. |
GLYPH_CLAUDE_API | api.anthropic.com | Host glyph usage --live asks for quota. |
GLYPH_FLEET_CONF | ~/.config/glyph/fleet.conf | Fleet presets. |
GLYPH_AGENTS | ~/.config/glyph/agents.tsv | Extra agents you define. |
GLYPH_MAP | ~/.config/glyph/names.tsv | Project name overrides. |
GLYPH_STATE | ~/.local/state/glyph | Session registry (honours XDG_STATE_HOME). |
GLYPH_UPDATE_URL | GitHub raw glyph.zsh | Where glyph update pulls from. Point it at a fork. |
GLYPH_SSH_CONFIG | ~/.ssh/config | Where host resolution reads SSH hosts. |
GLYPH_KNOWN_HOSTS | ~/.ssh/known_hosts | Where host resolution reads trusted hosts. |
GLYPH_TAILSCALE | auto-detected | Path to the tailscale binary. |
Files on disk
| Path | What it is |
|---|---|
~/.config/glyph/glyph.zsh | The wrapper itself. Replaced by glyph update; a symlink here is followed, not overwritten. |
~/.config/glyph/fleet.conf | Fleet presets, one name = slots per line. |
~/.config/glyph/agents.tsv | Extra agents: command, auto-approve flag, label, tab separated. |
~/.config/glyph/names.tsv | Project overrides: directory name, display name, tab separated. |
~/.local/state/glyph/sessions.tsv | What glyph ls reads. Delete it any time. |
~/.zshrc | One source line, added by the installer. |
Updating
- Loads the new file into the shell you ran it in, so there is nothing to reload.
- Refuses to install a file that does not parse.
- Keeps the previous copy at
~/.config/glyph/glyph.zsh.bak. - Follows a symlink and writes the file it points at, so an install linked into a synced folder keeps its link.
- Never touches
fleet.conf,names.tsvoragents.tsv. - Point
GLYPH_UPDATE_URLsomewhere else to track a fork.
Other shells you already had open keep the old wrapper until you run exec zsh in them.
Doctor
Before troubleshooting by hand, ask Glyph what it thinks is wrong.
It checks the wrapper path and whether it is a symlink, version drift between the file on disk
and the copy loaded in this shell, the ~/.zshrc line, which agents are on your PATH
but not actually wrapped, the Fleet backend it would use, the registry, and your config files.
It exits non-zero when something needs attention, so it works in a script.
The check that catches most confusion is version drift: an updated file on disk and an older copy still loaded in the shell you are typing in.
Troubleshooting
| Symptom | Fix |
|---|---|
command not found: glyph right after installing | The installer ran as a child process and could not touch your shell. Run . ~/.config/glyph/glyph.zsh, or use source ./install.sh next time. |
agy billing reports an unexpected argument | An older wrapper is still loaded in that shell. Run exec zsh. |
| A Fleet pane stalls on a host key fingerprint | Accept the key by hand once with ssh <host>, then the pane starts clean. |
glyph fleet opens a nested tmux inside Herdr | Set GLYPH_FLEET_BACKEND=herdr, or run Fleet outside Herdr. |
| Claude's startup banner does not show the name | It never does. Read ~/.claude/sessions/<pid>.json, or look at the session list on the web or your phone. |
| The machine tag reads badly | Set it yourself: export GLYPH_MACHINE=laptop. |
| Nothing happens at all | Confirm the source line is in ~/.zshrc, then run glyph version. If that fails, re-run ./install.sh. |
Two things that cost real debugging time
- Claude's
--remote-control <name>does not name the session. It opens the bridge, and the session still comes back asnameSource: "derived". Only-nsets the name, so Glyph passes both. - In zsh,
argvis$@. Declaringlocal -a argvin a function silently empties the positional parameters. Worth knowing if you fork this.
Uninstall
Nothing else was installed and no agent config was modified, so that is the whole of it.
Claude Code
Codex
AGY
Cursor
Crush