Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/nullclaw/nullclaw/llms.txt

Use this file to discover all available pages before exploring further.

The Signal channel connects NullClaw to Signal Messenger using the signal-cli daemon’s HTTP/JSON-RPC API for maximum privacy and security.

Features

  • End-to-end encrypted messaging
  • Group chat support
  • Allowlist-based access control
  • UUID and phone number support
  • Configurable group policies
  • Real-time message delivery via Server-Sent Events (SSE)
  • Typing indicators
  • Attachment handling

Prerequisites

You must have signal-cli installed and running in daemon mode:
# Install signal-cli (example for macOS)
brew install signal-cli

# Register your phone number (first time only)
signal-cli -u +1234567890 register
signal-cli -u +1234567890 verify <CODE>

# Start daemon mode
signal-cli --account +1234567890 daemon --http 127.0.0.1:8080
See signal-cli documentation for detailed installation and setup instructions.

Configuration

Add Signal to your config.json:
{
  "channels": {
    "signal": {
      "accounts": {
        "main": {
          "http_url": "http://127.0.0.1:8080",
          "account": "+1234567890",
          "allow_from": ["+1111111111", "uuid:a1b2c3d4-..."],
          "group_allow_from": ["+1111111111"],
          "group_policy": "allowlist",
          "ignore_attachments": true,
          "ignore_stories": true
        }
      }
    }
  }
}

Configuration Options

http_url
string
required
Base URL of the signal-cli daemon (e.g., http://127.0.0.1:8080). Trailing slashes are automatically stripped.
account
string
required
Your Signal account phone number in E.164 format (e.g., +1234567890)
allow_from
string[]
default:"[]"
List of allowed senders (phone numbers or UUIDs). Empty list = deny all (secure by default).Formats:
  • Phone: "+1234567890"
  • UUID: "uuid:a1b2c3d4-5678-90ab-cdef-1234567890ab"
  • Wildcard: "*" (not recommended)
group_allow_from
string[]
default:"[]"
Senders allowed in group chats when group_policy is "allowlist". If empty, falls back to allow_from.
group_policy
enum
default:"allowlist"
Group message handling:
  • "open" — Respond to all group messages
  • "allowlist" — Only respond to senders in group_allow_from
  • "disabled" — Ignore all group messages
ignore_attachments
boolean
default:"true"
Skip messages that contain only attachments with no text content
ignore_stories
boolean
default:"true"
Ignore Signal story posts
account_id
string
default:"default"
Account identifier for multi-account setups

Setup Guide

1

Install signal-cli

macOS (Homebrew):
brew install signal-cli
Linux (Debian/Ubuntu):
# See https://github.com/AsamK/signal-cli for latest instructions
wget https://github.com/AsamK/signal-cli/releases/download/v0.13.5/signal-cli_0.13.5_amd64.deb
sudo dpkg -i signal-cli_0.13.5_amd64.deb
From source:
git clone https://github.com/AsamK/signal-cli.git
cd signal-cli
./gradlew installDist
2

Register Your Phone Number

# Request verification code
signal-cli -u +1234567890 register

# Enter the code you received via SMS
signal-cli -u +1234567890 verify 123456
Note: Use a dedicated phone number for your bot, not your personal Signal account.
3

Start signal-cli Daemon

signal-cli --account +1234567890 daemon --http 127.0.0.1:8080
Leave this running in the background or set up as a system service.
4

Get Sender UUIDs or Phone Numbers

From your Signal app, share your contact information with someone who will send messages to the bot. You can use:
  • Phone numbers (e.g., +1234567890)
  • UUIDs from signal-cli logs when messages arrive
5

Configure NullClaw

Add Signal to ~/.nullclaw/config.json:
{
  "channels": {
    "signal": {
      "accounts": {
        "main": {
          "http_url": "http://127.0.0.1:8080",
          "account": "+1234567890",
          "allow_from": ["+1111111111"]
        }
      }
    }
  }
}
6

Start NullClaw

Run nullclaw and send a Signal message to the bot’s phone number from an allowed contact. You should receive a response.

Group Chat Support

NullClaw supports Signal group chats with configurable policies:

Allowlist-Based Groups

{
  "group_policy": "allowlist",
  "group_allow_from": ["+1111111111", "+2222222222"]
}
Only specified users can interact in groups.

Open Groups

{
  "group_policy": "open"
}
Respond to all messages in groups (not recommended for privacy).

Disabled Groups

{
  "group_policy": "disabled"
}
Ignore all group messages, only respond to 1:1 DMs.

UUID vs Phone Number

Signal supports both phone numbers and UUIDs for identification: Phone numbers (E.164 format):
{
  "allow_from": ["+1234567890", "+9876543210"]
}
UUIDs (for privacy mode users):
{
  "allow_from": [
    "uuid:a1b2c3d4-5678-90ab-cdef-1234567890ab",
    "uuid:b2c3d4e5-6789-01bc-defg-234567890abc"
  ]
}
Mixed:
{
  "allow_from": [
    "+1234567890",
    "uuid:a1b2c3d4-5678-90ab-cdef-1234567890ab"
  ]
}

Message Limits

Signal has no strict character limit, but NullClaw chunks messages at 4096 characters for optimal UX.

Attachment Handling

By default, NullClaw ignores attachment-only messages:
{
  "ignore_attachments": true
}
Set to false to process messages with attachments. Attachment content is not passed to the agent (only text).

Running as a System Service

systemd (Linux)

Create /etc/systemd/system/signal-cli.service:
[Unit]
Description=signal-cli daemon
After=network.target

[Service]
Type=simple
User=nullclaw
ExecStart=/usr/local/bin/signal-cli --account +1234567890 daemon --http 127.0.0.1:8080
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target
Enable and start:
sudo systemctl enable signal-cli
sudo systemctl start signal-cli

launchd (macOS)

Create ~/Library/LaunchAgents/com.signal-cli.daemon.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.signal-cli.daemon</string>
    <key>ProgramArguments</key>
    <array>
        <string>/opt/homebrew/bin/signal-cli</string>
        <string>--account</string>
        <string>+1234567890</string>
        <string>daemon</string>
        <string>--http</string>
        <string>127.0.0.1:8080</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <true/>
</dict>
</plist>
Load:
launchctl load ~/Library/LaunchAgents/com.signal-cli.daemon.plist

Troubleshooting

Daemon Not Starting

  1. Verify signal-cli is installed: signal-cli --version
  2. Check that phone number is registered: signal-cli -u +1234567890 listIdentities
  3. Ensure port 8080 is not in use: lsof -i :8080
  4. Check daemon logs for errors

Messages Not Received

  1. Verify daemon is running: curl http://127.0.0.1:8080/api/v1/check
  2. Check sender is in allow_from list
  3. Verify phone number format is E.164 (+ prefix, country code)
  4. For groups, check group_policy and group_allow_from
  5. Review NullClaw logs: nullclaw --log-level debug

Connection Refused

  1. Verify http_url matches daemon address (default: http://127.0.0.1:8080)
  2. Check firewall rules if daemon is on remote host
  3. Ensure daemon is listening on correct interface (not just localhost if remote)

UUID Mismatches

  1. UUIDs change when users reset their Signal account
  2. Check signal-cli logs for current sender UUIDs
  3. Update allow_from with new UUIDs as needed

Source Code

Implementation: src/channels/signal.zig