بنقرة واحدة
add-signal
Add Signal channel integration via signal-cli TCP daemon. Native adapter — no Chat SDK bridge.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Add Signal channel integration via signal-cli TCP daemon. Native adapter — no Chat SDK bridge.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
单后端闭环测试执行器(stack-agnostic / project-agnostic)。当一个后端 feature 收尾、需要补 superpowers/spec-kit 开发期 TDD 与契约测试覆盖不了的后端结构性测试缺口时使用:先读项目栈 (package.json / pyproject.toml / go.mod / pom.xml 等)按栈实例化对应工具,再针对实际命中的缺口 RED→GREEN 补测并固化为回归。覆盖四类后端结构性缺口——真库数据层/迁移/事务/约束、鉴权与越权 (BOLA/BFLA)、并发/竞态/限频原子性、韧性/故障注入(重试/超时/降级)。触发词:单后端测试 / 后端缺口补测 / backend testing / 真库测试 / 越权测试 / 并发测试 / 韧性测试 / 后端集成测试 / 后端回归补测。遵循 testing-system-blueprint 蓝本(风险分级 / 可追溯 / 发布门 / 三层节奏),受自愈护栏约束(只写 tests/、断言 不可弱化、禁伪造修复、有界重试、产 PR 人审)。被 test-routing-advisor 在判定"单后端"时调用,也可直接触发。
单前端闭环测试执行器(stack-agnostic / project-agnostic)。当一个前端 feature 收尾、需要补 superpowers/spec-kit 开发期覆盖不了的前端结构性测试缺口时使用:先读项目栈(package.json 或 等价清单)按栈实例化对应成熟工具,再针对实际命中的层 RED→GREEN 补测并固化为回归。与 backend-testing 的根本区别——后端缺口无现成工具需自建("施工队"),前端成熟工具齐全,本 skill 不重新发明工具,只做 三件事:装 + 配 + 把项目的视觉/交互契约翻译成这些工具能跑的断言/规则("装配工 + 监理")。覆盖五层 前端结构性缺口——编译期 lint 门、L0/L1 单测(含 getComputedStyle 断言 token/深色/涨跌色)、a11y + 跨浏览器/响应式、前后端契约 mock、视觉回归。触发词:单前端测试 / 前端缺口补测 / frontend testing / 视觉回归 / a11y 测试 / 跨浏览器测试 / 响应式测试 / token 断言 / 前后端契约 mock / 前端回归补测。 常见地基为零:很多前端 [FE] 任务出参验证只写"手测"、测试运行器/RTL/Playwright 可能完全没装—— 本 skill 第一动作是"识栈→若无测试运行器先立地基",不假设 L0/L1 已就绪。遵循 testing-system-blueprint 蓝本(风险分级 / 可追溯 / 发布门 / 三层节奏),受自愈护栏约束(只写测试不改产品码、断言不可弱化、禁伪造 修复、有界重试、产 PR 人审)。被 test-routing-advisor 在判定"单前端"时调用,也可直接触发。
完整功能链路测试执行器(stack-agnostic / project-agnostic)。当多个 feature 已陆续收尾、 某条**跨多 feature 的端到端旅程(A→B→C)首次贯通**、需要为这条关键旅程织一张端到端安全网时使用: 与前三格根本不同——本格的被测对象**不是给定的,要先从系统结构里【挖掘】出来**。先从三源 (静态代码图 + 运行时 trace + spec 契约)挖出一份**跨多 feature 的通路清单(path inventory)**, 挑 P0 关键旅程,再端到端验证、固化成安全网。覆盖跨多 feature 且含非 UI 跳步(定时任务 / 异步 / 跨通道)的 完整链路;单 feature 内单切片归"局部前后端"第三格,不在这里。两个最独特点:① 被测对象要先被挖掘出来; ② 它是**安全网层**——少而精只盖 P0;**若 bug 首次在这层被发现,说明下层(单后端/单前端/局部前后端)漏测了, 应回补下层**。六步闭环:挖通路+选 P0 → 全系统编排+只 stub 外部边界 → 条件命中 → 两层落地 → RED→GREEN(禁 sleep, fake clock/手动触发定时任务/poll-retry 等最终态)→ 归档+拆栈+PR 人审。触发词:完整功能链路 / 端到端旅程 / 跨 feature 测试 / 通路挖掘 / path inventory / 关键旅程 / 安全网 / journey 测试 / full chain testing / e2e journey / 链路贯通测试。天然要最多代码才能跑、是最后才能执行的一格;代码未落地时只能"挖候选通路 + 写 RED E2E"不能跑。遵循 testing-system-blueprint 蓝本(风险分级 / 可追溯 / 发布门 / 三层节奏),受自愈护栏约束 (只写测试不改产品码、断言不可弱化、禁伪造修复、有界重试、产 PR 人审,发现真 bug 回交 superpowers TDD)。 被 test-routing-advisor 判定"完整功能链路"时调用,也可直接触发。兄弟:backend-testing(单后端)/ frontend-testing(单前端)/ fullstack-slice-testing(局部前后端)。
局部前后端接缝测试执行器(stack-agnostic / project-agnostic)。当一个 feature 的前后端两侧都收尾、 需要把"单前端阶段拿来 mock 的那份假设"与"单后端的真实行为"做一次对账时使用:在**单 feature 内**, 让消费者侧(前端/调用方)↔ 提供者侧(后端/被调方)的**单条切片**以真实形态对接、停止 mock,验证接缝。 它是 backend-testing / frontend-testing 的对账——单前端 mock 撒的谎(字段/类型/状态码/错误体/鉴权/时序) 在这里穿帮。**仅限单 feature 内单切片,不跨 feature**(跨多 feature 旅程属"完整功能链路"第四格)。覆盖四个 能力缺口——环境编排(让两侧+依赖以真实形态可复现一键起来)、契约真实性(消费者 mock↔提供者规格比对)、 接缝粘合(凭证透传/序列化往返/错误映射/头部跨域)、真实时序(条件命中:仅切片含流式/实时/异步才测)。 与前两格的根本区别——新难点是"起真栈(环境编排)"而非写断言:前两格能把另一侧 mock 掉,这格不能, 必须真把两侧拉活。先读两侧栈清单按栈实例化编排/契约工具,再 RED→GREEN 补接缝断言并固化为回归。 触发词:局部前后端测试 / 前后端接缝测试 / 切片对账 / 真前后端对接 / 起真栈集成 / 契约漂移验证 / 消费者契约对账 / fullstack slice testing / seam testing / contract drift / 前后端集成补测。 遵循 testing-system-blueprint 蓝本(风险分级 / 可追溯 / 发布门 / 三层节奏),受自愈护栏约束(只写测试不改 产品码、断言不可弱化、禁伪造修复、有界重试、产 PR 人审)。被 test-routing-advisor 判定"局部前后端"时调用, 也可直接触发。兄弟:backend-testing(单后端)/ frontend-testing(单前端)。
测试路由顾问:在某个 feature 的所有 task 完成(全绿)、进入收尾阶段时,先通篇扫描该 feature 的所有 task/文件,把它们归入一个「开放可增减」的场景类别集合(单后端 / 单前端 / 局部前后端 / 完整功能链路 / 可增类…),判定本 feature 整体属于哪一类,再把每个测试缺口 「路由到对应类别的执行器 skill」去闭环补测。它是 stack-agnostic 的检测器 / 路由器: 本 skill 只做「判类 + 标缺口 + 路由」,不写死任何单栈工具为答案——具体工具由被路由到的 类别 skill 按栈(读 package.json / pyproject / go.mod 等判栈后)实例化。当前路由去向: 单后端 → `backend-testing` skill;单前端 → `frontend-testing` skill;局部前后端 → `fullstack-slice-testing` skill;完整功能链路 → `full-chain-testing` skill(gstack `/qa` 折叠进它的 UI 可走段,非依赖)。判类、缺口标注、 三层节奏、可追溯、发布门等方法标准统一遵循 `testing-system-blueprint` skill。判类信号来自 任务范围标签、依赖图、跨模块契约声明、验收标准 AC,因此与具体项目无关。它的杀手锏:从依赖图 推导出「完成本 feature 后某条完整功能链路(A→B→C)首次贯通」并主动提示「这条链路现在可以 端到端测了」——这是人最容易忘的事。 当某个 feature 正在收尾、用户说出类似「这个 feature 该测什么 / 收尾测试 / 测试路由 / feature 完成后测什么 / 该用什么测试 / run test routing / what should I test now / which testing tool should I use / what tests does this feature need」时务必使用。 它只做建议与路由——绝不编写、运行或强制任何测试;测试是否真的写了、过了、断言有没有被弱化, 靠确定性的 CI 闸和护栏化自愈 agent 来保证。
测试体系蓝本(testing blueprint / test strategy)——一份 stack-agnostic、project-agnostic 的"测试作为体系"方法骨架。当需要确定测试策略、做风险分级(P0–P3)、建立需求↔测试可追溯、 规划三层测试节奏、设计闭环补测、定义发布 go/no-go 门(release gate)时遵循本蓝本。 触发词:测试体系蓝本、测试策略、测试策略蓝本、风险分级、可追溯、需求追溯、发布门、 闭环补测、testing blueprint、test strategy、test pyramid、release gate。 它被 test-routing-advisor(路由器)和各类别测试 skill(如 backend-testing)共同遵循。 本蓝本只给"方法与标准",不写死任何语言/框架/工具,不执行测试也不强制门禁—— 能力是通用原语,工具由调用方读项目栈后实例化;门禁的强制由 CI/hook/pre-commit 承担。
| name | add-signal |
| description | Add Signal channel integration via signal-cli TCP daemon. Native adapter — no Chat SDK bridge. |
Adds Signal messaging support via a native adapter that speaks JSON-RPC to a signal-cli TCP daemon. No Chat SDK bridge — only Node.js builtins (node:net, node:child_process, node:fs).
Unlike Telegram or Discord, Signal has no bot API. NanoClaw registers as a full Signal account on a dedicated phone number (recommended) or links as a secondary device on your existing number.
signal-cli requires Java 17+:
java -version
If missing:
brew install --cask temurin@17sudo apt-get install -y default-jresudo dnf install -y java-17-openjdkJava 17–25 all work.
brew install signal-cliSIGNAL_CLI_VERSION=$(curl -fsSL https://api.github.com/repos/AsamK/signal-cli/releases/latest | python3 -c "import sys,json; print(json.load(sys.stdin)['tag_name'][1:])")
curl -fsSL "https://github.com/AsamK/signal-cli/releases/download/v${SIGNAL_CLI_VERSION}/signal-cli-${SIGNAL_CLI_VERSION}-Linux-native.tar.gz" \
| tar -xz -C ~/.local
ln -sf ~/.local/signal-cli ~/.local/bin/signal-cli
signal-cli --version
The Linux native tarball extracts a single binary directly to
~/.local/signal-cli(not into a subdirectory). The symlink above puts it on PATH.
Two paths. The new-number path is recommended and battle-tested.
Use a dedicated SIM or VoIP number. NanoClaw owns it entirely.
VoIP numbers: Signal requires SMS verification before voice. Some VoIP providers are blocked even for voice calls. If registration fails with an auth error, try a different provider or a physical SIM.
Step 1: Solve the CAPTCHA
Signal requires a CAPTCHA on first registration:
https://signalcaptchas.org/registration/generate.html in a browsersignalcaptcha:// — the token is everything after that prefixStep 2: Request SMS verification
signal-cli -a +1YOURNUMBER register --captcha "PASTE_TOKEN_HERE"
Step 3: Voice call fallback (if your number can't receive SMS)
Wait ~60 seconds after the SMS request, then:
signal-cli -a +1YOURNUMBER register --voice --captcha "SAME_TOKEN"
Signal calls your number and reads a 6-digit code. The same captcha token is reusable — no need to solve a new one.
You must request SMS first. Requesting voice immediately fails with
Invalid verification method: Before requesting voice verification…
Step 4: Verify
signal-cli -a +1YOURNUMBER verify CODE
No output = success.
Step 5: Set profile name (optional)
⚠ Stop NanoClaw before running signal-cli commands — the daemon holds an exclusive lock on its data directory while running.
# macOS
launchctl unload ~/Library/LaunchAgents/com.nanoclaw.plist
signal-cli -a +1YOURNUMBER updateProfile --name "YourBotName"
# optionally: --avatar /path/to/avatar.jpg
launchctl load ~/Library/LaunchAgents/com.nanoclaw.plist
# Linux
systemctl --user stop nanoclaw
signal-cli -a +1YOURNUMBER updateProfile --name "YourBotName"
systemctl --user start nanoclaw
Joins an existing Signal account as a secondary device. Simpler, but NanoClaw shares your personal number.
signal-cli -a +1YOURNUMBER link --name "NanoClaw"
This prints a tsdevice: URI. Scan it as a QR code on your phone: Settings → Linked Devices → Link New Device. QR codes expire in ~30 seconds — re-run if it expires.
Skip to Credentials if all of these are already in place:
src/channels/signal.ts and src/channels/signal.test.ts both existsrc/channels/index.ts contains import './signal.js';Otherwise continue. Every step below is safe to re-run.
git fetch origin channels
git show origin/channels:src/channels/signal.ts > src/channels/signal.ts
git show origin/channels:src/channels/signal.test.ts > src/channels/signal.test.ts
Append to src/channels/index.ts (skip if the line is already present):
import './signal.js';
pnpm run build
No npm packages to install — the adapter uses only Node.js builtins.
Add to .env:
SIGNAL_ACCOUNT=+1YOURNUMBER
# TCP daemon host and port (default: 127.0.0.1:7583)
SIGNAL_TCP_HOST=127.0.0.1
SIGNAL_TCP_PORT=7583
# Path to the signal-cli binary (default: resolved on PATH)
SIGNAL_CLI_PATH=/usr/local/bin/signal-cli
# Whether NanoClaw manages the daemon lifecycle (default: true).
# Set to false if you run signal-cli daemon externally.
SIGNAL_MANAGE_DAEMON=true
# signal-cli data directory (default: ~/.local/share/signal-cli)
SIGNAL_DATA_DIR=~/.local/share/signal-cli
Security note: keep the TCP host on 127.0.0.1. The daemon has no auth — binding it to a public interface would expose your full Signal account to the network.
Sync to container: mkdir -p data/env && cp .env data/env/env
# macOS
launchctl kickstart -k gui/$(id -u)/com.nanoclaw
# Linux
systemctl --user restart nanoclaw
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.
Add the Signal number to a group from your phone, send any message, then wire the resulting row the same way. For isolated per-group sessions:
NOW=$(date -u +"%Y-%m-%dT%H:%M:%S.000Z")
pnpm exec tsx scripts/q.ts data/v2.db "
INSERT OR IGNORE INTO messaging_group_agents
(id, messaging_group_id, agent_group_id, session_mode, priority, created_at)
VALUES
('mga-'||hex(randomblob(8)), 'mg-GROUPID', 'ag-AGENTID', 'isolated', 0, '$NOW');
"
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:
NOW=$(date -u +"%Y-%m-%dT%H:%M:%S.000Z")
pnpm exec tsx scripts/q.ts data/v2.db "
INSERT OR REPLACE INTO user_roles (user_id, role, agent_group_id, granted_by, granted_at)
VALUES ('signal:UUID', 'owner', NULL, 'system', '$NOW');
INSERT OR IGNORE INTO agent_group_members (user_id, agent_group_id, added_by, added_at)
VALUES ('signal:UUID', 'ag-AGENTID', 'system', '$NOW');
"
Find the UUID from messaging_groups.platform_id or the users table.
If you're in the middle of /setup, return to the setup flow now.
Otherwise, run /init-first-agent to create an agent and wire it to your Signal DM, or /manage-channels to wire this channel to an existing agent group.
signalsignal:{UUID} — sender's Signal UUID (ACI), not their phone numbersignal:{base64GroupId} — base64-encoded GroupV2 IDmessaging_groups as shown aboveisolated session mode**bold**, *italic* / _italic_, `code`, ```code fence```, ~~strike~~, ||spoiler|| (converted to Signal's offset-based text styles)replyTo* fields populated from Signal quotes(platformId, text) within a 10 s TTL to avoid syncMessage loopsisFromMe: true[Voice Message] placeholder text. Run /add-voice-transcription for local transcription via parakeet-mlxNot supported yet: outbound file attachments (logged and dropped), edit/delete messages, reactions.
grep "Signal" logs/nanoclaw.log | tail
If you see Signal daemon failed to start. Is signal-cli installed and your account linked?:
signal-cli is on PATH (or set SIGNAL_CLI_PATH)signal-cli -a +1YOURNUMBER listIdentities should succeed without promptingIf you see Signal daemon not reachable at 127.0.0.1:7583 and SIGNAL_MANAGE_DAEMON=false, start the daemon yourself: signal-cli -a +1YOURNUMBER daemon --tcp 127.0.0.1:7583.
grep "Signal channel connected" logs/nanoclaw.log | tail -1pnpm exec tsx scripts/q.ts data/v2.db "SELECT mg.platform_id, mg.name FROM messaging_groups mg JOIN messaging_group_agents mga ON mg.id = mga.messaging_group_id WHERE mg.channel_type='signal'"launchctl print gui/$(id -u)/com.nanoclaw (macOS) / systemctl --user status nanoclaw (Linux)If you see Signal channel lost TCP connection to signal-cli daemon in the logs, the daemon dropped the connection. Restart the service to re-establish.
not_memberThe Signal user hasn't been granted membership. See "Grant user access" above. This affects every new Signal user, including the owner's Signal identity — which is a separate user record from their identity on other channels even if it's the same person.
Signal requires a captcha for new registrations. Go to https://signalcaptchas.org/registration/generate.html, solve it, right-click "Open Signal", copy the link, extract the token after signalcaptcha://.
Invalid verification method: Before requesting voice verification…You must request SMS first, wait ~60 seconds, then request voice. Both steps can use the same captcha token.
signal-cli holds an exclusive lock on its data directory while the daemon is running. Stop NanoClaw before running any signal-cli commands directly, then restart afterward.
Modern Signal groups use GroupV2. The adapter must extract the group ID from envelope?.dataMessage?.groupV2?.id — not groupInfo?.groupId, which is GroupV1/legacy. If group messages are routing as DMs, check src/channels/signal.ts and confirm the groupId extraction falls through to groupV2.id.
Install Java 17+ — see the Prerequisites section above.
QR codes expire in ~30 seconds. Re-run the link command to generate a new one.