RiNG — Realtime Instance Notification Grid for active agent CLI sessions.
Project description
RiNG 🎤
台灣漢語 · English
Realtime Instance Notification Grid — a local dashboard for active agent-CLI sessions. Claude Code and Codex are built in; other tools can plug in.
When you run several Claude Code / Codex sessions at the same time, it is easy to lose track of which one is still working, which one has finished a turn, and which one needs your response. RiNG puts them on one board, with sessions waiting for you sorted first.
🎤 RiNG — 3 sessions on stage · 2 agent processes running
🔴 maigo 12s → waiting for permission
🟢 pelican-osm 3s → Edit
🟡 commitizen 8m turn finished, idle
Who It Is For
- You run multiple Claude Code / Codex sessions in parallel.
- You want one board for “working”, “idle”, “waiting for me”, and “ended”.
- You want to jump from a TUI row back to the terminal where the session lives.
- You are willing to install hooks for precise waiting-state detection and system notifications.
Key Features
- One board for every session: Claude Code / Codex are built in; other tools can feed
ring hook. - Waiting first: sessions that need your response are highlighted and sorted above the rest.
- Jump back to the terminal: in the TUI, select a session and press
Enter/Spaceto focus tmux, iTerm2, or Terminal.app. - System notifications: hook mode can beep and notify when a session starts waiting; with
terminal-notifier, clicking the notification jumps back. - Name your sessions: press
nin the TUI to add a local label such asmaigo · auth refactor. - Local and extensible: RiNG only reads local Claude Code / Codex data and writes
~/.config/ring/; session sources, focusers, and notifiers are pluggable.
Run
Requires Python 3.13+. The PyPI package is named ring-cli, while the import module and CLI command are both ring.
# Recommended: install the command from PyPI
uv tool install 'ring-cli[tui]'
# Or use pipx
pipx install 'ring-cli[tui]'
# Then run it
ring
ring --watch
ring --watch --interval 1
# Module form also works after installation
python -m ring
The [tui] extra installs the Textual interactive UI. Without it, --watch falls back to Rich polling, then plain text.
For development inside the repository:
uv run ring
uv run ring --watch
Zero-config mode can discover local Claude Code / Codex sessions without setup. For precise 🔴 waiting detection, install hooks:
ring install-hooks # merges into Claude Code / Codex hook settings
ring install-hooks --dry-run # preview without writing
ring doctor # inspect hooks, notification backends, focusers, and config
ring gc --dry-run # preview RiNG-owned stale state cleanup
Hooks only apply to new sessions, so restart Claude Code / Codex sessions after installing.
Common Commands
| Command | Purpose |
|---|---|
ring |
Print a one-shot snapshot |
ring --watch |
Keep refreshing; enters the TUI when Textual is installed |
ring --watch --interval 1 |
Refresh every second |
ring --watch --count N |
Stop after N frames, useful for tests / CI |
ring --all |
Show ended sessions too |
ring --no-legend |
Hide the legend |
ring --lang zh-Hant |
Switch UI language |
ring focus SESSION_ID |
Focus a specific session |
ring config |
Show config path and effective settings |
ring config set KEY VALUE |
Write one config value |
ring doctor |
Read-only environment diagnosis |
ring gc --dry-run |
Preview RiNG-owned stale state cleanup |
ring gc |
Clean RiNG-owned stale state files |
Watch Mode
- With Textual (
[tui]extra) in a real terminal: interactive TUI. Use↑/↓to select,Enter/Spaceto jump,nto name a session,ato toggle ended sessions,rto refresh, andqto quit. If you have vim muscle memory like I do,j/kmove up/down andg/Gjump to the first/last row. - Otherwise: Rich polling; without Rich, plain text.
Jump To A Session
Select a session and press Enter. RiNG focuses the terminal where that session is running.
- tmux: switches directly to the pane via
switch-client. - iTerm2 / Terminal.app on macOS: uses the session
ttyand AppleScript to focus the matching tab. The first run may ask for macOS Automation permission.
TTY matching is most accurate in hook mode. Without hooks, Codex falls back to zero-config matching: one live Codex session per cwd can jump correctly; multiple live Codex sessions in the same cwd are shown conservatively to avoid focusing the wrong tab.
Notifications
Default behavior: with hooks installed, when a session changes to 🔴 waiting, RiNG beeps and sends a system notification. If it keeps waiting, RiNG reminds you again at 30s / 120s / 300s by default.
For clickable notifications on macOS, install terminal-notifier:
brew install terminal-notifier
Without it, RiNG falls back to macOS text notifications without click-to-focus.
Notification sound, repeat timing, and backend selection are configurable; notification backends
are also pluggable via the Notifier extension point.
Cleaning RiNG State Files (ring gc)
When RiNG receives SessionEnd, it removes its own hook registry entry. If an agent crashes or the
final hook does not run, ended ~/.config/ring/sessions/*.json files can remain. They are hidden from
the board by default, and you can remove them with ring gc.
ring gc --dry-run # preview what would be deleted
ring gc # delete ended registry files older than 7 days, plus expired IPC files
ring gc --older-than 1d # use a 1-day threshold
ring gc --all-ended # delete every registry file currently classified as ended
ring gc only cleans state files RiNG owns under ~/.config/ring/. It does not touch Claude Code /
Codex transcripts or state. ring doctor remains read-only and never deletes files.
Session Sources
RiNG collects sessions from registered sources. Built-ins:
| Source | Reads From | Precision |
|---|---|---|
| Claude Code zero-config | ~/.claude/projects/**/*.jsonl, mtimes, and cwd fields |
no setup; detects recent activity and turn completion. Precise user-action prompts require hooks |
| Codex zero-config | ~/.codex/state_5.sqlite, rollout JSONL, and live codex processes |
no setup; detects live / ended / turn completion. Use hooks for precise jumps when multiple sessions share a cwd |
| hook registry | ~/.config/ring/sessions/, written by ring hook |
precise: 🔴 waiting / 🟢 working / 🟡 idle / ⚫ ended |
Zero-config needs no setup. For precise “who needs me”, install hooks so provider events feed the RiNG registry.
RiNG includes installers for Claude Code and Codex; other tools can use the provider-neutral ring hook protocol.
States
RiNG reduces every session to four user-facing states. 🔴 waiting is sorted first.
| State | Meaning | What RiNG Saw |
|---|---|---|
| 🔴 waiting | You should return now | hook event requiring a user response, such as permission or choices |
| 🟢 working | Agent is running | prompt submitted or recent activity |
| 🟡 idle | The current turn finished | Stop, or no new activity past working_threshold_seconds |
| ⚫ ended | Session is over | SessionEnd, process ended, or local records aged out |
🔴 waiting requires hook mode. Zero-config can tell whether a session was recently active, but not whether it needs a decision from you.
Hook Mode
Zero-config only has filesystem mtimes and local state snapshots, so it cannot reliably distinguish “needs a decision” from “just finished”. Hooks send agent-CLI events directly to RiNG, making 🔴 waiting and notifications precise.
Claude Code / Codex Installer
Hooks run ring hook, so install ring somewhere stable on PATH first:
uv tool install 'ring-cli[tui]'
Then register hooks:
ring install-hooks
ring install-hooks --dry-run
Claude Code hooks are written to ~/.claude/settings.json. If ~/.codex exists, Codex hooks are also written to
~/.codex/hooks.json; Codex will ask you to trust the hook before it runs it.
Claude Code events:
| Claude Code Event | RiNG State |
|---|---|
SessionStart / UserPromptSubmit |
🟢 working |
Stop |
🟡 idle |
Notification with permission_prompt / elicitation_dialog |
🔴 waiting |
PermissionRequest / PreToolUse with AskUserQuestion |
🔴 waiting |
SessionEnd |
removed from the board |
Codex currently installs the supported interactive events: PreToolUse, PermissionRequest, and Stop.
Verify that hooks are writing:
ls ~/.config/ring/sessions/
Other Providers
Any tool can feed JSON into ring hook:
ring hook --provider codex
# shorthand:
ring hook codex
Payload field names are intentionally loose. At minimum, provide a session id, event, and cwd:
{
"provider": "codex",
"session_id": "thread-123",
"event": "Notification",
"notification_type": "permission_prompt",
"requires_action": true,
"waiting_for": "permission",
"cwd": "/repo/app",
"tty": "/dev/ttys003",
"last_action": "waiting for permission"
}
If a provider can distinguish “needs user action now” from “just waiting for the next prompt”,
send requires_action = true/false or waiting_for = "permission" | "options" | "next_step".
agent-hooks
Notification details: --watch and the TUI both send notifications. The default backend is auto:
RiNG prefers clickable terminal-notifier, then falls back to osascript on macOS or notify-send
on Linux. If none are available, RiNG keeps the board running and skips notifications.
Config keys include notify_sound, notify_sound_name, notify_ignore_dnd,
notify_repeat_seconds, notify_repeat_max, and notify_backend. Custom notification channels
can be added by registering another Notifier.
agent-hooks is an optional external hook helper / decision UI. If it is installed and
notify_backend = "agent-hooks", ring hook still writes RiNG registry state, then passes the
raw payload to agent-hooks callback for the synchronous decision UI. RiNG --watch will not send
a duplicate notification. If agent-hooks is not on PATH, RiNG automatically falls back to auto.
Remove Hooks
ring remove-hooks
ring remove-hooks --dry-run
This removes RiNG-installed hook entries from Claude Code / Codex settings. It does not delete
~/.config/ring/ session records and does not touch other hooks.
Configuration
~/.config/ring/config.toml, all optional:
lang = "en"
interval = 2.0
show_all = false
legend = true
active_window_seconds = 21600
working_threshold_seconds = 90
waiting_window_seconds = 1800
notify_sound = true
notify_sound_name = "Glass"
notify_ignore_dnd = false
notify_backend = "auto" # auto / terminal-notifier / osascript / notify-send / agent-hooks / none
notify_repeat_seconds = [30, 120, 300]
notify_repeat_max = 3
focusers = ["tmux", "iTerm2", "Terminal"]
[colors]
waiting = "bold red"
working = "green"
idle = "yellow"
ended = "grey50"
project = "cyan"
location = "bright_blue"
muted = "grey50"
Extending
RiNG is not tied to a specific tool or terminal.
| Extension Point | Purpose | Built-ins |
|---|---|---|
SessionSource |
find sessions | Claude Code, Codex, hook registry |
Focuser |
jump to terminals | tmux, iTerm2, Terminal.app |
Notifier |
notify when sessions are waiting | terminal-notifier, osascript, notify-send |
Each backend is a small module under ring/sources/, ring/focus/, or ring/notify/, registered via register_*().
Platform & Privacy
- Platform: macOS / Linux. Windows is not supported.
- Privacy: entirely local. RiNG only reads local
~/.claude/and~/.codex/data and writes~/.config/ring/. No network, uploads, or telemetry.
Name
The name is a triple pun:
- It rings you when a session needs a response.
- “RiNG” is the live house from BanG Dream!.
- Realtime Instance Notification Grid describes what it is.
Non-Goals
RiNG tracks session state. It is not a token or cost dashboard.
Claude Code JSONL token counts are currently unreliable enough to make cost accounting misleading, so RiNG deliberately avoids that surface.
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ring_cli-0.3.0.tar.gz.
File metadata
- Download URL: ring_cli-0.3.0.tar.gz
- Upload date:
- Size: 68.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b54061ddc427430b1d7cf3bfb8770846ff8a1dc501fe4d3f1f239f805537b98e
|
|
| MD5 |
1226e13dde1f746222a11b201b8e4bdd
|
|
| BLAKE2b-256 |
1b65d1edffecd4923e58dbdc584b0ded4c32df064b6dd982da8a3e650ee9db84
|
Provenance
The following attestation bundles were made for ring_cli-0.3.0.tar.gz:
Publisher:
release.yml on Lee-W/ring
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ring_cli-0.3.0.tar.gz -
Subject digest:
b54061ddc427430b1d7cf3bfb8770846ff8a1dc501fe4d3f1f239f805537b98e - Sigstore transparency entry: 1950956528
- Sigstore integration time:
-
Permalink:
Lee-W/ring@acc4ef4301db98c399b965e14ed2b1ec11af3eeb -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Lee-W
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@acc4ef4301db98c399b965e14ed2b1ec11af3eeb -
Trigger Event:
push
-
Statement type:
File details
Details for the file ring_cli-0.3.0-py3-none-any.whl.
File metadata
- Download URL: ring_cli-0.3.0-py3-none-any.whl
- Upload date:
- Size: 92.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0881c64465bdfa79ce57747dc3f1962cace4dc9242788e71c94781f4af4a34ae
|
|
| MD5 |
6071a8ae5a0d39edcebe67928c288b35
|
|
| BLAKE2b-256 |
e18c3400d0b8dfc464ac025c8225e1480f7382f7e7107bfd542e89074f66e2ae
|
Provenance
The following attestation bundles were made for ring_cli-0.3.0-py3-none-any.whl:
Publisher:
release.yml on Lee-W/ring
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ring_cli-0.3.0-py3-none-any.whl -
Subject digest:
0881c64465bdfa79ce57747dc3f1962cace4dc9242788e71c94781f4af4a34ae - Sigstore transparency entry: 1950956687
- Sigstore integration time:
-
Permalink:
Lee-W/ring@acc4ef4301db98c399b965e14ed2b1ec11af3eeb -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Lee-W
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@acc4ef4301db98c399b965e14ed2b1ec11af3eeb -
Trigger Event:
push
-
Statement type: