compass-agent 2.0.7 → 2.0.8

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 ADDED
@@ -0,0 +1,3 @@
1
+ SLACK_APP_TOKEN=xapp-1-...
2
+ SLACK_BOT_TOKEN=xoxb-...
3
+ ALLOWED_USERS=
@@ -3,8 +3,7 @@ name: Publish to npm
3
3
  on:
4
4
  release:
5
5
  types: [published]
6
- push:
7
- branches: [main]
6
+ workflow_dispatch:
8
7
 
9
8
  jobs:
10
9
  publish:
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
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.
8
8
 
9
- ![Agentic task visualization with sub-agents](assets/sub-agent.png)
9
+ ![Agentic task visualization with sub-agents](docs/assets/sub-agent.png)
10
10
 
11
11
  ## Quick start
12
12
 
@@ -45,7 +45,7 @@ Set the working directory for Claude to read/write files.
45
45
 
46
46
  The picker remembers previously used directories. CWD is stored per-thread in SQLite.
47
47
 
48
- ![Working directory set in channel](assets/streaming-feedback.png)
48
+ ![Working directory set in channel](docs/assets/streaming-feedback.png)
49
49
 
50
50
  ### `$teach` — Team knowledge base
51
51
 
@@ -77,7 +77,7 @@ Responses stream token-by-token using Slack's native `chatStream` API, with auto
77
77
 
78
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.
79
79
 
80
- ![Streaming response with planning and sub-agents](assets/planning-streaming.png)
80
+ ![Streaming response with planning and sub-agents](docs/assets/planning-streaming.png)
81
81
 
82
82
  ### Git worktree isolation
83
83
 
