clankie 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 ADDED
@@ -0,0 +1,578 @@
1
+ # lil — Personal AI Assistant
2
+
3
+ A minimal, focused AI assistant that lives in Slack. Built on [pi](https://github.com/badlogic/pi-mono)'s SDK, lil gives you a personal AI teammate that runs on your machine with your credentials.
4
+
5
+ ## What Can lil Do?
6
+
7
+ - 💬 **Natural conversations in Slack threads** — @mention once, then chat naturally
8
+ - 🧠 **Remember things** — Built-in memory system (facts, preferences, project context)
9
+ - 🎭 **Multiple personas** — Different personalities for different contexts (work, coding, personal)
10
+ - 🛠️ **Use tools** — Read/write files, run bash commands, search memory
11
+ - 🔌 **pi ecosystem** — Works with all pi extensions, skills, and prompt templates
12
+ - 🔒 **Privacy-first** — Runs on your machine, your credentials, your data
13
+
14
+ ## Installation
15
+
16
+ ### Option 1: Install via npm (Recommended)
17
+
18
+ Requires [Bun](https://bun.sh):
19
+
20
+ ```bash
21
+ # Install Bun first (if you don't have it)
22
+ curl -fsSL https://bun.sh/install | bash
23
+
24
+ # Install clankie globally
25
+ bun install -g clankie
26
+
27
+ # Verify installation
28
+ clankie --version
29
+ ```
30
+
31
+ ### Option 2: Install from Source
32
+
33
+ ```bash
34
+ # Install Bun
35
+ curl -fsSL https://bun.sh/install | bash
36
+
37
+ # Clone and install
38
+ git clone https://github.com/thiagovarela/clankie
39
+ cd lil
40
+ bun install
41
+
42
+ # Link globally
43
+ bun link --cwd packages/clankie
44
+ ```
45
+
46
+ Now `clankie` is available from anywhere.
47
+
48
+ ## Slack Setup
49
+
50
+ ### Step 1: Create Slack App from Manifest
51
+
52
+ 1. Go to **https://api.slack.com/apps**
53
+ 2. Click **Create New App** → **From an app manifest**
54
+ 3. Select your workspace and click **Next**
55
+ 4. Choose **YAML** tab and paste the contents of [`slack-app-manifest.yaml`](./slack-app-manifest.yaml)
56
+ 5. Click **Next** → Review the summary → Click **Create**
57
+
58
+ ### Step 2: Generate App Token (for Socket Mode)
59
+
60
+ 1. Go to **Basic Information** (in the sidebar)
61
+ 2. Scroll to **App-Level Tokens** → Click **Generate Token and Scopes**
62
+ 3. Name: `clankie-socket`
63
+ 4. Click **Add Scope** → Select `connections:write`
64
+ 5. Click **Generate**
65
+ 6. **Copy the token** (starts with `xapp-`) — you'll need this for config
66
+
67
+ ### Step 3: Install App to Workspace
68
+
69
+ 1. Go to **Install App** (in the sidebar)
70
+ 2. Click **Install to Workspace**
71
+ 3. Review permissions and click **Allow**
72
+ 4. **Copy the Bot Token** (starts with `xoxb-`) — you'll need this for config
73
+
74
+ ### Step 4: Get Your Slack User ID
75
+
76
+ 1. In Slack, click your profile picture → **View profile**
77
+ 2. Click the three dots (**⋯**) → **Copy member ID**
78
+ 3. Save this ID (looks like `U01ABC23DEF`)
79
+
80
+ ### Step 5: Configure lil
81
+
82
+ ```bash
83
+ lil config set channels.slack.appToken "xapp-1-A0AG6UWU92B-..."
84
+ lil config set channels.slack.botToken "xoxb-10594563095936-..."
85
+ lil config set channels.slack.allowFrom '["U01ABC23DEF"]'
86
+ ```
87
+
88
+ Replace:
89
+ - `xapp-...` with your App Token from Step 2
90
+ - `xoxb-...` with your Bot Token from Step 3
91
+ - `U01ABC23DEF` with your user ID from Step 4
92
+
93
+ ### Step 6: Authenticate with AI Provider
94
+
95
+ ```bash
96
+ lil login
97
+ ```
98
+
99
+ Choose your provider (Anthropic, OpenAI, etc.) and authenticate. Credentials are stored securely in `~/.clankie/auth.json`.
100
+
101
+ ### Step 7: Start lil
102
+
103
+ ```bash
104
+ lil start
105
+ ```
106
+
107
+ You should see:
108
+ ```
109
+ [daemon] Starting lil daemon (pid 12345)...
110
+ [daemon] Workspace: /Users/you/.clankie/workspace
111
+ [daemon] Channels: slack
112
+ [slack] Connected as @lil (U01XYZ...)
113
+ [daemon] Ready. Waiting for messages...
114
+ ```
115
+
116
+ ### Step 8: Test in Slack
117
+
118
+ 1. **Invite the bot to a channel**: Type `/invite @lil` in any channel
119
+ 2. **@mention it**: `@lil hello!`
120
+ 3. Bot creates a thread and replies
121
+ 4. **Continue the conversation** (no more @mentions needed): `what's 2+2?`
122
+ 5. Bot responds in the same thread
123
+
124
+ 🎉 **You're all set!**
125
+
126
+ ## Using lil
127
+
128
+ ### In Slack
129
+
130
+ #### Start a Conversation
131
+
132
+ @mention the bot anywhere:
133
+ ```
134
+ Channel: #general
135
+ You: @lil what's the weather in SF?
136
+ Thread 🧵
137
+ Bot: It's 68°F and sunny
138
+ You: and tomorrow?
139
+ Bot: Tomorrow will be 72°F
140
+ ```
141
+
142
+ After the first @mention, the bot responds to all your messages in that thread automatically.
143
+
144
+ #### Direct Messages
145
+
146
+ Just message the bot directly — no @mention needed:
147
+ ```
148
+ DM with @lil
149
+ You: analyze this data [uploads file]
150
+ Bot: Sure! Here's what I found...
151
+ You: can you summarize it?
152
+ Bot: Here's a summary...
153
+ ```
154
+
155
+ #### Share Files
156
+
157
+ Upload files directly in a conversation:
158
+ ```
159
+ You: @lil review this code
160
+ [uploads code.py]
161
+ Bot: I'll analyze it...
162
+ [provides feedback]
163
+ ```
164
+
165
+ The bot can read images (with vision models), documents, code files, etc.
166
+
167
+ ### CLI Commands
168
+
169
+ Even though lil lives in Slack, you also have CLI access:
170
+
171
+ ```bash
172
+ # Interactive chat session (local terminal, uses pi's TUI)
173
+ lil chat
174
+
175
+ # Send a one-off message (prints response and exits)
176
+ lil send "What files are in the current directory?"
177
+
178
+ # Shorthand (no subcommand needed)
179
+ lil "Summarize recent git commits"
180
+
181
+ # Check daemon status
182
+ lil status
183
+
184
+ # Stop daemon
185
+ lil stop
186
+
187
+ # View configuration
188
+ lil config show
189
+
190
+ # Set a config value
191
+ lil config set agent.model.primary "anthropic/claude-sonnet-4-5"
192
+ ```
193
+
194
+ ## Configuration
195
+
196
+ Config file: `~/.clankie/clankie.json` (JSON5 format — comments and trailing commas allowed)
197
+
198
+ ### Common Settings
199
+
200
+ ```bash
201
+ # Slack credentials
202
+ lil config set channels.slack.appToken "xapp-..."
203
+ lil config set channels.slack.botToken "xoxb-..."
204
+ lil config set channels.slack.allowFrom '["U12345678"]'
205
+
206
+ # AI model
207
+ lil config set agent.model.primary "anthropic/claude-sonnet-4-5"
208
+ lil config set agent.model.fallbacks '["openai/gpt-4o"]'
209
+
210
+ # Default persona
211
+ lil config set agent.persona "default"
212
+
213
+ # Workspace (where agent works)
214
+ lil config set agent.workspace "~/projects"
215
+ ```
216
+
217
+ ### Config Paths
218
+
219
+ | Path | Description | Example |
220
+ |------|-------------|---------|
221
+ | `agent.persona` | Default persona name | `"default"`, `"coding"`, `"work"` |
222
+ | `agent.workspace` | Agent working directory | `"~/projects"` |
223
+ | `agent.model.primary` | Primary AI model | `"anthropic/claude-sonnet-4-5"` |
224
+ | `agent.model.fallbacks` | Fallback models (array) | `["openai/gpt-4o"]` |
225
+ | `channels.slack.appToken` | Socket Mode app token | `"xapp-..."` |
226
+ | `channels.slack.botToken` | Bot token for API calls | `"xoxb-..."` |
227
+ | `channels.slack.allowFrom` | Allowed user IDs (array) | `["U12345678"]` |
228
+ | `channels.slack.persona` | Override persona for Slack | `"work"` |
229
+
230
+ ## Personas
231
+
232
+ Personas let you customize lil's personality, knowledge, and behavior for different contexts. Each persona is a set of markdown files that shape the system prompt.
233
+
234
+ ### Built-in Persona: "default"
235
+
236
+ lil ships with a minimal default persona. You can customize it:
237
+
238
+ ```bash
239
+ # View persona files
240
+ lil persona show default
241
+
242
+ # Edit persona
243
+ lil persona edit default
244
+ ```
245
+
246
+ ### Create a New Persona
247
+
248
+ ```bash
249
+ # Create a new persona
250
+ lil persona create coding
251
+
252
+ # Edit its files
253
+ lil persona edit coding
254
+ ```
255
+
256
+ This creates `~/.clankie/personas/coding/` with these files:
257
+
258
+ #### `identity.md` — Who the assistant is
259
+ ```markdown
260
+ # Identity
261
+
262
+ You are **lil (coding)**, a personal AI coding assistant.
263
+
264
+ - You're an expert in software engineering
265
+ - You prefer working solutions over perfect ones
266
+ - You're concise but thorough with explanations
267
+ - You use modern best practices
268
+ ```
269
+
270
+ #### `instructions.md` — How to behave
271
+ ```markdown
272
+ # Instructions
273
+
274
+ - Write clean, readable code with comments
275
+ - Explain complex concepts simply
276
+ - Run tests before claiming something works
277
+ - Use git for version control
278
+ - Ask for clarification on ambiguous requirements
279
+ ```
280
+
281
+ #### `knowledge.md` — User context
282
+ ```markdown
283
+ # User Knowledge
284
+
285
+ - Name: Thiago
286
+ - Stack: TypeScript, Bun, React
287
+ - Current project: lil (AI assistant)
288
+ - Prefers: Functional programming, immutability
289
+ ```
290
+
291
+ #### `persona.json` — Model override (optional)
292
+ ```json
293
+ {
294
+ // Override the global model for this persona
295
+ "model": "anthropic/claude-sonnet-4-5"
296
+ }
297
+ ```
298
+
299
+ ### Use a Persona
300
+
301
+ ```bash
302
+ # Set as default
303
+ lil config set agent.persona "coding"
304
+
305
+ # Use for a specific session
306
+ lil chat --persona coding
307
+ lil send --persona coding "Review this code"
308
+
309
+ # Use for Slack only
310
+ lil config set channels.slack.persona "work"
311
+ ```
312
+
313
+ ### Manage Personas
314
+
315
+ ```bash
316
+ # List all personas
317
+ lil persona
318
+
319
+ # Show persona files
320
+ lil persona show coding
321
+
322
+ # Edit persona
323
+ lil persona edit coding
324
+
325
+ # Edit specific file
326
+ lil persona edit coding identity.md
327
+
328
+ # Get persona directory path
329
+ lil persona path coding
330
+
331
+ # Remove persona
332
+ lil persona remove coding
333
+ ```
334
+
335
+ ## Memory
336
+
337
+ lil has a built-in memory system powered by SQLite FTS5 (full-text search). The bot can remember facts, preferences, and context across conversations.
338
+
339
+ ### How It Works
340
+
341
+ When you tell lil to remember something:
342
+ ```
343
+ You: @lil remember my timezone is PST
344
+ Bot: Got it, I'll remember that.
345
+ ```
346
+
347
+ Behind the scenes, lil uses the `remember` tool (provided by the persona extension) to store this in `~/.clankie/memory.db`. Later:
348
+
349
+ ```
350
+ You: @lil what time is it for me?
351
+ Bot: Since you're in PST, it's currently 3:45 PM.
352
+ ```
353
+
354
+ ### Memory Categories
355
+
356
+ Memories are automatically categorized:
357
+ - **preference** — User preferences, settings
358
+ - **fact** — Objective facts about the user, project, etc.
359
+ - **context** — Project context, working memory
360
+ - **note** — General notes, ideas
361
+
362
+ ### CLI Commands
363
+
364
+ ```bash
365
+ # Show memory stats
366
+ lil memory
367
+
368
+ # Search memories
369
+ lil memory search "timezone"
370
+
371
+ # List all memories (or by category)
372
+ lil memory list
373
+ lil memory list preference
374
+
375
+ # Export core memories as JSON
376
+ lil memory export > memories.json
377
+
378
+ # Forget a specific memory
379
+ lil memory forget "timezone"
380
+ ```
381
+
382
+ ### How lil Uses Memory
383
+
384
+ The persona extension automatically:
385
+ 1. **Injects relevant memories** into the system prompt based on the current conversation
386
+ 2. **Uses FTS5 search** to find contextually relevant memories
387
+ 3. **Provides the `remember` tool** so lil can store new information
388
+
389
+ You don't need to do anything special — just tell lil to remember things naturally.
390
+
391
+ ## Running as a Service
392
+
393
+ Instead of running `lil start` manually, you can install lil as a system service that starts automatically on boot.
394
+
395
+ ### Install Service
396
+
397
+ ```bash
398
+ lil daemon install
399
+ ```
400
+
401
+ This installs:
402
+ - **macOS**: launchd agent (`~/Library/LaunchAgents/ai.clankie.daemon.plist`)
403
+ - **Linux**: systemd user service (`~/.config/systemd/user/lil.service`)
404
+
405
+ The daemon starts immediately and runs on boot.
406
+
407
+ ### Manage Service
408
+
409
+ ```bash
410
+ # Check service status
411
+ lil daemon status
412
+
413
+ # View logs
414
+ lil daemon logs
415
+
416
+ # Uninstall service
417
+ lil daemon uninstall
418
+ ```
419
+
420
+ Logs are stored in `~/.clankie/logs/daemon.log`.
421
+
422
+ ## Security
423
+
424
+ lil includes a built-in security extension that protects against common mistakes:
425
+
426
+ ### What It Blocks
427
+
428
+ - **Dangerous bash commands**: `rm -rf /`, `sudo`, `curl | sh`, `eval`
429
+ - **Sensitive file writes**: `~/.ssh/`, `~/.aws/`, `.env` files, system directories
430
+ - **Credential reads**: SSH keys, AWS credentials, API keys, `~/.clankie/auth.json`
431
+ - **Network exfiltration**: Patterns that suggest data theft
432
+
433
+ ### What It Redacts
434
+
435
+ When the agent reads files, it automatically redacts:
436
+ - Private keys (PEM, SSH)
437
+ - API keys (OpenAI, Anthropic, AWS, GitHub, etc.)
438
+ - Tokens and secrets
439
+
440
+ The agent sees `[REDACTED:...]` instead of the actual value.
441
+
442
+ ### Limitations
443
+
444
+ ⚠️ **The security extension is not a sandbox.** It's a safety net for common mistakes, not a security boundary. The agent runs with your user permissions and can still:
445
+ - Write to most files in your home directory
446
+ - Run most bash commands
447
+ - Access the internet
448
+
449
+ **Don't give lil credentials to production systems or sensitive environments.**
450
+
451
+ For the full threat model, see `docs/security.md` (if you've added this).
452
+
453
+ ## Advanced Features
454
+
455
+ ### Cron Jobs (Scheduled Tasks)
456
+
457
+ lil can schedule periodic tasks (not yet documented — coming soon).
458
+
459
+ ### Heartbeat
460
+
461
+ lil can check `~/.clankie/heartbeat.md` periodically and take proactive actions (not yet documented — coming soon).
462
+
463
+ ### pi Extensions
464
+
465
+ lil works with all pi extensions out of the box. Extensions are loaded from:
466
+ - `~/.pi/agent/extensions/`
467
+ - `.pi/extensions/` (in your project)
468
+
469
+ See pi's documentation for creating extensions.
470
+
471
+ ### Skills
472
+
473
+ Skills are reusable CLI tools the agent can create and invoke. They're loaded from:
474
+ - `~/.agents/skills/` (global)
475
+ - `~/.pi/agent/skills/` (pi shared)
476
+ - `.pi/skills/` (project-specific)
477
+
478
+ See pi's documentation for the skills system.
479
+
480
+ ## Troubleshooting
481
+
482
+ ### Bot doesn't respond in threads
483
+
484
+ **Problem**: Bot replies to @mentions but ignores subsequent messages in the thread.
485
+
486
+ **Solution**: Make sure you added the `message.channels` event subscription and `channels:read` scope to your Slack app. Then reinstall the app to your workspace.
487
+
488
+ ### "No channels configured" error
489
+
490
+ **Problem**: `lil start` fails with "No channels configured".
491
+
492
+ **Solution**: Configure Slack credentials:
493
+ ```bash
494
+ lil config set channels.slack.appToken "xapp-..."
495
+ lil config set channels.slack.botToken "xoxb-..."
496
+ lil config set channels.slack.allowFrom '["U12345678"]'
497
+ ```
498
+
499
+ ### Bot responds to everyone
500
+
501
+ **Problem**: Bot responds to all users, not just you.
502
+
503
+ **Solution**: Set `allowFrom` to only include your user ID:
504
+ ```bash
505
+ lil config get channels.slack.allowFrom
506
+ lil config set channels.slack.allowFrom '["U12345678"]'
507
+ ```
508
+
509
+ ### "Failed to run git: fatal: 'main' is already used by worktree"
510
+
511
+ **Problem**: Git worktree conflicts when trying to merge.
512
+
513
+ **Solution**: Merge from the main worktree directory, not a branch worktree.
514
+
515
+ ### Daemon won't start after reboot
516
+
517
+ **Problem**: Daemon doesn't auto-start after reboot (when installed as service).
518
+
519
+ **Solution**: Check service status:
520
+ ```bash
521
+ lil daemon status
522
+ lil daemon logs
523
+ ```
524
+
525
+ If the service isn't running, reinstall:
526
+ ```bash
527
+ lil daemon uninstall
528
+ lil daemon install
529
+ ```
530
+
531
+ ## Development
532
+
533
+ ```bash
534
+ # Run directly with Bun (no build step)
535
+ bun run packages/clankie/src/cli.ts chat
536
+ bun run packages/clankie/src/cli.ts send "hello"
537
+
538
+ # Code quality checks
539
+ bun run check # Run linter
540
+ bun run check:fix # Auto-fix issues
541
+ bun run format # Format code
542
+ ```
543
+
544
+ ### Publishing a Release
545
+
546
+ 1. **Update version** in `packages/clankie/package.json`
547
+ 2. **Test the package**:
548
+ ```bash
549
+ bun run publish:dry-run
550
+ ```
551
+ 3. **Publish to npm**:
552
+ ```bash
553
+ bun run publish:npm
554
+ ```
555
+
556
+ This publishes the package to npm registry. Users can then install with:
557
+ ```bash
558
+ npm install -g clankie
559
+ ```
560
+
561
+ ## Philosophy
562
+
563
+ lil is a **thin wrapper around pi**, not a replacement. It reuses the entire pi ecosystem:
564
+ - Extensions, skills, and prompt templates just work
565
+ - Same agent runtime, same resource loaders
566
+ - Authentication shared with `pi` CLI
567
+
568
+ Where other assistants try to be everything, lil focuses on **one thing done well**: giving you a personal AI teammate in Slack that reuses proven infrastructure.
569
+
570
+ ## Credits
571
+
572
+ Built on [pi](https://github.com/badlogic/pi-mono) by [@badlogic](https://github.com/badlogic).
573
+
574
+ Inspired by [OpenClaw](https://github.com/badlogic/openclaw) and [mom](https://github.com/badlogic/pi-mono/tree/main/packages/mom).
575
+
576
+ ## License
577
+
578
+ MIT
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "clankie",
3
+ "version": "0.1.0",
4
+ "description": "A minimal personal AI assistant built on pi's SDK",
5
+ "type": "module",
6
+ "bin": {
7
+ "clankie": "src/cli.ts"
8
+ },
9
+ "files": [
10
+ "src",
11
+ "README.md"
12
+ ],
13
+ "scripts": {
14
+ "dev": "bun run src/cli.ts",
15
+ "prepublishOnly": "echo 'Publishing to npm...'",
16
+ "publish:npm": "npm publish",
17
+ "publish:dry-run": "npm publish --dry-run"
18
+ },
19
+ "keywords": [
20
+ "ai",
21
+ "assistant",
22
+ "slack",
23
+ "pi",
24
+ "chatbot",
25
+ "llm",
26
+ "anthropic",
27
+ "openai"
28
+ ],
29
+ "author": "Thiago Varela",
30
+ "license": "MIT",
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "git+https://github.com/thiagovarela/clankie.git",
34
+ "directory": "packages/clankie"
35
+ },
36
+ "homepage": "https://github.com/thiagovarela/clankie/tree/main/packages/clankie",
37
+ "bugs": {
38
+ "url": "https://github.com/thiagovarela/clankie/issues"
39
+ },
40
+ "engines": {
41
+ "bun": ">=1.0.0"
42
+ },
43
+ "dependencies": {
44
+ "@mariozechner/pi-ai": "^0.54.0",
45
+ "@mariozechner/pi-coding-agent": "^0.54.0",
46
+ "@sinclair/typebox": "^0.34.48",
47
+ "@slack/socket-mode": "^2.0.0",
48
+ "@slack/web-api": "^7.0.0",
49
+ "json5": "^2.2.3"
50
+ },
51
+ "devDependencies": {
52
+ "@types/bun": "latest"
53
+ }
54
+ }