Overview
rousseau signal runs the Signal bridge by shelling out to a locally installed signal-cli (https://github.com/AsamK/signal-cli) in jsonRpc mode. The daemon pumps JSON-RPC messages between the account and the agent loop. This is the most privacy-preserving transport in the tree because Signal is end-to-end encrypted and does not require any provider-hosted infrastructure.
Source: internal/cli/signal.go. Transport: internal/transport/signal/.
Synopsis
rousseau signal [--account <e164>] [--binary <path>] [--allow <e164>...] [--config <path>]
Flags
| Flag | Type | Default | Effect |
|---|---|---|---|
--account |
string | signal.account |
E.164 phone number the daemon runs as. Passed to signal-cli -a. |
--binary |
string | signal.binary or signal-cli on $PATH |
Path to the signal-cli executable. |
--allow |
[]string | signal.allowlist |
Restrict inbound to these E.164 numbers. Repeatable. |
--config |
string | inherits from root | Path to the YAML config file. |
Config keys respected
internal/config/config.go SignalConfig:
| Key | Type | Default | Effect |
|---|---|---|---|
signal.binary |
string | signal-cli |
Executable name/path. |
signal.account |
string | empty | E.164 the daemon runs as. Required. |
signal.extra_args |
[]string | empty | Inserted between -a <account> and jsonRpc. |
signal.reply_header |
string | empty | Prefix prepended to every outbound message. |
signal.allowlist |
[]string | empty | E.164 numbers permitted to send inbound messages. |
Allowlist syntax
Every entry is an E.164 phone number with the leading +:
signal:
account: "+447900123456"
allowlist:
- "+447900123456"
- "+447900222222"
The router matches inbound sender numbers exactly against the list. Empty allowlist allows every sender — do not use this posture in production.
Environment variables
| Variable | Effect |
|---|---|
ROUSSEAU_SIGNAL_ACCOUNT |
Overrides signal.account. |
ROUSSEAU_SIGNAL_BINARY |
Overrides signal.binary. |
PATH |
Used to locate signal-cli when signal.binary is unset. |
Startup sequence
- Resolve and validate the account (either flag, env, or config).
- Default
claudecli.permission_modetobypassPermissionsbecause signal-cli JSON-RPC is unattended. - Open the session store.
signal.New— spawnsignal-cli -a <account> [extra_args] jsonRpcas a subprocess.- Pump JSON-RPC over the subprocess stdio.
wiring.startCron— wire cron delivery through Signal.- Block on
client.Startuntil context cancellation.
Exit codes
| Code | Meaning |
|---|---|
| 0 | Clean context cancellation. |
| 1 | Missing --account, subprocess spawn failure, provider/store setup failure. |
| 130 | SIGINT. |
If signal-cli itself dies, the wrapper returns a non-zero code that surfaces as 1.
Worked examples
# Basic
rousseau signal --account +447900123456 --allow +447900222222
# Custom signal-cli path (e.g. flatpak install)
rousseau signal \
--binary /var/lib/flatpak/exports/bin/org.asamk.signal.SignalCli \
--account +447900123456
# Multiple allowlist entries from config
cat > ~/.config/rousseau/config.yaml <<'EOF'
signal:
account: "+447900123456"
allowlist:
- "+447900123456"
- "+447900222222"
EOF
rousseau signal
Common failure modes
exec: "signal-cli": executable file not found— install signal-cli or setsignal.binary.Failed to send message: RateLimit— Signal rate-limits new accounts. Wait, then retry.Invalid recipient— E.164 must include the leading+.- Silent inbound drops — sender not on the allowlist. Grep for
router.transport.rejected.