Skip to content

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

9 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 

Repository files navigation

agent-tray

A Linux top-bar indicator for AI coding agents: Claude Code and ChatGPT / Codex. See every running session, the model it uses, how much context is left, token usage, time spent and your ChatGPT plan limits. Get popups with a soft chime when a task finishes or context runs low, and resume any session in one click without typing in a terminal.

Unofficial community tool. Not affiliated with or endorsed by Anthropic or OpenAI. All icons (the ✨ AI sparkle, the orange spark and the teal hexagon) are drawn for this project and are not either company's logo.

Quick start

git clone https://github.com/lincechacko-FSW/agent-tray.git
cd agent-tray
bash install.sh

The icon appears in the top bar. Click it to see your sessions. It starts automatically at every login.

Supported agents

Agent What it reads Running detection
Claude Code (CLI) Claude Code hooks (installed by install.sh), ~/.claude/sessions/ and ~/.claude/projects/ Exact from hooks: busy when you send a message, ⏳ waiting at a permission prompt, idle when Claude finishes. Without hooks it uses Claude's status file, or as a last resort estimates busy / idle from CPU (shown as "status estimated"; estimates never trigger popups)
ChatGPT desktop app (coding threads) ~/.codex/state_*.sqlite (read-only) and ~/.codex/sessions/ Busy while a turn is running; open exactly while the app's background service keeps the thread's file open (falls back to "used in the last 30 min while the app runs" if that can't be read)
Codex CLI Same ~/.codex/ folder Busy while a turn is running; open only while an interactive codex process runs the thread (holds its file open, or runs in that folder). The shared codex app-server service doesn't count: it also keeps files of closed CLI threads open

ChatGPT web / chat conversations live on OpenAI's servers and are not shown. Only coding threads saved in ~/.codex are.

Features

Each agent has its own colour and logo

Agent Colour Logo Where you see it
Claude Code 🟠 orange orange spark menu section header, 🟠 before each session, orange gauge ring, card stripe, tint and logo
ChatGPT / Codex 🟢 teal teal hexagon menu section header, 🟢 before each session, teal gauge ring, card stripe, tint, logo and button

Status is shown separately, by ⚡ busy / 💤 idle / ⏳ waiting in the menu and the status pill on each card.

Top-bar icon

  • Always there: a lavender ✨ AI sparkle in a faint orbit ring on a starry navy badge, with the number of running sessions next to it. It turns grey when nothing is running.

  • Space-themed animations for every agent:

    Event Icon Text next to icon (4 s)
    New session opens 🚀 A rocket launches through streaking stars, then the sparkle spins in 🚀 poc-28 launched
    A session starts working 💥 The sparkle flares and a shock ring expands in the agent's colour (🟠 / 🟢) ⚡ poc-28 working
    Sessions busy 🛰 A satellite orbits the sparkle in the busy agent's colour: 🟠 orange for Claude, 🟢 teal for ChatGPT, two satellites when both are busy
    Session finishes a task ✅ A green planet with a ✓ appears in a starburst ("mission complete") ✓ poc-28 done
    Session closed 🌒 The sparkle sinks, greys out and fades ✕ poc-28 closed
    Context 80% used Amber icon with a big ! that pulses ⚠ poc-28 ctx 82%
    Context 95% used Red icon with a big ! that pulses ⚠ poc-28 ctx 96%
  • Starts at login automatically.

Popups with a soft chime

When Popup
A task that ran 10 s or longer finishes ✅ poc-28 finished · Claude Code · Took 2m 14s · opus-5-5 · 84% context left · ~/POC
Claude stops to wait for you ⏳ poc-28 needs attention
Context 80% used ⚠️ poc-28 context 82% full · consider /compact soon
Context 95% used 🔴 poc-28 context almost full · run /compact or start a new session
ChatGPT 5-hour or weekly plan window passes 80% ⚠️ ChatGPT 5-hour limit 82% used · Plan: plus · resets Tue 16:09
  • Each popup plays a short bell chime made for this app, and has an Open dashboard button:

    Popup Chime
    ✅ Task finished 3 rising notes (E–B–E): "mission complete"
    ⚠️ / 🔴 Context filling up 2 falling notes (G–D): gentle heads-up
    ⚠️ ChatGPT plan limit 3 low notes (C–C–G): calm nudge
  • GNOME plays the chime at your normal volume, and keeps both popup and chime silent during Do Not Disturb. Set SOUND = False for silent popups.

  • A new popup for the same session replaces the previous one.

  • Context warnings fire once per level per session, and reset after /compact or /clear drops usage below 70%.

  • Sent warnings are remembered in ~/.cache/agent-tray/prefs.json, so restarting the app never repeats them.

  • Sessions with no message in the last hour don't warn (e.g. a forgotten terminal); they warn once you use them again.

  • Plan-limit popups fire once per window per reset period, also across restarts.

Tray menu (click the icon)

 ✨  Agent Tray — 3 running · 2 busy
     Today 535k tokens · 14.8M cached
 ───────────────────────────────────────────────────────
 [spark]    CLAUDE CODE  ·  2 running
 ◔  🟠  gyrodriver       💤 idle · 15h 11m          ▸
 ◕  🟠  agent-tray       ⚡ busy · 28m               ▸
 ───────────────────────────────────────────────────────
 [hexagon]  CHATGPT · CODEX  ·  1 running  ·  plan 5h 5% · weekly 1% used
 ◔  🟢  Explain GNSS…    ⚡ busy · 28m               ▸
 ───────────────────────────────────────────────────────
 ↺  Resume a past session                           ▸     🟠 supervisor_main …   🟢 …
 ▦  Open dashboard…
 ↻  Refresh
 ───────────────────────────────────────────────────────
 ⏻  Quit

Hover over a session to open its submenu:

 🧠  gpt-6.1-sol
 ▰▰▰▰▰▰▱▱▱▱  64% context left
 ⬆ 83k in  ·  ⬇ 6.4k out  ·  869k cached
 ⏱  running 19m · active 7m
 📍  open in ChatGPT app
 ────────────
 ▶  Open copy in terminal
 💬  Open the ChatGPT app      (ChatGPT threads only)
 📁  Open folder
 📋  Copy resume command
 ────────────
 ⏹  End session…               (ChatGPT app threads: "Stop it in the ChatGPT app…")
  • Sessions are grouped by agent under a header with the agent's logo. The ChatGPT header shows your plan usage.
  • Each session has a ring gauge icon in its agent's colour, with the agent's mark inside. The ring fills with context used.
  • Resume a past session ▸ lists the last 10 ended sessions from both agents (🟠 Claude, 🟢 ChatGPT).
  • The ChatGPT app often gives several threads the same name. Open threads with the same name in the same folder are listed once (the busy one, otherwise the most recently used), and same-named past threads get their first message and start time, e.g. Study this project · "exit" · 12:22.

Dashboard

A black window with an orange gradient header showing Running, Busy, Today tokens and Cache reads. Running sessions are grouped into a Claude Code section and a ChatGPT section, each with its logo and a count. The ChatGPT section also shows your plan usage (5-hour and weekly, with reset times). New cards slide in.

A switch under the header filters the dashboard to All, 🟠 Claude Code or 🟢 ChatGPT · Codex, with a live count on each button. It applies to both running and recently ended sessions, is instant, and is remembered the next time you open the dashboard (keys 1 / 2 / 3 work too).

Each card has its agent's colour: a coloured left stripe, a faint tint and the agent logo next to the name. Ended cards use a dimmer stripe.

Each card shows:

  • agent logo, name, project folder, status pill (busy / idle / ⏳ waiting / ended) and an agent label (Claude Code, ChatGPT for app threads, or Codex CLI)
  • model(s) used, including subagent models, and whether it is a 1M-context model
  • a context bar with % left
  • tokens: input, output, cache read, cache write (Claude subagents included)
  • time running, active time, last message, and API time and cost when available (Claude)

Resume in one click

Session Button Runs in a new terminal
Ended Claude session Open session claude --resume <id>
Running Claude session Open copy claude --resume <id> --fork-session (the original is untouched)
Ended ChatGPT / Codex thread Open session codex resume <id>
Open ChatGPT / Codex thread Open copy codex fork <id> (the original is untouched)

ChatGPT cards also have a ↗ button that brings the ChatGPT app to the front. Running cards have a ⏹ End session button at the far right (see Ending a session).

Light on resources

  • Reads only the lines added to session files since the last check
  • Reads the Codex database only when it changes, and opens it read-only
  • Watches the Claude sessions folder for changes (inotify), so it updates the moment a session starts or stops
  • Redraws only when something changed. Animation timers only run during an event animation or while a session is busy (the orbit), so the app uses no CPU when idle
  • No pip dependencies

Private by design

  • Reads only the files Claude Code and ChatGPT / Codex already save in ~/.claude/ and ~/.codex/
  • Never reads ~/.codex/auth.json or any credentials
  • Makes no network requests and uses no tokens
  • Session data never leaves your machine

Supported systems

System Status
Ubuntu 22.04 / 24.04 (GNOME) ✅ Tested, everything works
Ubuntu 25.04+ ⚠️ Works, but Open session needs gnome-terminal (sudo apt install gnome-terminal), because the default terminal there is Ptyxis
Other GNOME distros (Fedora, Arch…) ⚠️ Install the tray library and the AppIndicator extension yourself; install.sh only supports apt
KDE / XFCE / Cinnamon / MATE ⚠️ Icon, menu and popups should work; Open session needs gnome-terminal installed

Requirements

  • Linux with a desktop that shows AppIndicator / StatusNotifier tray icons. Tested on Ubuntu 24.04 (GNOME, Wayland).
    • GNOME needs the AppIndicator extension. Ubuntu has it enabled by default (ubuntu-appindicators@ubuntu.com).
    • KDE, XFCE, Cinnamon and MATE support tray icons out of the box.
  • Python 3.10+ with PyGObject (GTK 3). Preinstalled on Ubuntu.
  • gir1.2-ayatanaappindicator3-0.1. install.sh installs it.
  • gnome-terminal, used by the resume buttons.
  • A desktop notification service for popups (built into GNOME, KDE and most desktops).
  • At least one agent:
    • Claude Code, with sessions in ~/.claude/
    • the ChatGPT desktop app or the Codex CLI (standalone install in ~/.codex/packages/standalone, or npm i -g @openai/codex), with threads in ~/.codex/

Install

git clone https://github.com/lincechacko-FSW/agent-tray.git
cd agent-tray
bash install.sh

install.sh will:

  1. Install the tray-icon library with apt (asks for your sudo password)
  2. Stop any running copy, and remove an old claude-tray install if there is one
  3. Add Claude Code hooks to ~/.claude/settings.json for exact session status (your other settings are kept, and a backup is saved as settings.json.agent-tray-backup)
  4. Add an agent-tray command in ~/.local/bin
  5. Add an app-menu entry (Agent Tray) and start the app automatically at login
  6. Start it now

Hooks apply to Claude sessions started or resumed after installing. Restart open sessions (/exit, then claude --resume) to get exact status there.

Autostart points at the folder you ran install.sh from. If you move the folder, run bash install.sh again.

Usage

Action How
Start agent-tray, or open Agent Tray from the app menu
See sessions Click the icon in the top bar
See one session's details Icon menu, then hover over the session
Open the dashboard Icon menu, then Open dashboard…; or middle-click the icon; or click Open dashboard on a popup
Close the dashboard ✕ at the top-right, or press Esc (the icon stays in the top bar)
Show only Claude or ChatGPT / Codex sessions The All / 🟠 Claude Code / 🟢 ChatGPT · Codex switch under the dashboard header, or keys 1 / 2 / 3
Resume an ended session Open session on its card, or icon menu, then Resume a past session ▸
Open a running session Open copy on its card, or icon menu, then session, then Open copy in terminal (a forked copy)
Bring up the ChatGPT app ↗ on a ChatGPT card, the CHATGPT menu header, or Open the ChatGPT app in a thread's submenu
Open the project folder 📁 on a card, or icon menu, then session, then Open folder
Copy the resume command 📋 on a card, or icon menu, then session, then Copy resume command
End a running session ⏹ at the far right of a running card, or icon menu, then session, then ⏹ End session… (asks first; the conversation stays resumable)
Refresh now ↻ in the dashboard title bar, or icon menu, then Refresh
Stop Icon menu, then Quit

Closing the terminal you started it from doesn't stop the app, and starting it twice won't add a second icon. Resume terminals always open as new windows, whichever way the app was started.

Ending a session

⏹ End session… in a session's submenu, or the ⏹ button on a running dashboard card, stops that agent process after you confirm:

  • It sends a normal stop (SIGTERM) so the agent exits cleanly. If it is still running after 5 s (END_GRACE_S), it asks before a Force stop (SIGKILL).
  • Right before stopping, it re-checks that the PID still belongs to the same claude / codex process, so a recycled PID is never hit.
  • Works for Claude Code sessions and Codex CLI sessions (when one codex process runs in that folder). Threads inside the ChatGPT app share one process, so for those the item opens the app instead.
  • The conversation is saved, and the session moves to Resume a past session.

Command-line options

agent-tray                # start in the background (default)
agent-tray --foreground   # stay attached to the terminal and print logs
agent-tray --dump         # print the current session data (both agents) as JSON and exit
agent-tray --install-hooks   # add the Claude Code status hooks to ~/.claude/settings.json
agent-tray --remove-hooks    # remove them again (other settings are kept)

Background logs go to ~/.cache/agent-tray/agent-tray.log.

Updating

cd agent-tray
git pull
bash install.sh

Settings

Edit these constants in agent_tray.py (search for the name), then restart the app.

Setting Default What it does
SOUND True Play a soft chime with each popup; False for silent popups
NOTIFY_MIN_S 10 Only show a finished-task popup for tasks that ran at least this many seconds
LABEL_FLASH_S 4 Seconds the event text stays next to the icon
CTX_WARN 0.80 Context used (fraction) that triggers the ⚠️ warning popup
CTX_FULL 0.95 Context used (fraction) that triggers the 🔴 almost-full popup
CTX_REARM 0.70 Warnings reset once context used drops below this
WARN_ACTIVE_S 3600 Context warnings only for sessions with a message in the last this-many seconds
LIMIT_WARN 0.80 ChatGPT plan window usage (fraction) that triggers a popup
END_GRACE_S 5 Seconds to wait after End session before offering Force stop
CLAUDE_STALE_S 180 A hook-"busy" Claude session quiet this long is shown idle (the turn was interrupted with Esc)
CLAUDE_BUSY_CPU 0.015 For Claude sessions without a status file: CPU share above which the session counts as busy
CODEX_ACTIVE_S 1800 A ChatGPT / Codex thread counts as open if used this recently while its app runs
CODEX_STALE_S 600 An unfinished ChatGPT / Codex turn with no activity for this long stops counting as busy
POLL_S 3 Seconds between checks of live sessions
SLOW_S 30 Seconds between rescans for ended Claude sessions and today's totals
IDLE_GAP_S 300 Gaps between messages longer than this don't count as active time
ENDED_SHOWN 10 Number of recently ended sessions to list
ANIM_MS see file Frame speed of each icon animation in milliseconds (orbit = busy satellite, default 200)

What the numbers mean

  • Context left: the size of the last request compared with the model's context window (Claude: 200k, or 1M for [1m] models; ChatGPT: the window the app reports, e.g. 258k). It shows how full the conversation is, not your plan quota.
  • Active time: the time between messages, not counting gaps longer than 5 minutes.
  • Took (popup): how long the session was busy, from each agent's own timestamps.
  • Today: tokens from all sessions of both agents since local midnight. Cache reads are shown separately because they are much larger and cheaper.
  • ChatGPT plan: the 5-hour and weekly usage the ChatGPT app last reported, with reset times.
  • Claude plan limits (5-hour and weekly) are not stored on your machine, so they can't be shown. Run /usage inside Claude Code to see them.

How it works

Claude Code writes:

  • ~/.claude/sessions/<pid>.json: one file per open session, with name, folder, start time, and busy/idle status with a timestamp. The app checks each PID is still alive to spot stale files.
  • ~/.claude/projects/<project>/<session-id>.jsonl: each session's history, with the model and token usage of every response. Subagent histories are in <session-id>/subagents/.

Agent Tray's Claude hooks (agent-tray --hook, about 40 ms per event) write ~/.cache/agent-tray/claude/<session-id>.json:

  • UserPromptSubmit → busy (and remembers when the turn started)
  • Notification with permission_prompt → ⏳ waiting ("needs attention" popup)
  • Stop → idle ("finished" popup, exactly once per turn)
  • SessionEnd → the file is removed

Stop doesn't fire when you interrupt a turn with Esc, so a "busy" session whose process stays quiet for 3 minutes is shown idle (without a popup).

ChatGPT / Codex writes:

  • ~/.codex/state_*.sqlite: the thread list (title, folder, model, last update). The app opens it read-only.
  • ~/.codex/sessions/YYYY/MM/DD/rollout-*.jsonl: each thread's events. Turn start and finish give busy/idle; token events give usage, context window and plan limits.

A background thread reads both, and passes a snapshot to the GTK main thread only when something changed. The main thread compares each snapshot with the previous one to detect started, finished and closed sessions. It then plays the icon animation, shows the text next to the icon, and sends the popup through org.freedesktop.Notifications with its chime attached (sound-file). The chimes are generated once with Python's wave module into ~/.cache/agent-tray/.

Icon frames are small SVGs generated once into ~/.cache/agent-tray/.

Uninstall

agent-tray --remove-hooks
pkill -f "^(/usr/bin/)?python3 .*agent[-_]tray"
rm ~/.local/bin/agent-tray ~/.config/autostart/agent-tray.desktop ~/.local/share/applications/agent-tray.desktop
rm -rf ~/.cache/agent-tray

Troubleshooting

  • No icon appears: on GNOME, check the AppIndicator extension is enabled with gnome-extensions list --enabled | grep -i appindicator.
  • Namespace AyatanaAppIndicator3 not available: run sudo apt install gir1.2-ayatanaappindicator3-0.1.
  • No popups: check that Do Not Disturb is off, and that the task ran longer than NOTIFY_MIN_S seconds.
  • No chime: check that SOUND = True, that system sounds are on (Settings, then Sound, then Alert sound), and that Do Not Disturb is off.
  • A Claude session says "status estimated": it isn't using the hooks yet (it was started before they were installed, or they were removed). Restart it (/exit, then claude --resume), or run agent-tray --install-hooks. Estimated sessions never trigger popups.
  • A popup you didn't expect: every popup is logged with its time in ~/.cache/agent-tray/agent-tray.log.
  • ChatGPT threads don't show: check that ~/.codex/ exists and has a state_*.sqlite file, and run agent-tray --dump to see what the app reads.
  • "Already running" but no icon, or after an update: run bash install.sh, or pkill -f "^(/usr/bin/)?python3 .*agent[-_]tray"; agent-tray.
  • Open session does nothing: check that gnome-terminal is installed (which gnome-terminal), then look in ~/.cache/agent-tray/agent-tray.log for the error.
  • End session says "No codex process is running in this folder": that Codex CLI thread isn't running in any terminal any more. Refresh the menu; it should be under Resume a past session.
  • Resume says the conversation was not found: the project folder was moved or deleted, and Claude Code finds sessions by folder.
  • Anything else: run agent-tray --foreground to see errors in the terminal. Quit the running copy first.

Roadmap

  • More agents (Gemini CLI, Aider…)
  • Support more terminals (Ptyxis, Konsole, xfce4-terminal, Kitty…) for Open session
  • install.sh support for dnf and pacman

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages