🚦 Command-line tool for Semaphore, a USB status light. Hook it up to Claude Code, Codex, GitHub Copilot CLI, OpenCode or Antigravity CLI and see your agent status on a light indicator.
Tip
Needs a board running the Semaphore firmware.
- Light up one color at a time: green, yellow, or red
- Steady or blinking, with a configurable blink speed
- Read back the current state of the light
- Replay the startup animation on demand
- Ready-made hooks for Claude Code, Codex, GitHub Copilot CLI, OpenCode, and Antigravity (support for more harnesses is in the future)
- Node.js 18+
- A Semaphore light connected over USB. See the firmware README for supported boards and flashing instructions.
npm install -g semaphore-cliOr from source:
git clone https://github.com/artemy/semaphore
cd semaphore
npm install
npm install -g .semaphore <color> on
semaphore <color> blink [half_period_ms]
semaphore off
semaphore status
semaphore boot
<color>isred,yelloworgreen. The light shows one color at a time.- The blink half-period is 20–5000 ms (default 500).
--soft(or-s) exits silently with code 0 when the light is unplugged or unreachable (recommended for use in hooks).
Examples:
semaphore red on # steady red
semaphore green blink 250 # fast blinking green
semaphore off # turn the light off
semaphore status # get the current stateHooks make the light follow your agent's session automatically:
| Light | Meaning |
|---|---|
| green | Idle, waiting for you |
| red | Agent is busy |
| yellow blink | Agent needs your input |
| off | No active session |
semaphore from your PATH, so install the CLI globally first (see Installing).
Every hook command uses --soft. An unplugged light never breaks your session, and no hook output ends up in the model's context.
Run from your terminal:
agy plugin install https://github.com/artemy/semaphoreOr from a local clone:
agy plugin install ./plugins/semaphore-hooksHook events
| Light | Antigravity events |
|---|---|
| green | Stop |
| red | PreInvocation, PostToolUse |
| yellow blink | PreToolUse (on ask_question, run_command) |
Known limitations:
- Antigravity does not have
SessionStart,SessionEnd, orInterruptlifecycle hooks. As a result, the startup boot animation does not play automatically, and the light does not turn off when exiting the CLI session. - There is no dedicated
PermissionRequestevent hook; yellow blinking is triggered viaPreToolUseonask_questionandrun_command. Commands that are already permitted will briefly flash yellow before executing.
Run from inside Claude Code:
/plugin marketplace add artemy/semaphore
/plugin install semaphore-hooks@semaphore
To set up the hooks without the plugin, merge the hooks key from hooks/hooks.json into your .claude/settings.json.
Hook events
| Light | Hook events |
|---|---|
| green | SessionStart (after the boot animation), Stop, StopFailure |
| red | UserPromptSubmit, PostToolUse, PostToolUseFailure |
| yellow blink | PermissionRequest, Notification (permission prompts and questions) |
| off | SessionEnd |
SessionStart skips compaction, so an automatic compaction mid-turn does not turn the light green.
Known limitations:
- Claude Code has no hook for user interrupts. If you reject a permission prompt or dismiss a question with Esc, the light keeps blinking yellow until your next prompt.
- Tool calls from background subagents turn the light red, even while a prompt is waiting for you.
Run from your terminal:
codex plugin marketplace add artemy/semaphore
codex plugin add semaphore-hooks@semaphoreTo set up the hooks without the plugin, copy the contents of hooks/codex-hooks.json into your .codex/hooks.json.
Hook events
| Light | Hook events |
|---|---|
| green | SessionStart (after the boot animation), Stop, Interrupt |
| red | UserPromptSubmit, PostToolUse |
| yellow blink | PermissionRequest, PreToolUse (on request_user_input) |
| off | SessionEnd |
SessionStart skips compaction, as in Claude Code.
Register the Semaphore marketplace and install its Copilot CLI plugin:
copilot plugin marketplace add artemy/semaphore
copilot plugin install semaphore-hooks@semaphoreRestart Copilot CLI after installing the plugin. Every hook uses --soft and suppresses command output so the light works without interrupting the session or affecting hook output.
Hook events
| Light | Hook events |
|---|---|
| green | agentStop |
| red | userPromptSubmitted, preToolUse, postToolUse, postToolUseFailure |
| yellow blink | permissionRequest, notification (permission prompts and elicitation dialogs) |
| off | sessionEnd |
Known limitations:
- Copilot CLI's
sessionStarthook runs only after the first prompt, so Copilot CLI does not play a startup animation or set green before the first prompt.
Copy .opencode/plugins/semaphore-hooks.js into ~/.config/opencode/plugins/ to use it in every project, or into a project's .opencode/plugins/ to use it in that project only. OpenCode loads it automatically on the next start.
An npm package for the plugin is planned.
Plugin events
| Light | OpenCode events |
|---|---|
| green | session.created, session.idle, question.rejected |
| red | message.updated (user messages), tool.execute.after, permission.replied, question.replied |
| yellow blink | permission.asked, question.asked |
| off | dispose |
The permission.* and question.* events are also handled in their v2 forms.
The startup animation plays when OpenCode loads the plugin.
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
This project is licensed under the MIT License. See LICENSE.md for details.