signal-db-cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +248 -0
- package/docs/MANUAL.md +187 -0
- package/lib/signal-db.js +432 -0
- package/package.json +47 -0
- package/signal-db-cli.js +625 -0
- package/signal-db-mcp.js +206 -0
package/README.md
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
# Signal DB CLI & MCP Server
|
|
2
|
+
|
|
3
|
+
Read-only access to your local Signal Desktop database — from the terminal or through AI assistants via MCP.
|
|
4
|
+
|
|
5
|
+
> **Read-only.** The tool never modifies your Signal database.
|
|
6
|
+
|
|
7
|
+
## Prerequisites
|
|
8
|
+
|
|
9
|
+
- **Signal Desktop** installed and set up
|
|
10
|
+
- **Node.js 24** (see `.nvmrc`)
|
|
11
|
+
- **macOS / Linux / Windows**
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install -g signal-db-cli --ignore-scripts=false
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
The `--ignore-scripts=false` flag is required to compile the native SQLCipher addon.
|
|
20
|
+
|
|
21
|
+
## Getting the Decryption Key
|
|
22
|
+
|
|
23
|
+
Signal Desktop encrypts its database with a key stored in your system keychain / keyring. Extract it and save to `~/.signal-db-cli/.env` with:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
signal-db-cli decrypt
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
This works on **macOS** (Keychain), **Linux** (GNOME Keyring / KWallet), and **Windows** (DPAPI). The key is saved automatically — no manual steps needed.
|
|
30
|
+
|
|
31
|
+
> **Note:** Close Signal Desktop before use — Signal holds an exclusive lock on the database.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Part 1: MCP Server (AI Assistants)
|
|
36
|
+
|
|
37
|
+
The MCP server lets AI assistants browse your Signal messages, conversations, and calls using natural language.
|
|
38
|
+
|
|
39
|
+
### Available Tools
|
|
40
|
+
|
|
41
|
+
| Tool | Description |
|
|
42
|
+
|------|-------------|
|
|
43
|
+
| `get_messages` | Search and filter messages — full-text search, conversation filter, unread/unanswered, date ranges, direction |
|
|
44
|
+
| `get_conversations` | List or search conversations by name, phone, or ID |
|
|
45
|
+
| `get_calls` | Recent call history |
|
|
46
|
+
| `get_message_by_id` | Retrieve a single message by ID (full body) |
|
|
47
|
+
| `get_phone` | Look up phone numbers by contact name |
|
|
48
|
+
|
|
49
|
+
### Setup
|
|
50
|
+
|
|
51
|
+
> If you have the key in `~/.signal-db-cli/.env`, you can omit `SIGNAL_DECRYPTION_KEY` from the configs below — the server loads it automatically.
|
|
52
|
+
|
|
53
|
+
#### Claude Code
|
|
54
|
+
|
|
55
|
+
Run in your terminal:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
claude mcp add signal-db -- signal-db-mcp
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Or with an explicit key:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
claude mcp add signal-db -e SIGNAL_DECRYPTION_KEY=<your-hex-key> -- signal-db-mcp
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
#### Claude Desktop
|
|
68
|
+
|
|
69
|
+
Open the config file:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
open ~/Library/Application\ Support/Claude/claude_desktop_config.json
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Add the `signal-db` server (merge into existing `mcpServers` if needed):
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"mcpServers": {
|
|
80
|
+
"signal-db": {
|
|
81
|
+
"command": "signal-db-mcp",
|
|
82
|
+
"env": {
|
|
83
|
+
"SIGNAL_DECRYPTION_KEY": "<your-hex-key>"
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Then restart Claude Desktop.
|
|
91
|
+
|
|
92
|
+
#### Cursor
|
|
93
|
+
|
|
94
|
+
One-click install:
|
|
95
|
+
|
|
96
|
+
[<img src="https://cursor.com/deeplink/mcp-install-dark.svg" alt="Install in Cursor" height="32">](https://cursor.com/en/install-mcp?name=signal-db&config=eyJjb21tYW5kIjoic2lnbmFsLWRiLW1jcCJ9)
|
|
97
|
+
|
|
98
|
+
Or manually — open the config file:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
# macOS / Linux
|
|
102
|
+
open .cursor/mcp.json # project-level
|
|
103
|
+
open ~/.cursor/mcp.json # global
|
|
104
|
+
|
|
105
|
+
# Or create it
|
|
106
|
+
mkdir -p .cursor && cat > .cursor/mcp.json << 'EOF'
|
|
107
|
+
{
|
|
108
|
+
"mcpServers": {
|
|
109
|
+
"signal-db": {
|
|
110
|
+
"command": "signal-db-mcp",
|
|
111
|
+
"env": {
|
|
112
|
+
"SIGNAL_DECRYPTION_KEY": "<your-hex-key>"
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
EOF
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Then restart Cursor or reload the MCP servers (Cmd+Shift+P > "MCP: Reload").
|
|
121
|
+
|
|
122
|
+
### Example Prompts
|
|
123
|
+
|
|
124
|
+
Once the MCP server is connected, you can ask your AI assistant things like:
|
|
125
|
+
|
|
126
|
+
**Catch up on conversations:**
|
|
127
|
+
> What was I last discussing with John Doe?
|
|
128
|
+
|
|
129
|
+
> Show me all messages from the "Project Alpha" group in the last 3 days.
|
|
130
|
+
|
|
131
|
+
**Track what needs your attention:**
|
|
132
|
+
> Which messages are waiting for my reply?
|
|
133
|
+
|
|
134
|
+
> What unread messages do I have?
|
|
135
|
+
|
|
136
|
+
**Look up contacts:**
|
|
137
|
+
> What is John Doe's phone number?
|
|
138
|
+
|
|
139
|
+
**Summarize group activity:**
|
|
140
|
+
> Summarize the activity of the "Support Team" group for February 2026. What were the main topics, how were they resolved, who asked questions and who helped? Give me an executive summary.
|
|
141
|
+
|
|
142
|
+
**Cross-conversation research:**
|
|
143
|
+
> Find all messages mentioning "deadline" in the last week across all conversations.
|
|
144
|
+
|
|
145
|
+
> What did the AI User Group discuss recently? What are the key takeaways?
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Part 2: CLI
|
|
150
|
+
|
|
151
|
+
### Commands
|
|
152
|
+
|
|
153
|
+
| Command | Description |
|
|
154
|
+
|---------|-------------|
|
|
155
|
+
| `messages [query]` (alias: `msg`) | Messages with filters (full-text, conversation, unread, unanswered, date) |
|
|
156
|
+
| `convs [query]` | List conversations (optionally search by name) |
|
|
157
|
+
| `phone <query>` | Look up phone number by contact name |
|
|
158
|
+
| `calls [n]` | Call history |
|
|
159
|
+
| `interactive` (alias: `i`) | Interactive mode — main menu |
|
|
160
|
+
| `decrypt` | Extract decryption key and save to `~/.signal-db-cli/.env` |
|
|
161
|
+
| `manual` | Extended documentation |
|
|
162
|
+
|
|
163
|
+
### Message Filters
|
|
164
|
+
|
|
165
|
+
| Flag | Description |
|
|
166
|
+
|------|-------------|
|
|
167
|
+
| `--conv <name>` | Conversation filter — partial name (searches all matches), `=Exact Name` for single match, or UUID |
|
|
168
|
+
| `--unread` | Only unread incoming messages |
|
|
169
|
+
| `--unanswered [hours]` | Unanswered, older than N hours (default 24) |
|
|
170
|
+
| `--from <date>` | From date (ISO e.g. `2025-01-15`, or relative: `5h`, `3d`, `10m`) |
|
|
171
|
+
| `--to <date>` | To date (ISO or relative) |
|
|
172
|
+
| `--incoming` | Only incoming messages |
|
|
173
|
+
| `--outgoing` | Only outgoing messages |
|
|
174
|
+
|
|
175
|
+
### Global Flags
|
|
176
|
+
|
|
177
|
+
| Flag | Description |
|
|
178
|
+
|------|-------------|
|
|
179
|
+
| `-i, --interactive` | Interactive mode (Inquirer) |
|
|
180
|
+
| `--json` | Output as JSON |
|
|
181
|
+
| `-n, --limit <N>` | Limit number of results |
|
|
182
|
+
| `-V, --version` | Show version |
|
|
183
|
+
|
|
184
|
+
### Examples
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
# Unread messages
|
|
188
|
+
signal-db-cli messages --unread
|
|
189
|
+
|
|
190
|
+
# Last 20 messages
|
|
191
|
+
signal-db-cli messages
|
|
192
|
+
|
|
193
|
+
# Messages from a conversation (partial name — searches all matches)
|
|
194
|
+
signal-db-cli messages --conv "Tomas"
|
|
195
|
+
|
|
196
|
+
# Exact conversation name match (= prefix)
|
|
197
|
+
signal-db-cli messages --conv "=Project Alpha"
|
|
198
|
+
|
|
199
|
+
# Full-text search
|
|
200
|
+
signal-db-cli messages "deadline"
|
|
201
|
+
|
|
202
|
+
# Date range
|
|
203
|
+
signal-db-cli messages --from 2025-01-01 --to 2025-02-17
|
|
204
|
+
|
|
205
|
+
# Relative date (last 5 hours)
|
|
206
|
+
signal-db-cli messages --from 5h
|
|
207
|
+
|
|
208
|
+
# Unanswered messages (older than 48h)
|
|
209
|
+
signal-db-cli messages --unanswered 48
|
|
210
|
+
|
|
211
|
+
# List group conversations
|
|
212
|
+
signal-db-cli convs --type group
|
|
213
|
+
|
|
214
|
+
# Phone number lookup
|
|
215
|
+
signal-db-cli phone "Smith"
|
|
216
|
+
|
|
217
|
+
# Call history
|
|
218
|
+
signal-db-cli calls 30
|
|
219
|
+
|
|
220
|
+
# Interactive mode
|
|
221
|
+
signal-db-cli interactive
|
|
222
|
+
|
|
223
|
+
# JSON output for scripting
|
|
224
|
+
signal-db-cli messages --unread --json | jq '.messages[0].body'
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Search Syntax
|
|
228
|
+
|
|
229
|
+
Full-text search in `messages [query]`:
|
|
230
|
+
|
|
231
|
+
- **Space** = OR — `hello deadline` finds messages with "hello" OR "deadline"
|
|
232
|
+
- **Comma** = AND — `hello, deadline` finds messages with both
|
|
233
|
+
- **Prefix matching** — automatic: `hel` matches "hello", "help"
|
|
234
|
+
- Combined: `hello deadline, meeting` = (hello OR deadline) AND meeting
|
|
235
|
+
|
|
236
|
+
### Conversation Filter (`--conv`)
|
|
237
|
+
|
|
238
|
+
Three modes:
|
|
239
|
+
|
|
240
|
+
1. **Partial name** (`--conv "Tomas"`) — finds all matching conversations, queries messages across all of them
|
|
241
|
+
2. **Exact match** (`--conv "=Project Alpha"`) — `=` prefix forces exact name match, returns a single conversation
|
|
242
|
+
3. **UUID** (`--conv "a1b2c3d4-e5f6-..."`) — direct conversation ID
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## License
|
|
247
|
+
|
|
248
|
+
MIT
|
package/docs/MANUAL.md
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# Signal DB CLI – User Manual
|
|
2
|
+
|
|
3
|
+
## Introduction
|
|
4
|
+
|
|
5
|
+
Signal DB CLI is a tool for working with the local encrypted Signal Desktop database. It allows you to read messages, conversations, and calls without opening the Signal app.
|
|
6
|
+
|
|
7
|
+
**Important:** The tool operates in read-only mode. It does not modify the database.
|
|
8
|
+
|
|
9
|
+
## Prerequisites
|
|
10
|
+
|
|
11
|
+
- Signal Desktop installed
|
|
12
|
+
- Node.js 24
|
|
13
|
+
|
|
14
|
+
## Database Location
|
|
15
|
+
|
|
16
|
+
Signal stores data in an encrypted SQLite file:
|
|
17
|
+
|
|
18
|
+
- **macOS:** `~/Library/Application Support/Signal/sql/db.sqlite`
|
|
19
|
+
- **Windows:** `%APPDATA%\Signal\sql\db.sqlite`
|
|
20
|
+
- **Linux:** `~/.config/Signal/sql/db.sqlite`
|
|
21
|
+
|
|
22
|
+
## Configuration
|
|
23
|
+
|
|
24
|
+
Run `signal-db-cli decrypt` to extract the decryption key and save it automatically to `~/.signal-db-cli/.env`. This works on macOS (Keychain), Linux (GNOME Keyring / KWallet), and Windows (DPAPI).
|
|
25
|
+
|
|
26
|
+
The key is stored in the `SIGNAL_DECRYPTION_KEY` environment variable. The tool loads it from:
|
|
27
|
+
|
|
28
|
+
1. **Local `.env`** in the current directory
|
|
29
|
+
2. **Global config** in `~/.signal-db-cli/.env`
|
|
30
|
+
|
|
31
|
+
**Note:** Close Signal Desktop before use, otherwise the database may be locked.
|
|
32
|
+
|
|
33
|
+
## Command Overview
|
|
34
|
+
|
|
35
|
+
### Commands
|
|
36
|
+
|
|
37
|
+
| Command | Description |
|
|
38
|
+
|---------|-------------|
|
|
39
|
+
| `messages [query]` (alias: `msg`) | Messages with filters (full-text, conversation, unread, unanswered, date) |
|
|
40
|
+
| `convs [query]` | List conversations (optionally search by name) |
|
|
41
|
+
| `phone <query>` | Look up phone number by contact name |
|
|
42
|
+
| `calls [n]` | Call history |
|
|
43
|
+
| `interactive` (alias: `i`) | Interactive mode – main menu |
|
|
44
|
+
| `decrypt` | Extract decryption key from Signal Desktop and save to ~/.signal-db-cli/.env |
|
|
45
|
+
| `manual` | This documentation |
|
|
46
|
+
|
|
47
|
+
### Filters for `messages`
|
|
48
|
+
|
|
49
|
+
| Flag | Description |
|
|
50
|
+
|------|-------------|
|
|
51
|
+
| `--conv <name>` | Conversation filter – searches by partial name (queries all matches), `=Exact name` for a single conversation, or UUID |
|
|
52
|
+
| `--unread` | Only unread incoming messages |
|
|
53
|
+
| `--unanswered [hours]` | Unanswered, older than N hours (default 24) |
|
|
54
|
+
| `--from <date>` | From date (ISO e.g. 2025-01-15, or relative: 5h, 3d, 10m) |
|
|
55
|
+
| `--to <date>` | To date (ISO or relative) |
|
|
56
|
+
| `--incoming` | Only incoming messages |
|
|
57
|
+
| `--outgoing` | Only outgoing messages |
|
|
58
|
+
|
|
59
|
+
### Global Flags
|
|
60
|
+
|
|
61
|
+
- `-i, --interactive` – launch interactive mode (Inquirer)
|
|
62
|
+
- `--json` – output as JSON (useful for scripts and jq)
|
|
63
|
+
- `-n, --limit <number>` – limit number of results
|
|
64
|
+
- `-V, --version` – show version
|
|
65
|
+
|
|
66
|
+
## Examples
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# Unread messages
|
|
70
|
+
signal-db-cli messages --unread
|
|
71
|
+
|
|
72
|
+
# Last 20 messages
|
|
73
|
+
signal-db-cli messages
|
|
74
|
+
|
|
75
|
+
# Messages from a conversation (by partial name – queries all matches)
|
|
76
|
+
signal-db-cli messages --conv "Tomas"
|
|
77
|
+
signal-db-cli messages --conv SMARTA -n 10
|
|
78
|
+
|
|
79
|
+
# Exact conversation name match (= prefix)
|
|
80
|
+
signal-db-cli messages --conv "=USY HoT"
|
|
81
|
+
|
|
82
|
+
# Conversation by UUID
|
|
83
|
+
signal-db-cli messages --conv "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
|
|
84
|
+
|
|
85
|
+
# Full-text search in messages
|
|
86
|
+
signal-db-cli messages "deadline"
|
|
87
|
+
|
|
88
|
+
# Date range
|
|
89
|
+
signal-db-cli messages "deadline" --from 2025-01-01 --to 2025-02-17
|
|
90
|
+
|
|
91
|
+
# Relative date (last 5 hours)
|
|
92
|
+
signal-db-cli messages --from 5h
|
|
93
|
+
|
|
94
|
+
# Only incoming messages
|
|
95
|
+
signal-db-cli messages --incoming
|
|
96
|
+
|
|
97
|
+
# Unanswered (older than 24h)
|
|
98
|
+
signal-db-cli messages --unanswered
|
|
99
|
+
|
|
100
|
+
# Unanswered (older than 48h)
|
|
101
|
+
signal-db-cli messages --unanswered 48
|
|
102
|
+
|
|
103
|
+
# Search conversations
|
|
104
|
+
signal-db-cli convs "CI/CD"
|
|
105
|
+
|
|
106
|
+
# List group conversations
|
|
107
|
+
signal-db-cli convs --type group
|
|
108
|
+
|
|
109
|
+
# Phone number by name
|
|
110
|
+
signal-db-cli phone "Smith"
|
|
111
|
+
|
|
112
|
+
# Call history
|
|
113
|
+
signal-db-cli calls 30
|
|
114
|
+
|
|
115
|
+
# Interactive mode
|
|
116
|
+
signal-db-cli interactive
|
|
117
|
+
|
|
118
|
+
# Extract decryption key and save to ~/.signal-db-cli/.env
|
|
119
|
+
signal-db-cli decrypt
|
|
120
|
+
|
|
121
|
+
# JSON output for further processing
|
|
122
|
+
signal-db-cli messages --unread --json | jq '.messages[0].body'
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Search Syntax
|
|
126
|
+
|
|
127
|
+
Full-text search in the `messages [query]` command:
|
|
128
|
+
|
|
129
|
+
- **Space** = OR – message contains at least one term (`hello deadline` = hello OR deadline)
|
|
130
|
+
- **Comma** = AND – message must contain all terms (`hello, deadline` = hello AND deadline)
|
|
131
|
+
- **Prefix matching** – automatic; `hel` finds "hello", "helpful", `dead` finds "deadline"
|
|
132
|
+
- Combined: `hello deadline, meeting` = (hello OR deadline) AND meeting
|
|
133
|
+
|
|
134
|
+
## Conversation Filter (`--conv`)
|
|
135
|
+
|
|
136
|
+
The `--conv` flag supports three modes:
|
|
137
|
+
|
|
138
|
+
1. **Partial name search** (`--conv "Tomas"`) — finds all conversations whose name contains the given text, and queries messages across all matches. If there's only one match, the conversation name is displayed.
|
|
139
|
+
2. **Exact match** (`--conv "=USY HoT"`) — the `=` prefix forces exact name matching. Returns messages from a single conversation only.
|
|
140
|
+
3. **UUID** (`--conv "a1b2c3d4-e5f6-7890-abcd-ef1234567890"`) — direct conversation ID.
|
|
141
|
+
|
|
142
|
+
If the search finds no conversation, the command exits with an error.
|
|
143
|
+
|
|
144
|
+
## Interactive Mode
|
|
145
|
+
|
|
146
|
+
Run `signal-db-cli interactive` or `signal-db-cli i` for the main menu. Choose an action:
|
|
147
|
+
|
|
148
|
+
- **Unread messages** – shows unread incoming messages
|
|
149
|
+
- **Recent messages** – shows the last 20 messages
|
|
150
|
+
- **Conversations** – select a conversation by typing (list is filtered), then shows messages
|
|
151
|
+
- **Search messages** – enter text, select from results, and view detail
|
|
152
|
+
- **Unanswered** – shows unanswered messages
|
|
153
|
+
- **Call history** – shows calls
|
|
154
|
+
|
|
155
|
+
With the `messages` command, you can use `-i` for interactive conversation selection or full-text search.
|
|
156
|
+
|
|
157
|
+
## MCP Server
|
|
158
|
+
|
|
159
|
+
The tool includes an MCP server (`signal-db-mcp`) for integration with AI tools. Run it as:
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
signal-db-mcp
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Available tools: `get_messages`, `get_conversations`, `get_calls`, `get_message_by_id`, `get_phone`.
|
|
166
|
+
|
|
167
|
+
## Updates
|
|
168
|
+
|
|
169
|
+
The tool periodically checks the npm registry. If a new version is available, a message is shown at startup:
|
|
170
|
+
|
|
171
|
+
```
|
|
172
|
+
Update available 0.1.0 → 0.2.0
|
|
173
|
+
Run: npm install -g signal-db-cli
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
To disable the check, set `NO_UPDATE_NOTIFIER=1`.
|
|
177
|
+
|
|
178
|
+
## Troubleshooting
|
|
179
|
+
|
|
180
|
+
### Missing SIGNAL_DECRYPTION_KEY
|
|
181
|
+
Run `signal-db-cli decrypt` to extract and save the key automatically. Alternatively, set the `SIGNAL_DECRYPTION_KEY` environment variable in `.env` or `~/.signal-db-cli/.env` with a valid hex key.
|
|
182
|
+
|
|
183
|
+
### Database is locked
|
|
184
|
+
Close Signal Desktop before using the tool. Signal holds an exclusive lock on the database.
|
|
185
|
+
|
|
186
|
+
### SQLITE_BUSY
|
|
187
|
+
The database is in use by another process. Close Signal Desktop and try again.
|