Problem
Signal is one of the most popular privacy-focused messaging platforms, widely used by developers and security-conscious users. Right now RustifyMyClaw only supports Telegram, WhatsApp, and Slack as channel providers. Users who prefer Signal for its end-to-end encryption and privacy guarantees cannot use RustifyMyClaw to interact with their local AI tools.
Proposed solution
Add a new channel provider signal that:
- Uses the existing
ChannelProvider / ChannelProviderFactory traits (see src/channel/ and How to Add a New Channel Provider in CLAUDE.md)
- Integrates via signal-cli — a CLI and D-Bus interface for Signal
- Daemon mode (
signal-cli -a <account> daemon --json): long-running process that emits JSON-RPC on stdout; the provider reads incoming messages and sends responses back over stdin/JSON-RPC.
- Simplest path that fits the current "proxy to existing CLI" architecture.
- Implements
resolve_users to map AllowedUser entries to Signal phone numbers or UUIDs for SecurityGate.
- Supports both direct (1:1) messages and group messages.
Steps (from CLAUDE.md checklist)
- Create
src/channel/signal.rs implementing ChannelProvider + ChannelProviderFactory.
- Add
resolve_users() for phone-number / UUID resolution.
- Implement
create() — validate signal-specific config (account number, signal-cli path), resolve users, build SecurityGate.
- Implement
start() — spawn signal-cli daemon --json, read JSON lines from stdout, check gate, build InboundMessage, send on tx.
- Implement
send_response() — write JSON-RPC send commands to the daemon's stdin (or use signal-cli send).
- Wire up in
src/channel/mod.rs and src/config.rs (KNOWN_CHANNELS).
- Add
warn_misplaced_fields() entries for signal-specific config keys.
- Add tests in
src/tests/channel/signal_test.rs.
- Update
README.md channels table and docs/configuration.md.
Alternatives considered
- Using
libsignal-client or a Rust Signal crate directly — would give tighter integration and avoid the signal-cli Java dependency, but adds significant complexity, deviates from the CLI-proxy architecture, and requires managing the Signal protocol (keys, sessions, prekeys) directly.
- Using
signal-cli in one-shot mode (signal-cli receive / signal-cli send) — simpler but introduces polling overhead and latency compared to the daemon/JSON-RPC approach.
Problem
Signal is one of the most popular privacy-focused messaging platforms, widely used by developers and security-conscious users. Right now RustifyMyClaw only supports Telegram, WhatsApp, and Slack as channel providers. Users who prefer Signal for its end-to-end encryption and privacy guarantees cannot use RustifyMyClaw to interact with their local AI tools.
Proposed solution
Add a new channel provider
signalthat:ChannelProvider/ChannelProviderFactorytraits (seesrc/channel/and How to Add a New Channel Provider inCLAUDE.md)signal-cli -a <account> daemon --json): long-running process that emits JSON-RPC on stdout; the provider reads incoming messages and sends responses back over stdin/JSON-RPC.resolve_usersto mapAllowedUserentries to Signal phone numbers or UUIDs forSecurityGate.Steps (from CLAUDE.md checklist)
src/channel/signal.rsimplementingChannelProvider+ChannelProviderFactory.resolve_users()for phone-number / UUID resolution.create()— validate signal-specific config (account number, signal-cli path), resolve users, buildSecurityGate.start()— spawnsignal-cli daemon --json, read JSON lines from stdout, check gate, buildInboundMessage, send ontx.send_response()— write JSON-RPC send commands to the daemon's stdin (or usesignal-cli send).src/channel/mod.rsandsrc/config.rs(KNOWN_CHANNELS).warn_misplaced_fields()entries for signal-specific config keys.src/tests/channel/signal_test.rs.README.mdchannels table anddocs/configuration.md.Alternatives considered
libsignal-clientor a Rust Signal crate directly — would give tighter integration and avoid thesignal-cliJava dependency, but adds significant complexity, deviates from the CLI-proxy architecture, and requires managing the Signal protocol (keys, sessions, prekeys) directly.signal-cliin one-shot mode (signal-cli receive/signal-cli send) — simpler but introduces polling overhead and latency compared to the daemon/JSON-RPC approach.