An open API service indexing awesome lists of open source software.

https://github.com/artemy/semaphore

AI Agent status indicator for your desk
https://github.com/artemy/semaphore

ai-agent antigravity antigravity-hooks antigravity-plugin claude-code claude-code-hooks claude-code-plugin claude-code-skills codex codex-plugin copilot copilot-hooks copilot-plugin cursor cursor-hooks cursor-plugin hooks opencode opencode-plugin status-indicator

Last synced: 1 day ago
JSON representation

AI Agent status indicator for your desk

Awesome Lists containing this project

README

          

# Semaphore CLI

![MIT License](https://img.shields.io/github/license/artemy/semaphore)

🚦 CLI for a USB-HID traffic-light device that turns your desk light into a live session indicator for [Claude Code](https://claude.ai/code), [Codex](https://github.com/openai/codex), and [Opencode](https://opencode.ai).

## Features

- Control red, yellow, and green LEDs individually or all at once
- Three modes per LED: `off`, `on`, and `blink` with configurable speed
- `solo` command lights one LED and clears the other two
- `status` query reads current device state
- `boot` plays a startup animation
- Claude Code, Codex, and Opencode hook integration — the light follows session events automatically where supported

## Getting started

### Prerequisites

- Node.js 18+
- The semaphore device (VID `0x1209`, PID `0x0001`) connected via USB

### Installing

```shell
npm install -g semaphore-cli
```

Or from source:

```shell
git clone https://github.com/artemy/semaphore
cd semaphore/software
npm install
npm install -g .
```

## Usage

```
semaphore off
semaphore on
semaphore blink [half_period_ms]
semaphore solo on
semaphore solo blink [half_period_ms]
semaphore status
semaphore boot
```

- ``: `red` | `yellow` | `green` | `all`
- ``: `red` | `yellow` | `green` (solo turns off the other two)
- blink half-period: 20–5000 ms (default 500)
- `--soft` / `-s`: silently exit 0 on device-connectivity errors (for hooks)

### Examples

```shell
semaphore red on # turn red LED on
semaphore green blink 250 # fast-blink green (250 ms half-period)
semaphore solo yellow on # yellow on, red and green off
semaphore all off # turn everything off
semaphore status # read and print current device state
```

## Hooks installation

> ⚠️ Every hook command uses `--soft`. This keeps the LED best-effort when the device is unplugged, and suppresses stdout so hook output is not injected into the model's context.

### Claude Code

Claude Code hooks lifecycle

Claude Code support uses the documented lifecycle hooks in [`hooks/hooks.json`](hooks/hooks.json):

| LED state | Meaning | Hook events |
|----------------|-----------------------------|-------------------------------------|
| green solid | Idle / waiting for input | `SessionStart`, `Stop` |
| red solid | Claude is busy | `UserPromptSubmit`, `PostToolUse` |
| yellow blink | Needs human attention | `PermissionRequest`, `Notification` |
| all off | No active session | `SessionEnd` |

#### Plugin (recommended)

Make sure the package is installed globally first, then run from inside Claude Code:

```
/plugin marketplace add artemy/semaphore
/plugin install semaphore-hooks@semaphore
```

#### Manual

Merge the `hooks` key from [`hooks/hooks.json`](hooks/hooks.json) into your `.claude/settings.json`.

## OpenAI Codex

Codex hooks lifecycle

Codex support uses the documented Codex lifecycle hooks in [`hooks/codex-hooks.json`](hooks/codex-hooks.json):

| LED state | Meaning | Hook events |
|----------------|--------------------------|----------------------------------------|
| green solid | Idle / waiting for input | `Stop` |
| red solid | Codex is busy | `UserPromptSubmit`, `PostToolUse` |
| yellow blink | Needs human attention | `PreToolUse` (on `request_user_input`) |
| yellow blink | Needs human approval | `PermissionRequest` |

#### Plugin (recommended)

Make sure the package is installed globally first, then run from your terminal:

```shell
codex plugin marketplace add artemy/semaphore
codex plugin add semaphore-hooks@semaphore
```

> ⚠️ Codex will prompt you to review the newly installed hooks after you run it next time.

### Manual

Copy the contents of [`hooks/codex-hooks.json`](hooks/codex-hooks.json) into your `.codex/hooks.json`.

## Opencode

Opencode hooks lifecycle

Opencode support uses the native plugin system — the plugin at
[`.opencode/plugins/semaphore-hooks.js`](.opencode/plugins/semaphore-hooks.js) is auto-discovered and maps Opencode lifecycle events to the semaphore device:

| LED state | Meaning | Opencode events |
|--------------|--------------------------|-----------------------------------------------------------|
| green solid | Idle / waiting for input | `session.created`, `session.idle` |
| red solid | Opencode is busy | `message.updated` (`role=user`), `tool.execute.after` |
| yellow blink | Needs human attention | `permission.asked`, `tool.execute.before` (on `question`) |
| all off | No active session | `session.deleted`, `dispose` |

#### Plugin

TODO: Installation

## Built With

- [Node.js](https://nodejs.org/)
- [node-hid](https://github.com/node-hid/node-hid) — USB HID device access

## Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

## License

This project is licensed under the MIT License — see the [LICENSE.md](LICENSE.md) file for details