@thesammykins/tether 1.0.1 → 1.2.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/.env.example CHANGED
@@ -12,6 +12,20 @@ AGENT_TYPE=claude
12
12
  # Optional - Working directory for agent sessions
13
13
  CLAUDE_WORKING_DIR=/path/to/your/project
14
14
 
15
+ # Optional - HTTP API server configuration
16
+ TETHER_API_HOST=127.0.0.1
17
+ # Bind address for the HTTP API server (default: 127.0.0.1)
18
+ # Use 0.0.0.0 to allow external connections
19
+
20
+ TETHER_API_PORT=2643
21
+ # Port for the HTTP API server (default: 2643)
22
+
23
+ API_TOKEN=
24
+ # Optional - API authentication token
25
+ # If set, all API requests (except /health) must include:
26
+ # Authorization: Bearer <token>
27
+ # If not set, no authentication is required (backward compatible)
28
+
15
29
  # Optional - Direct Messages (disabled by default)
16
30
  ENABLE_DMS=false
17
31
  # Set to "true" to allow the bot to respond to DMs.
package/README.md CHANGED
@@ -9,269 +9,45 @@ Fork of [cord](https://github.com/alexknowshtml/cord) with multi-agent support a
9
9
 
10
10
  ## Features
11
11
 
12
- - **Multi-agent support** — Claude Code, OpenCode, Codex (switch via `AGENT_TYPE` env var)
13
- - **BRB mode** — Agent asks questions via Discord buttons; `tether ask` blocks until answered
14
- - **Direct messages** — Chat with the bot privately via DMs (opt-in)
12
+ - **Multi-agent support** — Claude Code, OpenCode, Codex (switch via config)
13
+ - **BRB mode** — Agent asks questions via Discord buttons when you're away
14
+ - **Direct messages** — Chat with the bot privately via DMs
15
+ - **Encrypted config** — `tether config` stores tokens with AES-256-GCM encryption
15
16
  - **Access control** — User, role, and channel allowlists
16
17
  - **Rate limiting** — Per-user sliding window
17
18
  - **Session management** — Turn limits, duration limits, pause/resume
18
19
  - **Smart threads** — Auto-naming, channel context for new conversations
19
- - **Acknowledgment** — 👀 reaction on incoming messages
20
20
  - **Resilient** — Exponential backoff on connection failures
21
21
 
22
22
  ## Quick Start
23
23
 
24
- ### Prerequisites
25
-
26
- - [Bun](https://bun.sh) runtime
27
- - [Redis](https://redis.io) (for BullMQ job queue)
28
- - A Discord bot token ([setup guide below](#discord-bot-setup))
29
- - An AI agent CLI installed on PATH (`claude`, `opencode`, or `codex`)
30
-
31
- ### Install
32
-
33
- From the npm registry (requires [Bun](https://bun.sh)):
34
-
35
- ```bash
36
- bun add @thesammykins/tether
37
- ```
38
-
39
- Or clone from source:
40
-
41
- ```bash
42
- git clone https://github.com/thesammykins/tether.git
43
- cd tether
44
- bun install
45
- ```
46
-
47
- ### Configure
48
-
49
- ```bash
50
- cp .env.example .env
51
- # Edit .env with your DISCORD_BOT_TOKEN and settings
52
- ```
53
-
54
- ### Run
55
-
56
- ```bash
57
- bun run start # Start bot + worker via CLI
58
- # or run separately:
59
- bun run bot # Discord gateway
60
- bun run worker # Job processor
61
- ```
62
-
63
- ---
64
-
65
- ## Discord Bot Setup
66
-
67
- Step-by-step guide to creating and configuring your Discord bot.
68
-
69
- ### 1. Create a Discord Application
70
-
71
- 1. Go to the [Discord Developer Portal](https://discord.com/developers/applications)
72
- 2. Click **New Application** and give it a name (e.g. "Tether")
73
- 3. Note the **Application ID** — you'll need it for the invite link
74
-
75
- ### 2. Create the Bot User
76
-
77
- 1. In your application, go to the **Bot** tab in the left sidebar
78
- 2. Click **Add Bot** (if not already created)
79
- 3. Under **Token**, click **Reset Token** and copy it — this is your `DISCORD_BOT_TOKEN`
80
- 4. **Store this token securely** — you won't be able to see it again
81
-
82
- ### 3. Configure Bot Permissions
83
-
84
- Under the **Bot** tab, configure these settings:
85
-
86
- **Privileged Gateway Intents** (toggle ON):
87
-
88
- | Intent | Why |
89
- |--------|-----|
90
- | **Message Content Intent** | Required to read message text (not just metadata) |
91
-
92
- > Without Message Content Intent enabled, the bot will connect but never see message contents.
93
-
94
- **Bot Permissions** — the bot needs these permissions in your server:
95
-
96
- | Permission | Why |
97
- |------------|-----|
98
- | Send Messages | Reply to users |
99
- | Create Public Threads | Create conversation threads |
100
- | Send Messages in Threads | Respond in threads |
101
- | Manage Threads | Rename threads |
102
- | Read Message History | Fetch channel context for new conversations |
103
- | Add Reactions | 👀 acknowledgment emoji |
104
- | Use Slash Commands | `/cord config` command |
105
-
106
- ### 4. Generate the Invite Link
107
-
108
- 1. Go to the **OAuth2** tab → **URL Generator**
109
- 2. Under **Scopes**, select:
110
- - `bot`
111
- - `applications.commands`
112
- 3. Under **Bot Permissions**, select the permissions listed above, or use the permission integer `326417588288` which includes all required permissions
113
- 4. Copy the generated URL and open it in your browser
114
- 5. Select the server you want to add the bot to and click **Authorize**
115
-
116
- ### 5. Enable DMs (Optional)
117
-
118
- If you want users to be able to DM the bot directly:
119
-
120
- 1. In `.env`, set `ENABLE_DMS=true`
121
- 2. In the Discord Developer Portal → **Bot** tab, make sure **Allow DMs** is not disabled
122
-
123
- DM behavior:
124
- - Any message sent to the bot in DMs starts or continues a conversation
125
- - No `@mention` needed — every DM is treated as a prompt
126
- - Sessions persist per-user until manually reset
127
- - Send `!reset` in DMs to start a fresh session
128
- - Only `ALLOWED_USERS` is checked for DMs (roles and channels don't apply)
129
-
130
- ### 6. Start the Bot
131
-
132
24
  ```bash
133
- # Make sure Redis is running
134
- redis-server
135
-
136
- # Start tether
137
- bun run start
138
- ```
139
-
140
- You should see:
141
- ```
142
- [bot] Connecting to Discord gateway (attempt 1)...
143
- [bot] Logged in as YourBot#1234
144
- [worker] Worker started, waiting for jobs...
145
- ```
146
-
147
- ### 7. Test It
148
-
149
- In your Discord server, `@mention` the bot in any channel:
150
-
151
- ```
152
- @Tether what time is it?
153
- ```
154
-
155
- The bot will:
156
- 1. React with 👀
157
- 2. Create a thread with an auto-generated name
158
- 3. Post a "Processing..." status message
159
- 4. Forward the prompt to your AI agent
160
- 5. Post the response in the thread
161
-
162
- ---
163
-
164
- ## Configuration
165
-
166
- | Variable | Default | Description |
167
- |----------|---------|-------------|
168
- | `DISCORD_BOT_TOKEN` | required | Discord bot token |
169
- | `AGENT_TYPE` | `claude` | Agent backend: `claude`, `opencode`, `codex` |
170
- | `ENABLE_DMS` | `false` | Allow bot to respond to direct messages |
171
- | `REDIS_HOST` | `localhost` | Redis host |
172
- | `REDIS_PORT` | `6379` | Redis port |
173
- | `ALLOWED_USERS` | (empty=all) | Comma-separated Discord user IDs |
174
- | `ALLOWED_ROLES` | (empty=all) | Comma-separated role IDs (guild only) |
175
- | `ALLOWED_CHANNELS` | (empty=all) | Comma-separated channel IDs (guild only) |
176
- | `RATE_LIMIT_REQUESTS` | `5` | Max requests per window |
177
- | `RATE_LIMIT_WINDOW_MS` | `60000` | Rate limit window (ms) |
178
- | `MAX_TURNS_PER_SESSION` | `50` | Max turns per thread/DM session |
179
- | `MAX_SESSION_DURATION_MS` | `3600000` | Max session duration (ms) |
180
- | `CLAUDE_WORKING_DIR` | cwd | Default working directory for agents |
181
- | `DB_PATH` | `./data/threads.db` | SQLite database path |
182
- | `CORD_ALLOWED_DIRS` | (empty=any) | Comma-separated allowed working directories |
183
-
184
- ### Finding Discord IDs
185
-
186
- To get user, role, or channel IDs:
187
- 1. Enable **Developer Mode** in Discord: Settings → App Settings → Advanced → Developer Mode
188
- 2. Right-click a user, role, or channel and select **Copy ID**
189
-
190
- ## Agent CLI Requirements
191
-
192
- Whichever agent you choose must be installed and available on PATH:
193
- - **Claude Code**: `claude` CLI — [Install guide](https://docs.anthropic.com/en/docs/claude-code)
194
- - **OpenCode**: `opencode` CLI
195
- - **Codex**: `codex` CLI
196
-
197
- ## Architecture
198
-
199
- Tether uses a queue-based architecture for reliable message processing:
200
-
201
- ```
202
- Discord Bot → BullMQ Queue → Agent Worker
203
- (gateway) (Redis) (spawns CLI)
204
- ```
205
-
206
- ### Key Components
207
-
208
- - **Bot** (`src/bot.ts`) — Discord gateway with middleware pipeline
209
- - **Worker** (`src/worker.ts`) — Job processor using adapter registry
210
- - **Adapters** (`src/adapters/`) — AgentAdapter interface for Claude/OpenCode/Codex
211
- - **Middleware** (`src/middleware/`) — Allowlist, rate-limiter
212
- - **Features** (`src/features/`) — Ack, channel-context, thread-naming, session-limits, pause-resume
213
- - **Queue** (`src/queue.ts`) — BullMQ job queue
214
- - **DB** (`src/db.ts`) — SQLite for thread→session mapping
215
-
216
- ### Message Flow
25
+ # Install
26
+ bun add -g @thesammykins/tether
217
27
 
218
- **Guild channels:**
219
- 1. User `@mentions` bot in Discord channel
220
- 2. Bot checks allowlist rate limiter → pause state
221
- 3. Bot creates thread with auto-generated name
222
- 4. Bot adds job to BullMQ queue
223
- 5. Worker pulls job and spawns agent adapter
224
- 6. Adapter runs CLI (`claude`/`opencode`/`codex`) with prompt
225
- 7. Worker posts response back to Discord thread
28
+ # Configure
29
+ tether config set DISCORD_BOT_TOKEN # paste token (hidden input)
30
+ tether config set AGENT_TYPE claude # or: opencode, codex
226
31
 
227
- **Direct messages:**
228
- 1. User sends message to bot in DMs (no `@mention` needed)
229
- 2. Bot checks user allowlist → rate limiter
230
- 3. Bot creates or resumes session for this user
231
- 4. Bot adds job to BullMQ queue
232
- 5. Worker posts response back to the DM channel
233
-
234
- ### Middleware Pipeline
235
-
236
- Messages pass through middleware in this order:
237
-
238
- 1. **Allowlist** — Block unauthorized users/channels/roles (DMs: user-only check)
239
- 2. **Rate Limiter** — Sliding window per-user rate limit
240
- 3. **Pause/Resume** — Hold messages if thread is paused (guild threads only)
241
-
242
- ### Session Management
243
-
244
- - **Turn limits** — Max messages per thread/DM session (prevents infinite loops)
245
- - **Duration limits** — Max session lifetime
246
- - **Pause/Resume** — Type `pause` to hold messages, `resume` to continue (threads only)
247
- - **DM Reset** — Type `!reset` in DMs to start a new session
248
- - **Auto-completion** — React with ✅ on last message to mark "Done" (threads only)
249
-
250
- ## Working Directory Configuration
251
-
252
- Tether supports per-channel working directories so agents operate in the correct project context.
253
-
254
- **Channel-level configuration** (persists for all conversations in that channel):
255
- ```
256
- /cord config dir ~/Code/myproject
257
- ```
258
-
259
- **Per-message override** (one-time, just for this conversation):
32
+ # Start Redis + Tether
33
+ redis-server &
34
+ tether start
260
35
  ```
261
- @bot [/other/project] what files are here?
262
- ```
263
-
264
- **Fallback chain**: Message override → Channel config → `CLAUDE_WORKING_DIR` env → `process.cwd()`
265
-
266
- ### Security: Directory Allowlist
267
36
 
268
- For multi-user deployments, restrict which directories users can access:
37
+ Then `@mention` the bot in your Discord server.
269
38
 
270
- ```bash
271
- CORD_ALLOWED_DIRS=/home/projects,/var/code
272
- ```
39
+ ## Documentation
273
40
 
274
- If not set, any existing directory is allowed (backward compatible). When set, paths outside the allowlist are rejected.
41
+ | Guide | Description |
42
+ |-------|-------------|
43
+ | **[Installation](docs/installation.md)** | Prerequisites, install methods, quick setup |
44
+ | **[Discord Setup](docs/discord-setup.md)** | Bot creation, permissions, intents, invite link |
45
+ | **[Agent Setup](docs/agents.md)** | Claude Code / OpenCode / Codex install and auth |
46
+ | **[Configuration](docs/configuration.md)** | All config keys, encrypted secrets, resolution chain |
47
+ | **[CLI Reference](docs/cli.md)** | Every `tether` command with examples |
48
+ | **[Architecture](docs/architecture.md)** | System design, message flow, middleware pipeline |
49
+ | **[Troubleshooting](docs/troubleshooting.md)** | Common problems and solutions |
50
+ | **[HTTP API](skills/tether/HTTP-API.md)** | REST API for external scripts and webhooks |
275
51
 
276
52
  ## Testing
277
53
 
@@ -280,45 +56,11 @@ bun test # Run all tests
280
56
  bun test tests/adapters/ # Adapter tests only
281
57
  bun test tests/middleware/ # Middleware tests only
282
58
  bun test tests/features/ # Feature tests only
283
- bun test tests/integration/ # Integration tests only
284
59
  ```
285
60
 
286
- ## CLI Commands
287
-
288
- Quick reference:
289
- - `tether start` — Start bot + worker
290
- - `tether stop` — Stop all processes
291
- - `tether status` — Show running status
292
- - `tether send <channel> "message"` — Send text message
293
- - `tether embed <channel> "text" --title "T"` — Send formatted embed
294
- - `tether file <channel> ./file.txt` — Send file attachment
295
- - `tether buttons <channel> "prompt" --button label="Yes" id="yes"` — Send interactive buttons
296
- - `tether state <channel> <msgId> done` — Update status message
297
- - `tether dm <user-id> "message"` — Send a DM to a user (proactive outreach)
298
- - `tether dm <user-id> --embed "text" --title "T"` — Send an embed DM
299
- - `tether dm <user-id> --file ./report.md` — Send a file via DM
300
- - `tether ask <channel> "question" --button "Yes" --button "No"` — Ask a question via buttons, blocks until answered
301
-
302
- ## HTTP API
303
-
304
- Tether exposes an HTTP API on port 2643 for external scripts and webhooks. See the [API documentation](./skills/tether/HTTP-API.md) for details.
305
-
306
- ## Troubleshooting
307
-
308
- | Problem | Solution |
309
- |---------|----------|
310
- | Bot connects but doesn't respond | Enable **Message Content Intent** in Developer Portal → Bot tab |
311
- | "TokenInvalid" error | Regenerate your bot token in the Developer Portal |
312
- | "DisallowedIntents" error | Enable the required intents in Developer Portal → Bot tab |
313
- | Bot doesn't receive DMs | Set `ENABLE_DMS=true` in `.env` |
314
- | "Rate limit exceeded" | Adjust `RATE_LIMIT_REQUESTS` / `RATE_LIMIT_WINDOW_MS` |
315
- | Agent command not found | Ensure `claude`/`opencode`/`codex` is installed and on PATH |
316
- | Redis connection refused | Start Redis: `redis-server` |
317
- | Bot can't create threads | Check bot has **Create Public Threads** permission in your server |
318
-
319
61
  ## Privacy
320
62
 
321
- Tether stores only thread-to-session mappings and channel configuration (working directories). **No message content, user data, or conversation history is persisted.** Messages pass through the Redis queue transiently and are discarded after processing.
63
+ No message content or user data is stored. Only thread-to-session mappings and channel config persist. Messages pass through Redis transiently and are discarded after processing.
322
64
 
323
65
  ## License
324
66