Turns the MacBook keyboard Caps Lock light into an agent status light: on while the agent works, flashing when it waits for your approval or answer, off when idle.
Install
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:xinyang920/dsh-caps-beacon
Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time — pnpm blocks those until you allow them, so an install can stop with ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED or ERR_PNPM_IGNORED_BUILDS; dsh prints the exact key to add under allowBuilds in your profile’s pnpm-workspace.yaml, and the install works on the next run. Allowing a build is a trust decision: only install sources you trust, and pin a commit (github:owner/repo#sha).
README
English | 简体中文
Use the Caps Lock LED on your MacBook as a status light for DeepSeek Harness — a DSH-native take on Mac-Agent-Beacon.
Solid = working · Fast blinking = needs your attention · Off = idle
When you send DSH off to work in the background, you can stop switching back to check on it: a glance at the keyboard tells you everything.
What the LED means
| Host state | LED |
|---|---|
| A root agent is running (tools, model calls, retries) | solid |
| An approval request is waiting for you | blinking |
An ask_user_question prompt or plan review is waiting for your answer |
blinking |
A root turn ended in error or blocked (latched until the next turn starts) |
blinking |
| Idle | off |
Attention always wins over working: the moment an approval is resolved, the
light returns to solid. Subagents and background children stay silent by
default (rootsOnly) so parallel fan-outs don't strobe your keyboard.
The plugin is a pure observer: the approval/request and tools/execute
listeners delegate through next() and never decide anything. It writes the
LED only — no key presses, no keyboard remapping, no approval-policy changes.
On exit, the helper restores the physical light to the current logical Caps
Lock state.
How it works
DSH host events ──▶ plugin state machine ──▶ beacon-led (C) ──▶ Caps Lock LED
- The plugin listens to DSH's public host events —
agent/status,approval/request,tools/execute, andsession/event. No internal interfaces are reverse-engineered, so nothing silently breaks when the agent stack updates. - A small C helper (
native/led.c, adapted from CapsPulse via Mac-Agent-Beacon, both MIT) drives the built-in keyboard's Caps Lock LED through macOS IOKit/IOHID output elements. The plugin keeps onebeacon-led servechild alive and writes1/0bytes to its stdin; blinking is a timer in the plugin. - The helper never injects key presses. If the logical Caps Lock state changes under a write, it stops immediately.
- The helper can still die for environmental reasons — a system sleep resetting the HID device, a stray signal reaching its process group. The plugin restarts it automatically (exponential backoff, 1s to 30s) and re-applies the current mode, so the beacon self-heals instead of going dark until the next dsh restart.
Requirements
- A MacBook with a built-in Apple keyboard (external and Magic Keyboards are not supported).
- macOS with Xcode Command Line Tools (
xcode-select --install) for the onemakestep. - DeepSeek Harness (
dsh) with a profile — tested withweb.
Install
# 1. Add the plugin to your profile (any profile works, `web` shown here).
dsh plugin --profile web add github:xinyang920/dsh-caps-beacon
# 2. Build the LED helper where pnpm placed the package.
cd ~/.dsh/profiles/web/node_modules/dsh-caps-beacon && make
# 3. Restart dsh web — bundle membership is read at startup.
Step 1 registers the bundle in dsh.profile.bundles automatically. Step 2
compiles build/beacon-led (about one second; the installer deliberately
does not run compiled code for you). Step 3 is required because plugins load
at boot.
Grant LED access if asked
On most machines the helper can write the LED with no extra authorization. If yours blocks it:
- Run
./build/beacon-led inspect— it explains the failure when access is denied. - Open System Settings → Privacy & Security → Input Monitoring, click
+, press
Cmd-Shift-G, and enter the absolute path ofdsh-caps-beacon/build/beacon-ledinside your profile'snode_modules. - Restart
dsh web.
Verify
# The helper finds the keyboard and LED element:
./build/beacon-led inspect
# {"keyboard":"Apple Internal Keyboard / Trackpad","led_output":true,...}
# The helper process is alive while dsh runs:
pgrep -fl beacon-led
Then give any task to a session: the LED goes solid while it runs. The
easiest blink test is to ask the agent a question that makes it call
ask_user_question — the LED blinks while the prompt waits for you.
Helper failures and unexpected exits are logged under the
[dsh-caps-beacon] prefix in the dsh log.
Configuration
Override the row by id dsh-caps-beacon in your profile's
cordis.patch.yml (a patch replaces the row's whole config, so restate
what you own):
- id: dsh-caps-beacon
config:
enabled: true
ledPath: "" # absolute path to beacon-led; default: bundled build/beacon-led
blinkIntervalMs: 250
rootsOnly: true # ignore subagents and background children
verbose: false # log every mode change
triggers:
approval: true # approval/request pending
question: true # ask_user_question / exit_plan_mode pending
error: true # turn ended in error/blocked
Troubleshooting
- LED never lights — check
pgrep -fl beacon-ledwhile dsh runs. No process means the plugin did not load: confirmdsh-caps-beaconappears indsh.profile.bundles(~/.dsh/profiles/web/package.json) and restart. A process with a dark LED usually means an external keyboard or Karabiner is involved: Karabiner-Elements can block LED access when it grabs the built-in keyboard exclusively. - LED went dark mid-session — the helper died (system sleep and terminal
Ctrl+C are the usual causes). Since v0.1.1 the plugin revives it
automatically within seconds; the revival is visible in the dsh log as
[dsh-caps-beacon] helper restarted after failure. If the LED stays dark past a minute, restartdsh web. makefails — install Xcode Command Line Tools (xcode-select --install) and retry.- Upgraded the plugin — rerun step 2 of the install (
makein the package directory) so the helper binary matches, then restart.
Uninstall
dsh plugin --profile web remove dsh-caps-beacon
Also remove dsh-caps-beacon from dsh.profile.bundles in
~/.dsh/profiles/web/package.json if your dsh version did not, then restart.
Credits
- Mac-Agent-Beacon (MIT) — the original Codex status light and the direct source of the LED helper's stdin protocol and safety checks. This project replaces its hardest part (reverse-engineering the Codex Desktop IPC stream) with DSH's public host events.
- CapsPulse (MIT) — the original IOKit/IOHID Caps Lock LED technique.
License
Links
More in this category
xmanrui/dsh-im★ 3118
Connect IM bots to DeepSeek Harness via QR codes or bot credentials (9 channels: Feishu, WeChat, DingTalk, WeCom, QQ, Slack, Telegram, Discord, and WhatsApp).
shaobeichen/dsh-pocket★ 2685
Remote phone access to the DSH Web UI: scan a QR code for LAN or public (cloudflared tunnel) access with real-time sync, a mobile-adaptive layout, and a settings tab.
OpenPetsHQ/openpets#dsh★ 1373
Bridges DeepSeek Harness lifecycle status, errors, and approval requests to a locally running OpenPets desktop companion.
c1overzz/dsh-bili-scroll★ 1150
Let your DSH agent browse Bilibili on its own, read subtitles, write a daily digest, and @ you when it finds something worth your attention.
inclusionAI/Avernet#deepseek-harness-channel-bcn★ 599
Connects DeepSeek Harness to Avernet's Bot Collaboration Network over WebSocket V2, with automatic onboarding, isolated agent sessions, tool-call events, and multi-bot routing tools.
zaofan-make/dsh-qqbot★ 213
QQ official bot channel for DeepSeek Harness (feature-rich fork of tencent-connect/dsh-qqbot): group and private chat with the full agent, sticker library with auto-tagging and AI meme replies, group management (join approval and mute), botplay interactive card events with paginated catalogs, user extension registry (custom slash commands and QQ tools), scheduled wakeups, remote approvals over QQ, and a floating dock web UI.
Community comments
Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.