compass-agent 2.0.5 → 2.0.7

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.
@@ -3,6 +3,8 @@ name: Publish to npm
3
3
  on:
4
4
  release:
5
5
  types: [published]
6
+ push:
7
+ branches: [main]
6
8
 
7
9
  jobs:
8
10
  publish:
@@ -15,6 +17,7 @@ jobs:
15
17
  - uses: oven-sh/setup-bun@v2
16
18
 
17
19
  - name: Set version from release tag
20
+ if: github.event_name == 'release'
18
21
  run: npm version "${GITHUB_REF_NAME#v}" --no-git-tag-version --allow-same-version
19
22
 
20
23
  - run: bun install --frozen-lockfile
@@ -0,0 +1,19 @@
1
+ name: Tests
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+
15
+ - uses: oven-sh/setup-bun@v2
16
+
17
+ - run: bun install --frozen-lockfile
18
+
19
+ - run: bun test
package/README.md CHANGED
@@ -1,37 +1,46 @@
1
- # Compass
1
+ # 🧭 Compass
2
2
 
3
- A Slack app that connects Claude Code to your workspace. Every thread becomes a coding session — set a working directory, ask questions, and get answers with full access to your local filesystem. Claude runs on your machine, streams responses in real-time, and remembers context across messages.
3
+ [![Tests](https://github.com/raja-jamwal/compass/actions/workflows/test.yml/badge.svg)](https://github.com/raja-jamwal/compass/actions/workflows/test.yml)
4
+ [![Publish to npm](https://github.com/raja-jamwal/compass/actions/workflows/publish.yml/badge.svg)](https://github.com/raja-jamwal/compass/actions/workflows/publish.yml)
5
+ [![npm version](https://img.shields.io/npm/v/compass-agent)](https://www.npmjs.com/package/compass-agent)
6
+
7
+ Bring workforce of Claude Codes to your Slack workspace. Every thread becomes an isolated coding session — with its own working directory, git worktree, and full access to your local filesystem. Claude runs on your machine, streams responses in real-time, and your whole team can use it simultaneously without conflicts.
4
8
 
5
9
  ![Agentic task visualization with sub-agents](assets/sub-agent.png)
6
10
 
7
- ## How it works
11
+ ## Quick start
12
+
13
+ ```bash
14
+ bunx compass-agent
15
+ ```
8
16
 
9
- The bot runs locally on your machine using Slack's Socket Mode (no public URL needed). When you send a message in the App Home, it spawns a `claude` CLI process, streams the output back to Slack using the native streaming API, and maintains session continuity across messages in the same thread.
17
+ That's it. The bot connects via Socket Mode no servers, no ngrok, no cloud deployment. See [Setup](#setup) for first-time configuration.
18
+
19
+ ## How it works
10
20
 
11
21
  ```
12
22
  You (Slack thread) → Bot (Socket Mode) → Claude CLI (local) → Your filesystem
13
23
  ```
14
24
 
15
- Each thread is an isolated session with its own working directory, Claude session ID, and optionally its own git worktree.
25
+ The bot runs locally using Slack's Socket Mode. When you message it, it spawns a `claude` CLI process, streams output back to Slack in real-time, and maintains session continuity across messages. Each thread is an isolated session with its own working directory, session ID, and git worktree.
16
26
 
17
27
  ## Features
18
28
 
19
29
  ### Per-thread sessions
20
30
 
21
- Every App Home thread is an independent Claude session. The bot tracks session IDs so subsequent messages in the same thread resume the same Claude conversation with full context.
31
+ Every thread is an independent Claude session. Subsequent messages in the same thread resume the conversation with full context.
22
32
 
23
- Session lifecycle:
24
- 1. First message new Claude session created
25
- 2. Claude's `system.init` event stores the real session ID in SQLite
26
- 3. Subsequent messages use `--resume <session_id>` to continue the conversation
33
+ 1. First message creates a new Claude session
34
+ 2. `system.init` stores the session ID in SQLite
35
+ 3. Follow-up messages use `--resume <session_id>` to continue
27
36
 
28
37
  ### `$cwd` — Working directory
29
38
 
30
- Each thread requires a working directory before Claude can run. This is where Claude will read/write files.
39
+ Set the working directory for Claude to read/write files.
31
40
 
32
41
  | Command | Description |
33
42
  |---------|-------------|
34
- | `$cwd` | Opens an interactive picker with recent directories and an "Add new" button |
43
+ | `$cwd` | Opens an interactive picker with recent directories |
35
44
  | `$cwd /path/to/project` | Sets the directory directly |
36
45
 
37
46
  The picker remembers previously used directories. CWD is stored per-thread in SQLite.
@@ -40,23 +49,22 @@ The picker remembers previously used directories. CWD is stored per-thread in SQ
40
49
 
41
50
  ### `$teach` — Team knowledge base
42
51
 
43
- Store team conventions and instructions that get injected into every Claude session via `--append-system-prompt`.
52
+ Store team conventions that get injected into every Claude session across your workspace.
44
53
 
45
54
  | Command | Description |
46
55
  |---------|-------------|
47
- | `$teach` | Shows usage help |
48
- | `$teach <instruction>` | Adds a new teaching (strips surrounding quotes) |
56
+ | `$teach <instruction>` | Adds a new convention |
49
57
  | `$teach list` | Lists all active teachings with IDs |
50
- | `$teach remove <id>` | Soft-deletes a teaching by ID |
58
+ | `$teach remove <id>` | Removes a teaching by ID |
51
59
 
52
- Examples:
53
60
  ```
54
61
  $teach Use TypeScript for all new files
55
62
  $teach Always write tests before implementation
56
63
  $teach Use pnpm instead of npm
57
64
  ```
58
65
 
59
- Teachings are workspace-wide and persist across sessions. They appear in Claude's system prompt as:
66
+ These appear in Claude's system prompt as:
67
+
60
68
  ```
61
69
  Team conventions:
62
70
  - Use TypeScript for all new files
@@ -65,62 +73,30 @@ Team conventions:
65
73
 
66
74
  ### Streaming responses
67
75
 
68
- Responses stream to Slack token-by-token using Slack's native `chatStream` API (`chat.startStream` / `chat.appendStream` / `chat.stopStream`). This gives a smooth typing effect instead of chunked updates.
76
+ Responses stream token-by-token using Slack's native `chatStream` API, with automatic fallback to throttled `chat.update` calls if streaming isn't available.
69
77
 
70
- If streaming fails (e.g., missing permissions or API errors), the bot falls back to throttled `chat.update` calls (every 750ms).
71
-
72
- Claude's tool calls are visualized as an agentic timeline — each tool invocation (file reads, code edits, shell commands) appears as a step that progresses from in-progress to complete.
78
+ Tool calls are visualized as an agentic timeline — each invocation (file reads, edits, shell commands) appears as a step that progresses from in-progress to complete.
73
79
 
74
80
  ![Streaming response with planning and sub-agents](assets/planning-streaming.png)
75
81
 
76
- ### Stop button
77
-
78
- Every response includes a red "Stop" button. Clicking it sends `SIGTERM` to the Claude process. The partial response is preserved with a "_Stopped by user._" suffix.
79
-
80
- During streaming mode, the Stop button lives in a separate carrier message that gets deleted after the stream finalizes.
81
-
82
- ### App Home dashboard
83
-
84
- The Home tab shows a live dashboard when you open it:
85
-
86
- - **Stats bar** — active sessions, team teachings count, active worktrees, running processes
87
- - **Recent sessions** — last 10 sessions with CWD and status indicator (green = active, white = idle)
88
- - **Recent activity** — last 5 usage logs with model, turns, and cost
89
- - **Quick actions** — "View Teachings" opens a modal listing all teachings; "Add Teaching" opens an input modal
90
-
91
82
  ### Git worktree isolation
92
83
 
93
- When the CWD is inside a git repository, the bot automatically creates a git worktree for each thread. This means parallel threads can make code changes without conflicting with each other or your main working tree.
94
-
95
- How it works:
96
- 1. On first message, `detectGitRepo()` checks if CWD is in a git repo
97
- 2. If yes, creates a worktree at `<repo>/trees/slack-<thread_ts>` on a new branch `slack/<thread_ts>`
98
- 3. Copies `.env`, `.env.local`, `.env.development` from the main repo
99
- 4. Claude spawns in the worktree directory instead of the raw CWD
100
- 5. Subsequent messages in the same thread reuse the existing worktree
101
-
102
- Cleanup: An hourly job removes worktrees that have been idle for 24+ hours, skipping any with active processes or uncommitted changes.
103
-
104
- If the CWD is not a git repo, Claude runs directly in the CWD with no worktree.
105
-
106
- ### Usage logging
84
+ When the CWD is inside a git repo, the bot automatically creates a worktree for each thread. Parallel threads can make code changes without conflicting with each other or your main working tree.
107
85
 
108
- Every Claude invocation logs to the `usage_logs` table:
109
- - Session key, user ID, model
110
- - Input/output tokens, total cost (USD)
111
- - Duration, number of turns
86
+ 1. First message detects if CWD is in a git repo
87
+ 2. Creates a worktree at `<repo>/trees/slack-<thread_ts>` on branch `slack/<thread_ts>`
88
+ 3. Copies `.env` files from the main repo
89
+ 4. Claude runs in the worktree instead of the raw CWD
90
+ 5. Subsequent messages reuse the existing worktree
112
91
 
113
- This data powers the "Recent Activity" section on the App Home dashboard.
92
+ An hourly cleanup job removes worktrees idle for 24+ hours, skipping any with active processes or uncommitted changes. If the CWD is not a git repo, Claude runs directly in it.
114
93
 
115
- ### User whitelist
94
+ ### More features
116
95
 
117
- Set `ALLOWED_USERS` in `.env` to restrict who can interact with the bot. Comma-separated Slack user IDs.
118
-
119
- ```
120
- ALLOWED_USERS=U096GJFBZ54,U0XXXXXXXX
121
- ```
122
-
123
- Leave empty or unset to allow all users.
96
+ - **Stop button** Every response includes a red Stop button that sends `SIGTERM` to Claude. Partial responses are preserved.
97
+ - **App Home dashboard** — Live stats (active sessions, teachings, worktrees), recent sessions with status indicators, usage logs with cost tracking, and quick actions for managing teachings.
98
+ - **Usage logging** — Every invocation logs session, user, model, tokens, cost, duration, and turns to SQLite. Powers the dashboard's "Recent Activity" section.
99
+ - **User whitelist** — Set `ALLOWED_USERS` in `.env` to restrict access by Slack user ID.
124
100
 
125
101
  ## Setup
126
102
 
@@ -152,29 +128,25 @@ EOF
152
128
  ### 3. Run
153
129
 
154
130
  ```bash
155
- bunx compass
131
+ bunx compass-agent
156
132
  ```
157
133
 
158
- That's it. The bot connects via Socket Mode — no ngrok or public URL needed.
159
-
160
134
  You can also point to a specific env file:
161
135
 
162
136
  ```bash
163
- bunx compass --env-file /path/to/.env
137
+ bunx compass-agent --env-file /path/to/.env
164
138
  ```
165
139
 
166
- Or pass tokens directly as environment variables:
140
+ Or pass tokens directly:
167
141
 
168
142
  ```bash
169
- SLACK_APP_TOKEN=xapp-... SLACK_BOT_TOKEN=xoxb-... bunx compass
143
+ SLACK_APP_TOKEN=xapp-... SLACK_BOT_TOKEN=xoxb-... bunx compass-agent
170
144
  ```
171
145
 
172
- #### Alternative: clone and run locally
173
-
174
- If you prefer to run from source:
146
+ #### Running from source
175
147
 
176
148
  ```bash
177
- git clone https://github.com/anthropics/compass.git
149
+ git clone https://github.com/raja-jamwal/compass.git
178
150
  cd compass
179
151
  cp .env.example .env # edit with your tokens
180
152
  bun install
@@ -183,8 +155,6 @@ bun start
183
155
 
184
156
  #### Environment loading precedence
185
157
 
186
- When multiple sources provide the same variable, higher priority wins:
187
-
188
158
  1. Real environment variables (highest)
189
159
  2. `--env-file <path>`
190
160
  3. `~/.compass/.env`
@@ -203,77 +173,40 @@ When multiple sources provide the same variable, higher priority wins:
203
173
  ```
204
174
  src/
205
175
  app.ts Entry point — Bolt app, actions, modals, App Home, startup
206
- db.ts SQLite schema (11 tables) and typed prepared statement exports (bun:sqlite)
207
- types.ts Shared TypeScript interfaces (row types, runtime types)
176
+ db.ts SQLite schema and typed prepared statements (bun:sqlite)
177
+ types.ts Shared TypeScript interfaces
208
178
  handlers/
209
- assistant.ts Assistant handlersthreadStarted, userMessage, commands
210
- stream.ts Claude CLI streaming — NDJSON parsing, task chunks, usage logging
179
+ assistant.ts Thread lifecyclesession management, commands, message routing
180
+ stream.ts Claude CLI streaming — NDJSON parsing, tool timeline, usage logging
211
181
  ui/
212
- blocks.ts Block Kit builders — stop button, feedback, disclaimer, prompts, dashboard
182
+ blocks.ts Block Kit builders — dashboard, stop button, feedback, prompts
213
183
  lib/
214
- log.ts Shared logging helpers (ts, log, logErr, toSqliteDatetime)
215
- worktree.ts Git worktree lifecycle operations (create, remove, detect)
184
+ log.ts Structured logging helpers
185
+ worktree.ts Git worktree lifecycle (create, remove, detect, cleanup)
216
186
  mcp/
217
187
  server.ts MCP server — reminders, teachings, channel CWD tools
218
188
  manifest.yml Slack app manifest (scopes, events, features)
219
189
  sessions.db SQLite database (auto-created on first run)
220
190
  ```
221
191
 
222
- ### Database tables
223
-
224
- | Table | Purpose |
225
- |-------|---------|
226
- | `sessions` | Per-thread session tracking (session_id, cwd, user) |
227
- | `cwd_history` | Recently used directories for the picker |
228
- | `team_knowledge` | `$teach` instructions (soft-deletable) |
229
- | `usage_logs` | Token counts, cost, duration per invocation |
230
- | `worktrees` | Active git worktree tracking and cleanup state |
231
- | `feedback` | Thumbs up/down feedback on responses |
232
- | `annotations` | File annotations (future) |
233
- | `shared_sessions` | Session sharing via codes (future) |
234
- | `watched_channels` | Auto-respond channels (future) |
235
- | `snapshots` | Git state snapshots (future) |
236
- | `mcp_configs` | MCP server configurations (future) |
237
-
238
192
  ### Message flow
239
193
 
240
194
  ```
241
- 1. Slack message arrives via Socket Mode
242
- 2. Check: subtype? bot? allowed user?
243
- 3. Check: $cwd or $teach command? → handle and return
244
- 4. Check: active process in this thread? → reject
245
- 5. Session lookup: resume existing or create new (pending → system.init)
246
- 6. CWD gate: require working directory
247
- 7. Worktree setup: detect git, create/reuse worktree
248
- 8. Post "Thinking..." message with Stop button
249
- 9. Create chatStream (or fallback to chat.update)
250
- 10. Inject team teachings via --append-system-prompt
251
- 11. Spawn claude CLI with stream-json output
252
- 12. Parse NDJSON events: system.init, text_delta, result
253
- 13. Stream text to Slack via chatStream.append() or throttled chat.update
254
- 14. On close: finalize stream, log usage, clean up stop button
255
- ```
256
-
257
- ### Logging
258
-
259
- Every action produces timestamped structured logs to stdout/stderr:
260
-
261
- ```
262
- 2026-02-14T14:32:01.123Z [D0XXXXXX] Incoming message event: user=U096GJ... ts=1707900000.123456
263
- 2026-02-14T14:32:01.124Z [D0XXXXXX] $teach command: arg="Use TypeScript" user=U096GJ...
264
- 2026-02-14T14:32:01.200Z [D0XXXXXX] Worktree lookup: thread=1707900000.123456 existingWt=none
265
- 2026-02-14T14:32:01.201Z [D0XXXXXX] Git detection: cwd=/Users/dev/project isGit=true repoRoot=/Users/dev/project
266
- 2026-02-14T14:32:01.300Z [D0XXXXXX] Created worktree: /Users/dev/project/trees/slack-1707900000-123456
267
- 2026-02-14T14:32:01.400Z [D0XXXXXX] Spawning claude: cwd=/Users/dev/project/trees/slack-1707900000-123456
268
- 2026-02-14T14:32:02.100Z [D0XXXXXX] stream: type=system subtype=init session_id=abc-123
269
- 2026-02-14T14:32:02.500Z [D0XXXXXX] Streamer activated: first append
270
- 2026-02-14T14:32:05.000Z [D0XXXXXX] stream: result turns=3 cost=$0.0142
271
- 2026-02-14T14:32:05.100Z [D0XXXXXX] Usage logged: cost=$0.0142 turns=3
272
- 2026-02-14T14:32:05.200Z [D0XXXXXX] Stream finalized, stop button deleted
195
+ Slack message (Socket Mode)
196
+ Auth check (subtype, bot, allowed user)
197
+ Command check ($cwd, $teach)
198
+ Concurrency check (one process per thread)
199
+ Session lookup (resume or create)
200
+ CWD gate
201
+ Worktree setup (detect git, create/reuse)
202
+ Post "Thinking..." with Stop button
203
+ Start chatStream (or fallback to chat.update)
204
+ Spawn claude CLI with team teachings
205
+ Parse NDJSON stream (init, text_delta, tool calls, result)
206
+ Stream to Slack in real-time
207
+ Finalize: log usage, clean up stop button
273
208
  ```
274
209
 
275
- Errors go to stderr via `logErr()`. The format is `TIMESTAMP [CHANNEL_ID] message`.
276
-
277
210
  ## Configuration
278
211
 
279
212
  | Variable | Required | Description |
@@ -282,13 +215,5 @@ Errors go to stderr via `logErr()`. The format is `TIMESTAMP [CHANNEL_ID] messag
282
215
  | `SLACK_BOT_TOKEN` | Yes | Bot user OAuth token (`xoxb-...`) |
283
216
  | `ALLOWED_USERS` | No | Comma-separated Slack user IDs to whitelist |
284
217
  | `CLAUDE_PATH` | No | Path to the `claude` binary (defaults to `claude` in PATH) |
285
- | `CLAUDE_ADDITIONAL_ARGS` | No | Extra CLI args appended to every `claude` invocation (space-separated) |
286
- | `ENV_*` | No | Variables prefixed with `ENV_` are injected into the Claude process (e.g. `ENV_ANTHROPIC_API_KEY=sk-...` sets `ANTHROPIC_API_KEY`) |
287
-
288
- ## Manifest scopes
289
-
290
- **Bot scopes:** `channels:history`, `channels:read`, `chat:write`, `im:history`, `im:read`, `im:write`, `app_mentions:read`, `assistant:write`, `incoming-webhook`, `commands`
291
-
292
- **Bot events:** `message.channels`, `message.im`, `app_mention`, `app_home_opened`, `assistant_thread_started`
293
-
294
- **Features:** App Home (messages + home tabs), Bot User, Assistant View, Slash Commands (`/cwd`)
218
+ | `CLAUDE_ADDITIONAL_ARGS` | No | Extra CLI args appended to every `claude` invocation |
219
+ | `ENV_*` | No | Variables prefixed with `ENV_` are injected into Claude's environment (e.g. `ENV_ANTHROPIC_API_KEY=sk-...` sets `ANTHROPIC_API_KEY`) |
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "compass-agent",
3
- "version": "2.0.5",
3
+ "version": "2.0.7",
4
4
  "type": "module",
5
5
  "description": "Bring Claude Code to your Slack workspace — per-thread AI coding sessions with full local filesystem access",
6
6
  "bin": {
@@ -10,13 +10,7 @@
10
10
  "start": "bun src/app.ts",
11
11
  "test": "bun test"
12
12
  },
13
- "keywords": [
14
- "slack",
15
- "claude",
16
- "ai",
17
- "coding-assistant",
18
- "claude-code"
19
- ],
13
+ "keywords": ["slack", "claude", "ai", "coding-assistant", "claude-code"],
20
14
  "license": "MIT",
21
15
  "dependencies": {
22
16
  "@modelcontextprotocol/sdk": "^1.26.0",