/add-signal
Add Signal channel integration via signal-cli device-link. Native adapter — no Chat SDK bridge.
Claude Code
$ npx -y skills add nanocoai/nanoclaw --skill add-signal --agent claude-code
Codex
$ npx skills add nanocoai/nanoclaw --skill add-signal -a codex -y
Cursor
$ npx skills add nanocoai/nanoclaw --skill add-signal -a cursor -y
Gemini CLI
$ npx skills add nanocoai/nanoclaw --skill add-signal -a gemini-cli -y
GitHub Copilot
$ npx skills add nanocoai/nanoclaw --skill add-signal -a github-copilot -y
OpenCode
$ npx skills add nanocoai/nanoclaw --skill add-signal -a opencode -y
Windsurf
$ npx skills add nanocoai/nanoclaw --skill add-signal -a windsurf -y
SKILL.md
add-signal.SKILL.mdname: add-signal
description: Add Signal channel integration via signal-cli device-link. Native adapter — no Chat SDK bridge.
Add Signal Channel
Adds Signal support via a native adapter that speaks JSON-RPC to a [signal-cli](https://github.com/AsamK/signal-cli) daemon — no Chat SDK bridge, only Node.js builtins. NanoClaw links to Signal as a *secondary device* on your existing phone: no new number, no bot API. Your assistant sends and receives as the number on the phone that scans the link.
Apply
1. Install signal-cli
NanoClaw talks to Signal through signal-cli, which has no bot API of its own. Install it if it isn't on PATH yet — Homebrew on macOS, the native release binary on Linux (neither needs Java). If it's already installed this is a no-op:
command -v signal-cli >/dev/null 2>&1 || bash setup/install-signal-cli.sh
2. Copy the adapter and its registration test
Fetch the `channels` branch and copy the Signal adapter and its registration test into `src/channels/` (overwrite — the branch is canonical):
src/channels/signal.ts
src/channels/signal-registration.test.ts
3. Register the adapter
Append the self-registration import to the channel barrel (skipped if the line is already present). This one line is the skill's only reach-in into core:
import './signal.js';
4. Install the QR-rendering dependency
The device-link step renders the linking URL as a terminal QR via `qrcode`. Pinned to exact versions — the supply-chain policy rejects ranges and `latest`:
qrcode@1.5.4
@types/qrcode@1.5.6
The adapter itself consumes only Node.js builtins, so there is no adapter package to install — `qrcode` is purely for rendering the link during setup.
5. Build and validate
Build first: it guards the adapter's typed core-API consumption. Then run the one integration test.
pnpm run build
pnpm exec vitest run src/channels/signal-registration.test.ts
`signal-registration.test.ts` imports the real channel barrel and asserts the registry contains `signal`. It goes red if the `import './signal.js';` line is deleted or drifts, or if the barrel fails to evaluate — so the channel genuinely would not register. The adapter has no npm dependency to guard; its typed core-API consumption is covered by the build. End-to-end delivery against a real Signal account is verified manually once the service runs.
Link your Signal account
This is the whole credential step. signal-cli opens a device-link handshake, prints a `sgnl://linkdevice…` URL, and renders it as a scannable QR. You scan it once from the phone that already runs Signal; that phone's number becomes the account NanoClaw sends and receives as — no number is registered.
The device-link runs signal-cli, so it must be reachable first — on `PATH`, or at `$SIGNAL_CLI_PATH`. If step 1's install didn't land, the link step has nothing to drive; confirm it's present before linking (re-run step 1 if this fails):
command -v signal-cli >/dev/null 2>&1 || [ -x "$SIGNAL_CLI_PATH" ]
Tell the user:
Link NanoClaw to your Signal account:
1. On the phone that runs Signal, open Signal → Settings → Linked Devices → Link New Device.
2. Scan the QR code shown below — or open the `sgnl://linkdevice…` link printed under it on that phone.
3. Wait for confirmation. The linking URL expires after ~3 minutes; re-run this step for a fresh one.
Run the device-link. It blocks until you scan, then reports the linked phone number back as the account — that number is both your owner handle and the conversation address the wiring step needs:
pnpm exec tsx setup/index.ts --step signal-auth
`owner_handle` and `platform_id` both come back as the bare phone number (e.g. `+15551234567`). Your assistant reaches you through Signal's Note to Self, so the owner conversation is addressed by your own number — not a per-contact UUID.
Persist the account
Store the linked number so the adapter binds the right account on start, then sync it into the container env:
SIGNAL_ACCOUNT={{platform_id}}Restart
Restart the service so it loads the Signal adapter and binds the account you just linked, and wait for its CLI socket before wiring:
bash setup/lib/restart.sh
Wiring
DMs
After the service starts, send any message to the Signal number from your personal Signal app. The router auto-creates a `messaging_groups` row. Then:
pnpm exec tsx scripts/q.ts data/v2.db \
"SELECT id, platform_id FROM messaging_groups WHERE channel_type='signal' ORDER BY created_at DESC LIMIT 5"
Pass the `id` to `/init-first-agent` or `/manage-channels` to wire it to an agent group.
Groups
Add the Signal number to a group from your phone, send any message, then wire the resulting row the same way. Each group gets its own session with the default `shared` mode (one session per agent + messaging group). Create the wiring with `ncl` — **the host service must be running** (`ncl` connects to it over a Unix socket):
# Engage mode/pattern default to the Signal adapter's declared channel defaults
ncl wirings create --messaging-group-id mg-GROUPID --agent-group-id ag-AGENTID
Grant user access
New Signal users (including the owner's Signal identity) are silently dropped with `not_member` until granted access. After the user's first message appears in `messaging_groups` (host service running):
ncl users create --id "signal:UUID" --kind signal --display-name "<name>"
ncl roles grant --user "signal:UUID" --role owner
ncl members add --user "signal:UUID" --group ag-AGENTID
Find the UUID from `messaging_groups.platform_id` or the `users` table.
Next Steps
If you're in the middle of
Read more
name: add-signal description: Add Signal channel integration via signal-cli device-link. Native adapter — no Chat SDK bridge.
Add Signal Channel
Adds Signal support via a native adapter that speaks JSON-RPC to a [signal-cli](https://github.com/AsamK/signal-cli) daemon — no Chat SDK bridge, only Node.js builtins. NanoClaw links to Signal as a *secondary device* on your existing phone: no new number, no bot API. Your assistant sends and receives as the number on the phone that scans the link.
Apply
1. Install signal-cli
NanoClaw talks to Signal through signal-cli, which has no bot API of its own. Install it if it isn't on PATH yet — Homebrew on macOS, the native release binary on Linux (neither needs Java). If it's already installed this is a no-op:
command -v signal-cli >/dev/null 2>&1 || bash setup/install-signal-cli.sh
2. Copy the adapter and its registration test
Fetch the `channels` branch and copy the Signal adapter and its registration test into `src/channels/` (overwrite — the branch is canonical):
src/channels/signal.ts src/channels/signal-registration.test.ts
3. Register the adapter
Append the self-registration import to the channel barrel (skipped if the line is already present). This one line is the skill's only reach-in into core:
import './signal.js';
4. Install the QR-rendering dependency
The device-link step renders the linking URL as a terminal QR via `qrcode`. Pinned to exact versions — the supply-chain policy rejects ranges and `latest`:
qrcode@1.5.4 @types/qrcode@1.5.6
The adapter itself consumes only Node.js builtins, so there is no adapter package to install — `qrcode` is purely for rendering the link during setup.
5. Build and validate
Build first: it guards the adapter's typed core-API consumption. Then run the one integration test.
pnpm run build
pnpm exec vitest run src/channels/signal-registration.test.ts
`signal-registration.test.ts` imports the real channel barrel and asserts the registry contains `signal`. It goes red if the `import './signal.js';` line is deleted or drifts, or if the barrel fails to evaluate — so the channel genuinely would not register. The adapter has no npm dependency to guard; its typed core-API consumption is covered by the build. End-to-end delivery against a real Signal account is verified manually once the service runs.
Link your Signal account
This is the whole credential step. signal-cli opens a device-link handshake, prints a `sgnl://linkdevice…` URL, and renders it as a scannable QR. You scan it once from the phone that already runs Signal; that phone's number becomes the account NanoClaw sends and receives as — no number is registered.
The device-link runs signal-cli, so it must be reachable first — on `PATH`, or at `$SIGNAL_CLI_PATH`. If step 1's install didn't land, the link step has nothing to drive; confirm it's present before linking (re-run step 1 if this fails):
command -v signal-cli >/dev/null 2>&1 || [ -x "$SIGNAL_CLI_PATH" ]
Tell the user:
Link NanoClaw to your Signal account: 1. On the phone that runs Signal, open Signal → Settings → Linked Devices → Link New Device. 2. Scan the QR code shown below — or open the `sgnl://linkdevice…` link printed under it on that phone. 3. Wait for confirmation. The linking URL expires after ~3 minutes; re-run this step for a fresh one.
Run the device-link. It blocks until you scan, then reports the linked phone number back as the account — that number is both your owner handle and the conversation address the wiring step needs:
pnpm exec tsx setup/index.ts --step signal-auth
`owner_handle` and `platform_id` both come back as the bare phone number (e.g. `+15551234567`). Your assistant reaches you through Signal's Note to Self, so the owner conversation is addressed by your own number — not a per-contact UUID.
Persist the account
Store the linked number so the adapter binds the right account on start, then sync it into the container env:
SIGNAL_ACCOUNT={{platform_id}}Restart
Restart the service so it loads the Signal adapter and binds the account you just linked, and wait for its CLI socket before wiring:
bash setup/lib/restart.sh
Wiring
DMs
After the service starts, send any message to the Signal number from your personal Signal app. The router auto-creates a `messaging_groups` row. Then:
pnpm exec tsx scripts/q.ts data/v2.db \ "SELECT id, platform_id FROM messaging_groups WHERE channel_type='signal' ORDER BY created_at DESC LIMIT 5"
Pass the `id` to `/init-first-agent` or `/manage-channels` to wire it to an agent group.
Groups
Add the Signal number to a group from your phone, send any message, then wire the resulting row the same way. Each group gets its own session with the default `shared` mode (one session per agent + messaging group). Create the wiring with `ncl` — **the host service must be running** (`ncl` connects to it over a Unix socket):
# Engage mode/pattern default to the Signal adapter's declared channel defaults ncl wirings create --messaging-group-id mg-GROUPID --agent-group-id ag-AGENTID
Grant user access
New Signal users (including the owner's Signal identity) are silently dropped with `not_member` until granted access. After the user's first message appears in `messaging_groups` (host service running):
ncl users create --id "signal:UUID" --kind signal --display-name "<name>" ncl roles grant --user "signal:UUID" --role owner ncl members add --user "signal:UUID" --group ag-AGENTID
Find the UUID from `messaging_groups.platform_id` or the `users` table.
Next Steps
If you're in the middle of
A lightweight alternative to OpenClaw that runs in containers for security. Connects to WhatsApp, Telegram, Slack, Discord, Gmail and other messaging apps,, has memory, scheduled jobs, and runs directly on Anthropic's Agents SDK
Other skills on nanoclaw.
More skills from other plugins.
browser-use
Direct browser control via CDP for web interaction: automation, scraping, testing, screenshots, and site/app work. Also covers…
agent-browser
Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling…
opencli-adapter-author
Build or improve an OpenCLI JS adapter using observed site behavior, existing adapters and browser API evidence. For ad-hoc…
Questions about add-signal.
- Which coding agents can use add-signal?
- add-signal installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.