@@ -0,0 +1,468 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Compass — Bring Claude Code to Slack</title>
7
+ <meta name="description" content="Bring a workforce of Claude Codes to your Slack workspace. Per-thread AI coding sessions with full local filesystem access.">
8
+ <link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🧭</text></svg>">
9
+ <link rel="preconnect" href="https://fonts.googleapis.com">
10
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
11
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
12
+ <script src="https://cdn.tailwindcss.com"></script>
13
+ <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
14
+ <script>
15
+ tailwind.config = {
16
+ theme: {
17
+ extend: {
18
+ fontFamily: {
19
+ sans: ['Inter', '-apple-system', 'BlinkMacSystemFont', 'sans-serif'],
20
+ mono: ['JetBrains Mono', 'monospace'],
21
+ },
22
+ colors: {
23
+ apple: {
24
+ blue: '#007AFF',
25
+ indigo: '#5856D6',
26
+ purple: '#AF52DE',
27
+ pink: '#FF2D55',
28
+ gray: {
29
+ 50: '#F9FAFB',
30
+ 100: '#F2F2F7',
31
+ 200: '#E5E5EA',
32
+ 300: '#D1D1D6',
33
+ 400: '#AEAEB2',
34
+ 500: '#8E8E93',
35
+ 600: '#636366',
36
+ 700: '#48484A',
37
+ 800: '#2C2C2E',
38
+ 900: '#1C1C1E',
39
+ }
40
+ }
41
+ }
42
+ }
43
+ }
44
+ }
45
+ </script>
46
+ <style>
47
+ * { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
48
+
49
+ .glass-nav {
50
+ background: rgba(255, 255, 255, 0.72);
51
+ backdrop-filter: saturate(180%) blur(20px);
52
+ -webkit-backdrop-filter: saturate(180%) blur(20px);
53
+ }
54
+
55
+ .hero-gradient {
56
+ background: linear-gradient(180deg, #f5f5f7 0%, #ffffff 100%);
57
+ }
58
+
59
+ .text-gradient {
60
+ background: linear-gradient(135deg, #007AFF 0%, #5856D6 50%, #AF52DE 100%);
61
+ -webkit-background-clip: text;
62
+ -webkit-text-fill-color: transparent;
63
+ background-clip: text;
64
+ }
65
+
66
+ .card-glass {
67
+ background: rgba(255, 255, 255, 0.6);
68
+ backdrop-filter: blur(12px);
69
+ -webkit-backdrop-filter: blur(12px);
70
+ }
71
+
72
+ .screenshot-shadow {
73
+ box-shadow:
74
+ 0 2px 4px rgba(0, 0, 0, 0.04),
75
+ 0 8px 16px rgba(0, 0, 0, 0.06),
76
+ 0 24px 48px rgba(0, 0, 0, 0.08);
77
+ }
78
+
79
+ .feature-card-hover {
80
+ transition: transform 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94), box-shadow 0.3s ease;
81
+ }
82
+ .feature-card-hover:hover {
83
+ transform: translateY(-4px);
84
+ box-shadow: 0 12px 40px rgba(0, 0, 0, 0.08);
85
+ }
86
+
87
+ .flow-connector {
88
+ width: 40px;
89
+ height: 2px;
90
+ background: linear-gradient(90deg, #D1D1D6, #AEAEB2);
91
+ }
92
+
93
+ .install-box {
94
+ background: #1C1C1E;
95
+ transition: box-shadow 0.2s ease;
96
+ }
97
+ .install-box:hover {
98
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
99
+ }
100
+
101
+ .step-number {
102
+ background: linear-gradient(135deg, #007AFF, #5856D6);
103
+ }
104
+
105
+ .section-fade {
106
+ opacity: 0;
107
+ transform: translateY(30px);
108
+ transition: opacity 0.6s ease, transform 0.6s ease;
109
+ }
110
+ .section-fade.visible {
111
+ opacity: 1;
112
+ transform: translateY(0);
113
+ }
114
+
115
+ .config-row {
116
+ transition: background 0.15s ease;
117
+ }
118
+ .config-row:hover {
119
+ background: #F9FAFB;
120
+ }
121
+
122
+ @media (max-width: 768px) {
123
+ .flow-connector { display: none; }
124
+ .screenshot-row { flex-direction: column !important; }
125
+ }
126
+ </style>
127
+ </head>
128
+ <body class="font-sans text-apple-gray-900 bg-white antialiased">
129
+
130
+ <!-- Nav -->
131
+ <nav class="glass-nav fixed top-3 left-1/2 -translate-x-1/2 z-50 border border-apple-gray-200/60 rounded-2xl max-w-4xl w-[calc(100%-2rem)]">
132
+ <div class="px-6 h-12 flex items-center justify-between">
133
+ <a href="#" class="text-base font-semibold tracking-tight flex items-center gap-2 text-apple-gray-900 no-underline">
134
+ 🧭 Compass
135
+ </a>
136
+ <div class="flex items-center gap-6">
137
+ <a href="#features" class="hidden sm:block text-sm text-apple-gray-600 hover:text-apple-gray-900 no-underline transition-colors">Features</a>
138
+ <a href="#screenshots" class="hidden sm:block text-sm text-apple-gray-600 hover:text-apple-gray-900 no-underline transition-colors">Screenshots</a>
139
+ <a href="#setup" class="hidden sm:block text-sm text-apple-gray-600 hover:text-apple-gray-900 no-underline transition-colors">Setup</a>
140
+ <a href="https://www.npmjs.com/package/compass-agent" class="hidden sm:block text-sm text-apple-gray-600 hover:text-apple-gray-900 no-underline transition-colors">npm</a>
141
+ <a href="https://github.com/raja-jamwal/compass" class="inline-flex items-center gap-1.5 text-sm font-medium text-white bg-apple-gray-900 hover:bg-apple-gray-800 px-4 py-1.5 rounded-full no-underline transition-colors">
142
+ <svg class="w-4 h-4" fill="currentColor" viewBox="0 0 24 24"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg>
143
+ GitHub
144
+ </a>
145
+ </div>
146
+ </div>
147
+ </nav>
148
+
149
+ <!-- Hero -->
150
+ <section class="hero-gradient pt-32 pb-20 sm:pt-40 sm:pb-28">
151
+ <div class="max-w-4xl mx-auto px-6 text-center">
152
+ <div class="flex gap-2 justify-center mb-8 flex-wrap">
153
+ <a href="https://github.com/raja-jamwal/compass/actions/workflows/test.yml"><img src="https://github.com/raja-jamwal/compass/actions/workflows/test.yml/badge.svg" alt="Tests"></a>
154
+ <a href="https://github.com/raja-jamwal/compass/actions/workflows/publish.yml"><img src="https://github.com/raja-jamwal/compass/actions/workflows/publish.yml/badge.svg" alt="Publish"></a>
155
+ <a href="https://www.npmjs.com/package/compass-agent"><img src="https://img.shields.io/npm/v/compass-agent" alt="npm version"></a>
156
+ </div>
157
+
158
+ <h1 class="text-5xl sm:text-7xl font-extrabold tracking-tight leading-[1.05] mb-6">
159
+ Bring your workforce of<br>
160
+ <span class="text-gradient">Claude Code to Slack</span>
161
+ </h1>
162
+
163
+ <p class="text-lg sm:text-xl text-apple-gray-500 max-w-2xl mx-auto mb-10 leading-relaxed font-light">
164
+ Every thread becomes an isolated coding session — with its own working directory, git worktree, and full local filesystem access. Your whole team, working in parallel, zero conflicts.
165
+ </p>
166
+
167
+ <div class="flex flex-col sm:flex-row gap-3 justify-center items-center mb-16">
168
+ <div id="install-cmd" class="install-box rounded-xl px-5 py-3 flex items-center gap-3 cursor-pointer select-none">
169
+ <span class="text-apple-gray-500 font-mono text-sm select-none">$</span>
170
+ <span class="text-green-400 font-mono text-sm sm:text-base">bunx compass-agent</span>
171
+ <span id="copy-icon" class="text-apple-gray-500 text-xs ml-2 transition-all">
172
+ <svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg>
173
+ </span>
174
+ </div>
175
+ <a href="https://github.com/raja-jamwal/compass" class="inline-flex items-center gap-2 bg-apple-blue hover:bg-blue-600 text-white font-semibold text-sm px-7 py-3 rounded-full no-underline transition-colors shadow-lg shadow-blue-500/20">
176
+ View on GitHub
177
+ <svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2.5" viewBox="0 0 24 24"><path d="M5 12h14m-7-7l7 7-7 7"/></svg>
178
+ </a>
179
+ <a href="https://www.youtube.com/watch?v=EH_9WAe-PZA" class="inline-flex items-center gap-2 bg-red-600 hover:bg-red-700 text-white font-semibold text-sm px-7 py-3 rounded-full no-underline transition-colors shadow-lg shadow-red-500/20">
180
+ <svg class="w-4 h-4" fill="currentColor" viewBox="0 0 24 24"><path d="M23.498 6.186a3.016 3.016 0 00-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 00.502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 002.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 002.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"/></svg>
181
+ Watch Demo
182
+ </a>
183
+ </div>
184
+
185
+ <div class="relative max-w-4xl mx-auto">
186
+ <div class="absolute -inset-4 bg-gradient-to-b from-apple-blue/5 to-apple-purple/5 rounded-3xl blur-2xl"></div>
187
+ <div class="relative rounded-2xl border border-apple-gray-200 screenshot-shadow overflow-hidden" style="aspect-ratio: 16/9;">
188
+ <iframe class="w-full h-full" src="https://www.youtube.com/embed/EH_9WAe-PZA" title="Compass Demo" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
189
+ </div>
190
+ </div>
191
+ </div>
192
+ </section>
193
+
194
+ <!-- How it works -->
195
+ <section id="how-it-works" class="py-24 bg-white section-fade">
196
+ <div class="max-w-5xl mx-auto px-6">
197
+ <div class="text-center mb-16">
198
+ <p class="text-sm font-semibold text-apple-blue uppercase tracking-wider mb-3">How it works</p>
199
+ <h2 class="text-3xl sm:text-4xl font-bold tracking-tight mb-4">Local-first, zero infrastructure</h2>
200
+ <p class="text-lg text-apple-gray-500 max-w-xl mx-auto font-light">Runs on your machine using Slack's Socket Mode. No servers to deploy, no URLs to expose.</p>
201
+ </div>
202
+
203
+ <div class="flex items-center justify-center flex-wrap gap-4">
204
+ <div class="card-glass border border-apple-gray-200 rounded-2xl p-6 text-center min-w-[150px] feature-card-hover">
205
+ <div class="text-3xl mb-2">💬</div>
206
+ <div class="font-semibold text-sm">Slack Thread</div>
207
+ <div class="text-xs text-apple-gray-500 mt-1">You send a message</div>
208
+ </div>
209
+ <div class="flow-connector hidden sm:block"></div>
210
+ <div class="card-glass border border-apple-gray-200 rounded-2xl p-6 text-center min-w-[150px] feature-card-hover">
211
+ <div class="text-3xl mb-2">🔌</div>
212
+ <div class="font-semibold text-sm">Socket Mode</div>
213
+ <div class="text-xs text-apple-gray-500 mt-1">Bot receives locally</div>
214
+ </div>
215
+ <div class="flow-connector hidden sm:block"></div>
216
+ <div class="card-glass border border-apple-gray-200 rounded-2xl p-6 text-center min-w-[150px] feature-card-hover">
217
+ <div class="text-3xl mb-2">🤖</div>
218
+ <div class="font-semibold text-sm">Claude CLI</div>
219
+ <div class="text-xs text-apple-gray-500 mt-1">Spawns a session</div>
220
+ </div>
221
+ <div class="flow-connector hidden sm:block"></div>
222
+ <div class="card-glass border border-apple-gray-200 rounded-2xl p-6 text-center min-w-[150px] feature-card-hover">
223
+ <div class="text-3xl mb-2">📂</div>
224
+ <div class="font-semibold text-sm">Filesystem</div>
225
+ <div class="text-xs text-apple-gray-500 mt-1">Reads & writes files</div>
226
+ </div>
227
+ </div>
228
+ </div>
229
+ </section>
230
+
231
+ <!-- Features -->
232
+ <section id="features" class="py-24 bg-apple-gray-50 section-fade">
233
+ <div class="max-w-5xl mx-auto px-6">
234
+ <div class="text-center mb-16">
235
+ <p class="text-sm font-semibold text-apple-indigo uppercase tracking-wider mb-3">Features</p>
236
+ <h2 class="text-3xl sm:text-4xl font-bold tracking-tight mb-4">Everything your team needs</h2>
237
+ <p class="text-lg text-apple-gray-500 max-w-xl mx-auto font-light">Built for real development workflows, not demos.</p>
238
+ </div>
239
+
240
+ <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-5">
241
+ <div class="bg-white border border-apple-gray-200 rounded-2xl p-7 feature-card-hover">
242
+ <div class="w-10 h-10 rounded-xl bg-blue-50 flex items-center justify-center text-xl mb-4">🧵</div>
243
+ <h3 class="text-base font-semibold mb-2">Per-thread sessions</h3>
244
+ <p class="text-sm text-apple-gray-500 leading-relaxed">Every thread is an independent Claude session. Follow-up messages resume with full context using <code class="text-xs bg-apple-gray-100 text-apple-indigo px-1.5 py-0.5 rounded font-mono">--resume</code>.</p>
245
+ </div>
246
+
247
+ <div class="bg-white border border-apple-gray-200 rounded-2xl p-7 feature-card-hover">
248
+ <div class="w-10 h-10 rounded-xl bg-indigo-50 flex items-center justify-center text-xl mb-4">📁</div>
249
+ <h3 class="text-base font-semibold mb-2"><code class="text-sm bg-apple-gray-100 text-apple-indigo px-1.5 py-0.5 rounded font-mono">$cwd</code> Working directory</h3>
250
+ <p class="text-sm text-apple-gray-500 leading-relaxed">Set the directory Claude works in. Interactive picker remembers recent directories, or set directly with a path.</p>
251
+ </div>
252
+
253
+ <div class="bg-white border border-apple-gray-200 rounded-2xl p-7 feature-card-hover">
254
+ <div class="w-10 h-10 rounded-xl bg-purple-50 flex items-center justify-center text-xl mb-4">🎓</div>
255
+ <h3 class="text-base font-semibold mb-2"><code class="text-sm bg-apple-gray-100 text-apple-indigo px-1.5 py-0.5 rounded font-mono">$teach</code> Team knowledge</h3>
256
+ <p class="text-sm text-apple-gray-500 leading-relaxed">Store conventions injected into every session. "Use TypeScript", "Always write tests" — shared across your workspace.</p>
257
+ </div>
258
+
259
+ <div class="bg-white border border-apple-gray-200 rounded-2xl p-7 feature-card-hover">
260
+ <div class="w-10 h-10 rounded-xl bg-orange-50 flex items-center justify-center text-xl mb-4">⚡</div>
261
+ <h3 class="text-base font-semibold mb-2">Streaming responses</h3>
262
+ <p class="text-sm text-apple-gray-500 leading-relaxed">Token-by-token streaming via Slack's native <code class="text-xs bg-apple-gray-100 text-apple-indigo px-1.5 py-0.5 rounded font-mono">chatStream</code> API. Tool calls render as a live agentic timeline.</p>
263
+ </div>
264
+
265
+ <div class="bg-white border border-apple-gray-200 rounded-2xl p-7 feature-card-hover">
266
+ <div class="w-10 h-10 rounded-xl bg-green-50 flex items-center justify-center text-xl mb-4">🌳</div>
267
+ <h3 class="text-base font-semibold mb-2">Git worktree isolation</h3>
268
+ <p class="text-sm text-apple-gray-500 leading-relaxed">Each thread gets its own worktree and branch. Parallel sessions make code changes without conflicts. Auto-cleanup after 24h.</p>
269
+ </div>
270
+
271
+ <div class="bg-white border border-apple-gray-200 rounded-2xl p-7 feature-card-hover">
272
+ <div class="w-10 h-10 rounded-xl bg-pink-50 flex items-center justify-center text-xl mb-4">📊</div>
273
+ <h3 class="text-base font-semibold mb-2">Dashboard & usage tracking</h3>
274
+ <p class="text-sm text-apple-gray-500 leading-relaxed">App Home shows live stats, recent sessions, cost tracking per invocation. Stop button on every response.</p>
275
+ </div>
276
+ </div>
277
+ </div>
278
+ </section>
279
+
280
+ <!-- Screenshots -->
281
+ <section id="screenshots" class="py-24 bg-white section-fade">
282
+ <div class="max-w-5xl mx-auto px-6">
283
+ <div class="text-center mb-16">
284
+ <p class="text-sm font-semibold text-apple-purple uppercase tracking-wider mb-3">In action</p>
285
+ <h2 class="text-3xl sm:text-4xl font-bold tracking-tight mb-4">See it working</h2>
286
+ </div>
287
+
288
+ <div class="space-y-24">
289
+ <div class="flex flex-col md:flex-row items-center gap-12 screenshot-row">
290
+ <div class="flex-1">
291
+ <div class="relative">
292
+ <div class="absolute -inset-3 bg-gradient-to-br from-blue-100/40 to-indigo-100/40 rounded-3xl blur-xl"></div>
293
+ <img src="assets/streaming-feedback.png" alt="Working directory set in Slack" class="relative w-full rounded-2xl border border-apple-gray-200 screenshot-shadow">
294
+ </div>
295
+ </div>
296
+ <div class="flex-1 max-w-md">
297
+ <div class="w-10 h-10 rounded-xl bg-blue-50 flex items-center justify-center text-xl mb-4">📁</div>
298
+ <h3 class="text-2xl font-bold mb-3 tracking-tight">Set a directory, start coding</h3>
299
+ <p class="text-apple-gray-500 leading-relaxed">Point Claude at any project on your machine. The working directory is stored per-thread, so each conversation is scoped to its own codebase.</p>
300
+ </div>
301
+ </div>
302
+
303
+ <div class="flex flex-col md:flex-row-reverse items-center gap-12 screenshot-row">
304
+ <div class="flex-1">
305
+ <div class="relative">
306
+ <div class="absolute -inset-3 bg-gradient-to-br from-purple-100/40 to-pink-100/40 rounded-3xl blur-xl"></div>
307
+ <img src="assets/planning-streaming.png" alt="Streaming with planning and sub-agents" class="relative w-full rounded-2xl border border-apple-gray-200 screenshot-shadow">
308
+ </div>
309
+ </div>
310
+ <div class="flex-1 max-w-md">
311
+ <div class="w-10 h-10 rounded-xl bg-purple-50 flex items-center justify-center text-xl mb-4">⚡</div>
312
+ <h3 class="text-2xl font-bold mb-3 tracking-tight">Agentic tool timeline</h3>
313
+ <p class="text-apple-gray-500 leading-relaxed">Watch Claude think, plan, and execute in real-time. Every tool call — file reads, edits, shell commands, sub-agents — renders as a live progress step.</p>
314
+ </div>
315
+ </div>
316
+ </div>
317
+ </div>
318
+ </section>
319
+
320
+ <!-- Setup -->
321
+ <section id="setup" class="py-24 bg-apple-gray-50 section-fade">
322
+ <div class="max-w-3xl mx-auto px-6">
323
+ <div class="text-center mb-16">
324
+ <p class="text-sm font-semibold text-apple-blue uppercase tracking-wider mb-3">Get started</p>
325
+ <h2 class="text-3xl sm:text-4xl font-bold tracking-tight mb-4">Up and running in 5 minutes</h2>
326
+ <p class="text-lg text-apple-gray-500 max-w-xl mx-auto font-light">Prerequisites: <a href="https://bun.sh" class="text-apple-blue hover:underline">Bun</a>, <a href="https://docs.anthropic.com/en/docs/claude-code" class="text-apple-blue hover:underline">Claude CLI</a>, and a Slack workspace.</p>
327
+ </div>
328
+
329
+ <div class="space-y-4">
330
+ <div class="bg-white border border-apple-gray-200 rounded-2xl p-7 pl-20 relative feature-card-hover">
331
+ <div class="step-number absolute left-6 top-7 w-9 h-9 rounded-xl text-white flex items-center justify-center font-bold text-sm">1</div>
332
+ <h3 class="text-base font-semibold mb-2">Create the Slack app</h3>
333
+ <p class="text-sm text-apple-gray-500 leading-relaxed">Go to <a href="https://api.slack.com/apps" class="text-apple-blue hover:underline">api.slack.com/apps</a>, create from manifest using the included <code class="text-xs bg-apple-gray-100 text-apple-indigo px-1.5 py-0.5 rounded font-mono">manifest.yml</code>, and install to your workspace.</p>
334
+ </div>
335
+
336
+ <div class="bg-white border border-apple-gray-200 rounded-2xl p-7 pl-20 relative feature-card-hover">
337
+ <div class="step-number absolute left-6 top-7 w-9 h-9 rounded-xl text-white flex items-center justify-center font-bold text-sm">2</div>
338
+ <h3 class="text-base font-semibold mb-2">Configure environment</h3>
339
+ <p class="text-sm text-apple-gray-500 leading-relaxed mb-3">Store your tokens in <code class="text-xs bg-apple-gray-100 text-apple-indigo px-1.5 py-0.5 rounded font-mono">~/.compass/.env</code></p>
340
+ <div class="bg-apple-gray-900 rounded-xl p-4 overflow-x-auto">
341
+ <pre class="text-sm font-mono text-green-400 leading-relaxed">mkdir -p ~/.compass
342
+ cat > ~/.compass/.env &lt;&lt; 'EOF'
343
+ SLACK_APP_TOKEN=xapp-1-...
344
+ SLACK_BOT_TOKEN=xoxb-...
345
+ EOF</pre>
346
+ </div>
347
+ </div>
348
+
349
+ <div class="bg-white border border-apple-gray-200 rounded-2xl p-7 pl-20 relative feature-card-hover">
350
+ <div class="step-number absolute left-6 top-7 w-9 h-9 rounded-xl text-white flex items-center justify-center font-bold text-sm">3</div>
351
+ <h3 class="text-base font-semibold mb-2">Run</h3>
352
+ <p class="text-sm text-apple-gray-500 leading-relaxed mb-3">One command. No servers, no ngrok.</p>
353
+ <div class="bg-apple-gray-900 rounded-xl p-4">
354
+ <pre class="text-sm font-mono text-green-400">bunx compass-agent</pre>
355
+ </div>
356
+ </div>
357
+
358
+ <div class="bg-white border border-apple-gray-200 rounded-2xl p-7 pl-20 relative feature-card-hover">
359
+ <div class="step-number absolute left-6 top-7 w-9 h-9 rounded-xl text-white flex items-center justify-center font-bold text-sm">4</div>
360
+ <h3 class="text-base font-semibold mb-2">Verify</h3>
361
+ <p class="text-sm text-apple-gray-500 leading-relaxed">Open the app in Slack, go to the Home tab, start a thread, set <code class="text-xs bg-apple-gray-100 text-apple-indigo px-1.5 py-0.5 rounded font-mono">$cwd</code>, and ask a question.</p>
362
+ </div>
363
+ </div>
364
+ </div>
365
+ </section>
366
+
367
+ <!-- Configuration -->
368
+ <section id="config" class="py-24 bg-white section-fade">
369
+ <div class="max-w-3xl mx-auto px-6">
370
+ <div class="text-center mb-16">
371
+ <p class="text-sm font-semibold text-apple-blue uppercase tracking-wider mb-3">Configuration</p>
372
+ <h2 class="text-3xl sm:text-4xl font-bold tracking-tight mb-4">Environment variables</h2>
373
+ </div>
374
+
375
+ <div class="bg-white border border-apple-gray-200 rounded-2xl overflow-hidden">
376
+ <table class="w-full text-sm">
377
+ <thead>
378
+ <tr class="border-b border-apple-gray-200 bg-apple-gray-50">
379
+ <th class="text-left px-6 py-3 text-xs font-semibold text-apple-gray-500 uppercase tracking-wider">Variable</th>
380
+ <th class="text-left px-4 py-3 text-xs font-semibold text-apple-gray-500 uppercase tracking-wider w-20"></th>
381
+ <th class="text-left px-6 py-3 text-xs font-semibold text-apple-gray-500 uppercase tracking-wider">Description</th>
382
+ </tr>
383
+ </thead>
384
+ <tbody class="divide-y divide-apple-gray-100">
385
+ <tr class="config-row">
386
+ <td class="px-6 py-4"><code class="text-xs bg-apple-gray-100 text-apple-indigo px-1.5 py-0.5 rounded font-mono">SLACK_APP_TOKEN</code></td>
387
+ <td class="px-4 py-4"><span class="text-xs font-semibold text-orange-500">Required</span></td>
388
+ <td class="px-6 py-4 text-apple-gray-500">App-level token for Socket Mode</td>
389
+ </tr>
390
+ <tr class="config-row">
391
+ <td class="px-6 py-4"><code class="text-xs bg-apple-gray-100 text-apple-indigo px-1.5 py-0.5 rounded font-mono">SLACK_BOT_TOKEN</code></td>
392
+ <td class="px-4 py-4"><span class="text-xs font-semibold text-orange-500">Required</span></td>
393
+ <td class="px-6 py-4 text-apple-gray-500">Bot user OAuth token</td>
394
+ </tr>
395
+ <tr class="config-row">
396
+ <td class="px-6 py-4"><code class="text-xs bg-apple-gray-100 text-apple-indigo px-1.5 py-0.5 rounded font-mono">ALLOWED_USERS</code></td>
397
+ <td class="px-4 py-4"><span class="text-xs text-apple-gray-400">Optional</span></td>
398
+ <td class="px-6 py-4 text-apple-gray-500">Comma-separated Slack user IDs to whitelist</td>
399
+ </tr>
400
+ <tr class="config-row">
401
+ <td class="px-6 py-4"><code class="text-xs bg-apple-gray-100 text-apple-indigo px-1.5 py-0.5 rounded font-mono">CLAUDE_PATH</code></td>
402
+ <td class="px-4 py-4"><span class="text-xs text-apple-gray-400">Optional</span></td>
403
+ <td class="px-6 py-4 text-apple-gray-500">Path to <code class="text-xs bg-apple-gray-100 text-apple-indigo px-1 rounded font-mono">claude</code> binary</td>
404
+ </tr>
405
+ <tr class="config-row">
406
+ <td class="px-6 py-4"><code class="text-xs bg-apple-gray-100 text-apple-indigo px-1.5 py-0.5 rounded font-mono">CLAUDE_ADDITIONAL_ARGS</code></td>
407
+ <td class="px-4 py-4"><span class="text-xs text-apple-gray-400">Optional</span></td>
408
+ <td class="px-6 py-4 text-apple-gray-500">Extra CLI args for every invocation</td>
409
+ </tr>
410
+ <tr class="config-row">
411
+ <td class="px-6 py-4"><code class="text-xs bg-apple-gray-100 text-apple-indigo px-1.5 py-0.5 rounded font-mono">ENV_*</code></td>
412
+ <td class="px-4 py-4"><span class="text-xs text-apple-gray-400">Optional</span></td>
413
+ <td class="px-6 py-4 text-apple-gray-500">Injected into Claude's environment (e.g. <code class="text-xs bg-apple-gray-100 text-apple-indigo px-1 rounded font-mono">ENV_ANTHROPIC_API_KEY</code>)</td>
414
+ </tr>
415
+ </tbody>
416
+ </table>
417
+ </div>
418
+ </div>
419
+ </section>
420
+
421
+ <!-- Footer -->
422
+ <footer class="border-t border-apple-gray-200 py-12 bg-apple-gray-50">
423
+ <div class="max-w-5xl mx-auto px-6 text-center">
424
+ <div class="flex gap-8 justify-center mb-6">
425
+ <a href="https://github.com/raja-jamwal/compass" class="text-sm text-apple-gray-500 hover:text-apple-gray-900 no-underline transition-colors">GitHub</a>
426
+ <a href="https://www.npmjs.com/package/compass-agent" class="text-sm text-apple-gray-500 hover:text-apple-gray-900 no-underline transition-colors">npm</a>
427
+ <a href="https://github.com/raja-jamwal/compass/issues" class="text-sm text-apple-gray-500 hover:text-apple-gray-900 no-underline transition-colors">Issues</a>
428
+ </div>
429
+ <p class="text-sm text-apple-gray-400">MIT License</p>
430
+ </div>
431
+ </footer>
432
+
433
+ <script>
434
+ // Copy install command
435
+ $('#install-cmd').on('click', function() {
436
+ navigator.clipboard.writeText('bunx compass-agent');
437
+ const $icon = $('#copy-icon');
438
+ $icon.html('<svg class="w-4 h-4 text-green-400" fill="none" stroke="currentColor" stroke-width="2.5" viewBox="0 0 24 24"><path d="M5 13l4 4L19 7"/></svg>');
439
+ setTimeout(() => {
440
+ $icon.html('<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg>');
441
+ }, 2000);
442
+ });
443
+
444
+ // Smooth scroll
445
+ $('a[href^="#"]').on('click', function(e) {
446
+ e.preventDefault();
447
+ const target = $($(this).attr('href'));
448
+ if (target.length) {
449
+ $('html, body').animate({ scrollTop: target.offset().top - 48 }, 500);
450
+ }
451
+ });
452
+
453
+ // Scroll fade-in
454
+ const observer = new IntersectionObserver((entries) => {
455
+ entries.forEach(entry => {
456
+ if (entry.isIntersecting) {
457
+ entry.target.classList.add('visible');
458
+ }
459
+ });
460
+ }, { threshold: 0.1 });
461
+
462
+ $('.section-fade').each(function() {
463
+ observer.observe(this);
464
+ });
465
+ </script>
466
+
467
+ </body>
468
+ </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "compass-agent",
3
- "version": "2.0.7",
3
+ "version": "2.0.8",
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": {
package/src/app.ts CHANGED
@@ -33,6 +33,26 @@ if (envFileIdx !== -1 && process.argv[envFileIdx + 1]) {
33
33
  Object.assign(process.env, realEnv);
34
34
  // -----------------------------------------------------------------------------------------
35
35
 
36
+ // --- Required env validation ---
37
+ const requiredEnv = ["SLACK_BOT_TOKEN", "SLACK_APP_TOKEN"] as const;
38
+ const missing = requiredEnv.filter((k) => !process.env[k]);
39
+ if (missing.length > 0) {
40
+ console.error(`ERROR: Missing required environment variable(s): ${missing.join(", ")}`);
41
+ process.exit(1);
42
+ }
43
+
44
+ // Validate CLAUDE_PATH exists
45
+ const claudePath = process.env.CLAUDE_PATH || "claude";
46
+ if (path.isAbsolute(claudePath)) {
47
+ if (!fs.existsSync(claudePath)) {
48
+ console.error(`ERROR: CLAUDE_PATH not found: ${claudePath}`);
49
+ process.exit(1);
50
+ }
51
+ } else if (!Bun.which(claudePath)) {
52
+ console.error(`ERROR: CLAUDE_PATH "${claudePath}" not found in PATH. Set CLAUDE_PATH in .env to the full path of the claude binary.`);
53
+ process.exit(1);
54
+ }
55
+
36
56
  import { App } from "@slack/bolt";
37
57
  import { execFileSync } from "child_process";
38
58
  import {
@@ -219,8 +239,6 @@ app.command("/cwd", async ({ command, ack, client }: any) => {
219
239
  });
220
240
  });
221
241
 
222
- const CLAUDE_PATH = process.env.CLAUDE_PATH || "claude";
223
-
224
242
  // ── Modal submissions ───────────────────────────────────────
225
243
 
226
244
  app.view("cwd_modal", async ({ view, ack, client }: any) => {
@@ -647,18 +665,6 @@ async function processMessage({ channelId, threadTs, messageTs, userText, userId
647
665
  // ── Startup ─────────────────────────────────────────────────
648
666
 
649
667
  (async () => {
650
- // Validate CLAUDE_PATH exists before starting
651
- const claudePath = process.env.CLAUDE_PATH || "claude";
652
- // Check if it's an absolute path that exists, or resolve via Bun.which
653
- if (path.isAbsolute(claudePath)) {
654
- if (!fs.existsSync(claudePath)) {
655
- console.error(`ERROR: CLAUDE_PATH not found: ${claudePath}`);
656
- process.exit(1);
657
- }
658
- } else if (!Bun.which(claudePath)) {
659
- console.error(`ERROR: CLAUDE_PATH "${claudePath}" not found in PATH. Set CLAUDE_PATH in .env to the full path of the claude binary.`);
660
- process.exit(1);
661
- }
662
668
  log(null, `Claude CLI found: ${claudePath}`);
663
669
 
664
670
  // Register MCP server (idempotent — overwrites if already exists)
File without changes
File without changes
File without changes