obsidian-agent-fleet 0.4.2 → 0.4.4

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 CHANGED
@@ -1,157 +1,288 @@
1
1
  # Agent Fleet for Obsidian
2
2
 
3
- **File-backed AI agents, task scheduling, and interactive chat — all inside Obsidian.**
3
+ **Turn Obsidian into an AI-powered command center. Create autonomous agents, schedule tasks, chat in real-time, connect via Slack, and hook into any MCP service — all from your vault.**
4
4
 
5
- Agent Fleet lets you create, configure, and run AI agents directly from your Obsidian vault. Every agent, skill, task, and run log is a markdown file with YAML frontmatter. If the plugin disappears, your knowledge stays.
5
+ ![Agent Fleet Dashboard](screenshot.png)
6
6
 
7
- ## Key Features
7
+ ---
8
8
 
9
- - **Interactive Chat** chat with agents in a side panel with streaming markdown responses
10
- - **Session Persistence** — conversations survive panel close and Obsidian restarts via Claude CLI `--resume`
11
- - **Task Scheduling** — cron-based recurring tasks, one-shot runs, and manual execution
12
- - **Skill System** — reusable skill libraries that agents can share
13
- - **Agent Memory** — persistent context across runs via `[REMEMBER]...[/REMEMBER]` tags
14
- - **Live Dashboard** — overview with charts, run history, kanban board, and approval workflow
15
- - **Lucide Icon Picker** — searchable icon selector for agent avatars (1,400+ icons)
16
- - **18 Built-in Skills** — PDF, PPTX, DOCX, XLSX, Claude API, MCP Builder, Frontend Design, and more
17
- - **Run Output** — rendered markdown with collapsible tool call summaries
9
+ ## What is Agent Fleet?
18
10
 
19
- ## Requirements
11
+ Agent Fleet is an Obsidian plugin that lets you build, configure, and run AI agents directly from your vault. Agents are powered by **Claude Code CLI** — works with a Claude Max/Pro subscription or Anthropic API key. Every agent, skill, task, and run log is a markdown file. If the plugin disappears, your knowledge stays.
20
12
 
21
- - **Obsidian** 1.6.0 or later (desktop only)
22
- - **[Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code)** installed and authenticated
23
- ```bash
24
- npm install -g @anthropic-ai/claude-code
25
- claude # authenticate on first run
26
- ```
27
- - **Claude Max subscription** or Anthropic API key (for Claude Code CLI)
13
+ ### Core Capabilities
14
+
15
+ 🤖 **AI Agents** — Create specialized agents with system prompts, skills, permissions, heartbeat schedules, and memory. Each agent is a folder of markdown files you fully own and control.
16
+
17
+ 💬 **Interactive Chat** Dock a chat panel anywhere in Obsidian. Switch between agents. Attach documents and images. Send follow-up messages while the agent works.
18
+
19
+ 📡 **Slack Channels** Chat with your agents from Slack. Multi-agent routing via `@agent-name` prefix. Native "is thinking..." indicator via Slack Assistants API. Session persistence across restarts.
28
20
 
29
- ## Installation
21
+ 💓 **Heartbeat** — Autonomous periodic agent runs. Define what an agent does when no one is asking — monitoring, reports, health checks — with results posted to Slack.
30
22
 
31
- ### Via BRAT (recommended auto-updates)
23
+ 📋 **Task Board**Kanban view with scheduling, priority, real-time progress tracking, and abort. Tasks run on cron schedules or on-demand.
32
24
 
33
- 1. Install the [BRAT plugin](https://github.com/TfTHacker/obsidian42-brat) from Community Plugins
34
- 2. Open BRAT settings → **Add Beta Plugin**
35
- 3. Paste: `denberek/obsidian-agent-fleet`
36
- 4. Enable **Agent Fleet** in Settings → Community Plugins
25
+ 🔌 **MCP Integration** Discover, authenticate, and inspect MCP servers. One-click OAuth 2.1 authentication. Assign MCP tools to specific agents.
37
26
 
38
- ### Manual Install
27
+ 🧠 **Agent Memory** — Agents persist context across sessions using `[REMEMBER]` tags stored as markdown.
39
28
 
40
- 1. Download `main.js`, `manifest.json`, and `styles.css` from the [latest release](https://github.com/denberek/obsidian-agent-fleet/releases)
41
- 2. Create folder: `<your-vault>/.obsidian/plugins/agent-fleet/`
29
+ 📊 **Dashboard** Overview with run charts, success rates, token/cost tracking, activity timeline, fleet status, and streaming output from active agents.
30
+
31
+ ---
32
+
33
+ ## Quick Start
34
+
35
+ ### Install
36
+
37
+ **Via npm (recommended):**
38
+ ```bash
39
+ npm install -g obsidian-agent-fleet
40
+ ```
41
+ The installer automatically finds your Obsidian vaults and copies the plugin files.
42
+
43
+ **Via BRAT:**
44
+ 1. Install the [BRAT plugin](https://github.com/TfTHacker/obsidian42-brat)
45
+ 2. Add beta plugin: `denberek/obsidian-agent-fleet`
46
+ 3. Enable Agent Fleet in Settings → Community Plugins
47
+
48
+ **Manual:**
49
+ 1. Download `main.js`, `manifest.json`, `styles.css` from the [latest release](https://github.com/denberek/obsidian-agent-fleet/releases)
50
+ 2. Create `<vault>/.obsidian/plugins/agent-fleet/`
42
51
  3. Copy the 3 files into that folder
43
- 4. Restart Obsidian → Settings → Community Plugins → Enable **Agent Fleet**
52
+ 4. Restart Obsidian → Enable Agent Fleet
53
+
54
+ ### Requirements
55
+
56
+ - **Obsidian** 1.6.0+ (desktop only)
57
+ - **[Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code)** — the engine behind all agent execution:
58
+ ```bash
59
+ npm install -g @anthropic-ai/claude-code
60
+ claude # authenticate on first run
61
+ ```
62
+ - **Claude subscription** (Max or Pro) or **Anthropic API key** — Claude Code works with your existing subscription, no separate API costs. If you're already paying for Claude, you're ready to go.
44
63
 
45
- ## First Launch
64
+ ### First Launch
46
65
 
47
- On first launch, Agent Fleet creates a `_fleet/` folder in your vault root with:
66
+ On first launch, Agent Fleet creates a `_fleet/` folder in your vault:
48
67
 
49
68
  ```
50
69
  _fleet/
51
70
  ├── agents/
52
- │ └── fleet-orchestrator/ ← default agent (knows how to manage the fleet)
71
+ │ └── fleet-orchestrator/ ← default agent (manages the fleet)
53
72
  ├── skills/ ← 18 built-in skills
54
73
  ├── tasks/
74
+ ├── channels/
55
75
  ├── runs/
56
76
  └── memory/
57
77
  ```
58
78
 
59
- The **Fleet Orchestrator** agent is ready to use — click **Chat** to ask it to create new agents, tasks, or skills.
79
+ The **Fleet Orchestrator** agent is ready — click Chat to ask it to create new agents, tasks, skills, or channels.
80
+
81
+ ### Update
60
82
 
61
- ## How It Works
83
+ ```bash
84
+ npm update -g obsidian-agent-fleet
85
+ ```
86
+
87
+ Or via BRAT: settings → check for updates.
88
+
89
+ ---
90
+
91
+ ## Features
62
92
 
63
93
  ### Agents
64
94
 
65
- Each agent is a folder in `_fleet/agents/<name>/` with these files:
95
+ Agents are AI assistants with specific personalities, capabilities, and permissions. Each agent is a folder in `_fleet/agents/` containing markdown files:
96
+
97
+ ```
98
+ agents/my-agent/
99
+ ├── agent.md ← Identity: name, description, system prompt
100
+ ├── config.md ← Runtime: model, timeout, permissions
101
+ ├── SKILLS.md ← Agent-specific skills
102
+ ├── CONTEXT.md ← Project context
103
+ └── HEARTBEAT.md ← Autonomous periodic run instruction (optional)
104
+ ```
105
+
106
+ **What you can configure:**
107
+
108
+ | Setting | Description |
109
+ |---------|-------------|
110
+ | **Name & Description** | Identity shown in the dashboard |
111
+ | **Avatar** | Lucide icon picker (1,400+ icons) or emoji |
112
+ | **System Prompt** | Core instructions that define the agent's behavior |
113
+ | **Model** | Claude Opus 4.6, Sonnet 4.6, Haiku 4.5, Bedrock models, or custom |
114
+ | **Adapter** | Claude Code (more adapters coming soon) |
115
+ | **Working Directory** | Where the agent operates (defaults to vault root) |
116
+ | **Timeout** | Max execution time in seconds |
117
+ | **Permission Mode** | bypassPermissions, dontAsk, acceptEdits, or plan |
118
+ | **Allow/Deny Lists** | Fine-grained tool control (e.g., allow `Bash(curl *)`, deny `Bash(rm -rf *)`) |
119
+ | **Skills** | Shared skills from the skill library |
120
+ | **MCP Servers** | Which MCP servers the agent can access |
121
+ | **Memory** | Persistent context across sessions via `[REMEMBER]` tags |
122
+ | **Heartbeat** | Autonomous periodic run with schedule and instruction |
123
+
124
+ **Permission Modes:**
125
+
126
+ | Mode | Behavior |
127
+ |------|----------|
128
+ | `bypassPermissions` | Auto-runs everything except deny list |
129
+ | `dontAsk` | Only allow-listed commands run |
130
+ | `acceptEdits` | File edits auto-approved, bash blocked unless allowed |
131
+ | `plan` | Read-only — no writes, no commands |
132
+
133
+ ---
134
+
135
+ ### Heartbeat
136
+
137
+ A heartbeat gives an agent autonomous behavior — what it does when no one is asking. Think periodic monitoring, daily reports, health checks, or trend analysis.
66
138
 
67
- | File | Purpose |
68
- |------|---------|
69
- | `agent.md` | Identity, description, system prompt, skill assignments |
70
- | `config.md` | Model, timeout, permission mode, working directory |
71
- | `CONTEXT.md` | Project-specific context (optional) |
72
- | `SKILLS.md` | Agent-specific skills not shared with others (optional) |
73
- | `permissions.json` | Claude Code allow/deny rules (optional) |
139
+ **Setup:** Create a `HEARTBEAT.md` file in the agent's folder, or configure it in the dashboard's agent edit page:
74
140
 
75
- **Example `agent.md`:**
76
141
  ```yaml
77
142
  ---
78
- name: site-monitor
79
- description: Checks website uptime and alerts on failures
80
- avatar: globe
81
143
  enabled: true
82
- tags: [monitoring]
83
- skills:
84
- - agent-fleet-system
144
+ schedule: "0 */6 * * *" # every 6 hours
145
+ notify: true # Obsidian notice on completion
146
+ channel: my-slack # post results to Slack (optional)
85
147
  ---
86
148
 
87
- You are a website monitoring agent. Check the specified URL,
88
- report its HTTP status code, response time, and any errors.
149
+ Check all monitored endpoints for availability and response time.
150
+ Compare with previous checks using your memory. Report anomalies.
151
+ If everything is healthy, respond with a one-line "all clear".
89
152
  ```
90
153
 
91
- ### Skills
154
+ **Key behaviors:**
155
+ - The **"Run Now" button** on any agent with a heartbeat uses the heartbeat instruction (no more generic fallback)
156
+ - **Agent memory integration** — heartbeats can use `[REMEMBER]` tags to track trends across runs
157
+ - **Slack delivery** — results automatically posted to a configured Slack channel
158
+ - **Dashboard** — heartbeat status shown on the agent's Overview tab with enable/disable toggle, schedule, and next run time
92
159
 
93
- Reusable instruction sets in `_fleet/skills/<name>/`:
160
+ ---
94
161
 
95
- | File | Purpose |
96
- |------|---------|
97
- | `skill.md` | Core instructions and description |
98
- | `tools.md` | CLI/API tool documentation (optional) |
99
- | `references.md` | Background docs, conventions (optional) |
100
- | `examples.md` | Few-shot examples (optional) |
162
+ ### Slack Channels
101
163
 
102
- Agents reference skills by name in their `agent.md` frontmatter. Multiple agents can share the same skill.
164
+ Chat with your agents from Slack every message flows through the same Claude CLI session pipeline, with full tool use, session persistence, and agent memory.
103
165
 
104
- ### Tasks
166
+ > **📖 [Step-by-step Slack setup guide →](SLACK_SETUP.md)** — complete walkthrough from creating the Slack app to sending your first message.
105
167
 
106
- Scheduled or one-shot tasks in `_fleet/tasks/<name>.md`:
168
+ **Quick overview:**
169
+ 1. Create a Slack app at [api.slack.com](https://api.slack.com/apps) with Socket Mode + Agents & AI Apps enabled
170
+ 2. Add credentials in Settings → Agent Fleet → Channel Credentials
171
+ 3. Create a channel via the dashboard or as `_fleet/channels/my-slack.md`
172
+ 4. DM the bot from Slack
107
173
 
108
174
  ```yaml
109
175
  ---
110
- task_id: check-website
111
- agent: site-monitor
112
- schedule: "0 * * * *" # every hour
113
- type: recurring
176
+ name: my-slack
177
+ type: slack
178
+ default_agent: fleet-orchestrator
179
+ allowed_agents:
180
+ - fleet-orchestrator
181
+ - site-monitor
182
+ - code-reviewer
114
183
  enabled: true
184
+ credential_ref: my-slack-creds
185
+ allowed_users:
186
+ - U0AQW6P37N1
187
+ per_user_sessions: true
188
+ channel_context: |
189
+ You are being contacted via Slack. Keep replies concise.
115
190
  ---
116
-
117
- Check https://example.com — report status code and response time.
118
191
  ```
119
192
 
120
- **Task types:**
121
- - `recurring`runs on a cron schedule
122
- - `once`runs at a specific time (`run_at` field)
123
- - `immediate` runs once on creation
193
+ **Features:**
194
+ - **Socket Mode** outbound WebSocket, works behind NAT/firewalls, no public URL needed
195
+ - **Slack Assistants API** native "is thinking..." indicator, threaded conversations, thread titles
196
+ - **Multi-agent routing** — type `@agent-name: message` to switch agents mid-thread. Each agent gets its own isolated session. `/agents` slash command lists available agents.
197
+ - **Session persistence** — conversations survive Obsidian restarts via `claude --resume`
198
+ - **Idle hibernation** — subprocess eviction after configurable idle time, transparent resume on next message
199
+ - **Allowlist** — only approved Slack users (by user ID) can reach the bot
200
+ - **Rate limiting** — per-conversation sliding window to prevent budget burn
201
+ - **Markdown → mrkdwn** — automatic formatting conversion with fence-aware chunking for long replies
124
202
 
125
- ### Chat
203
+ **Important:** Obsidian must be running for channels to work. When Obsidian is closed, the bot goes offline.
126
204
 
127
- Click **Chat** on any agent to open an interactive conversation panel. Features:
205
+ ---
128
206
 
129
- - **Streaming responses** — text appears in real-time as the agent works
130
- - **Markdown rendering** — headers, lists, code blocks, tables render properly
131
- - **Tool activity indicator** — shows what the agent is doing ("Working… (Read)")
132
- - **Collapsible tool summary** — "🔧 12 tool calls" after each response
133
- - **Session persistence** — close and reopen, your conversation is still there
134
- - **`--resume` sessions** — Claude CLI maintains full tool context between turns
135
- - **New Chat** button to start fresh
207
+ ### Interactive Chat
136
208
 
137
- ### Run History
209
+ The chat panel is a first-class Obsidian view — dock it in the sidebar, center, or any split.
138
210
 
139
- Every execution (scheduled or manual) is logged in `_fleet/runs/YYYY-MM-DD/` with:
140
- - Status (success, failure, timeout, cancelled, pending_approval)
141
- - Duration, token count, model used
142
- - Full prompt and output
143
- - Tools used with commands
211
+ **Features:**
212
+ - **Agent Switcher** dropdown to switch between agents instantly. Each agent has its own conversation.
213
+ - **Session Persistence** conversations survive Obsidian restarts via Claude CLI `--resume`
214
+ - **Bidirectional Streaming** send follow-up messages while the agent is working. Steer it mid-task.
215
+ - **Document Attachment** click + to attach the active document. Agent gets the full content; you see a compact pill.
216
+ - **Image Paste & Drop** — paste from clipboard or drag images into chat. Saved to vault, passed to Claude.
217
+ - **Stop Button** — + button becomes ■ while agent works. Click to abort.
218
+ - **Streaming Markdown** — responses render in real-time with syntax highlighting
219
+ - **Code Block Copy** — hover any code block for a copy button
220
+ - **Tool Activity** — see which tools the agent is using in real-time
144
221
 
145
- ### Agent Memory
222
+ ---
223
+
224
+ ### Task Board
225
+
226
+ A kanban view for managing agent tasks with five columns:
227
+
228
+ | Column | Description |
229
+ |--------|-------------|
230
+ | **Backlog** | Tasks with no schedule, waiting to be run manually |
231
+ | **Scheduled** | Tasks with a cron schedule, enabled and waiting |
232
+ | **Running** | Currently executing — shows real-time progress bar tied to timeout |
233
+ | **Done** | Completed today |
234
+ | **Failed** | Failed, timed out, or cancelled today |
235
+
236
+ **Task features:**
237
+ - **Priority** — low / medium / high / critical (color-coded left border)
238
+ - **Real-time Progress** — progress bar shows elapsed time vs timeout, updates every second
239
+ - **Stop Button** — red ■ on running cards to abort (shows as "Cancelled", not "Failed")
240
+ - **Cron Scheduling** — human-friendly picker (daily, weekdays, weekly, monthly, custom)
241
+ - **Catch Up If Missed** — auto-run overdue tasks when Obsidian opens
242
+ - **Run Now** — execute any task immediately regardless of schedule
243
+ - **Drag & Drop** — move tasks between backlog and scheduled columns
244
+
245
+ ---
246
+
247
+ ### MCP Servers
248
+
249
+ Discover and manage all MCP (Model Context Protocol) servers configured in Claude Code.
250
+
251
+ **Discovery:**
252
+ - **stdio servers** — spawned and probed directly via JSON-RPC (~1-2s)
253
+ - **HTTP/SSE servers** — probed with OAuth tokens for full tool schemas
254
+ - **Plugin metadata** — descriptions from Claude's plugin directory
255
+
256
+ **OAuth 2.1 Authentication:**
257
+
258
+ One-click browser-based auth for MCP servers:
259
+ 1. Click "Authenticate" on any server card
260
+ 2. Plugin discovers OAuth endpoints automatically
261
+ 3. Registers via Dynamic Client Registration
262
+ 4. Opens browser for approval (PKCE flow)
263
+ 5. Tokens stored in plugin settings, auto-refresh
264
+
265
+ **Server Management:**
266
+ - Enable/disable toggle per server (writes to Claude's settings)
267
+ - Server cards show status, tool count, type, description
268
+ - Detail slideover with full tool list, descriptions, input schemas, parameters
269
+ - Assign MCP servers to specific agents in the agent editor
270
+
271
+ ---
272
+
273
+ ### Skills
274
+
275
+ Reusable instruction sets that agents share. Each skill is a folder:
146
276
 
147
- When `memory: true` in config, agents can persist context using:
148
277
  ```
149
- [REMEMBER]Something important to remember[/REMEMBER]
278
+ skills/my-skill/
279
+ ├── skill.md ← Core instructions
280
+ ├── tools.md ← CLI/API tool documentation
281
+ ├── references.md ← Background docs
282
+ └── examples.md ← Few-shot examples
150
283
  ```
151
284
 
152
- These entries are appended to `_fleet/memory/<agent-name>.md` and included in future prompts.
153
-
154
- ## Built-in Skills
285
+ **18 Built-in Skills:**
155
286
 
156
287
  | Skill | Description |
157
288
  |-------|-------------|
@@ -168,21 +299,77 @@ These entries are appended to `_fleet/memory/<agent-name>.md` and included in fu
168
299
  | `pptx` | Create, read, edit PowerPoint (.pptx) files |
169
300
  | `skill-creator` | Create, evaluate, and optimize skills |
170
301
  | `slack-gif-creator` | Animated GIFs optimized for Slack |
171
- | `theme-factory` | Apply visual themes to artifacts |
172
- | `web-artifacts-builder` | Multi-component HTML artifacts with React/Tailwind |
173
- | `webapp-testing` | Test web apps with Playwright |
174
- | `xlsx` | Create, read, edit spreadsheet files |
302
+ | `taste-skill` | Senior UI/UX engineering for frontend design |
303
+ | `frontend-slides` | HTML presentation creation |
304
+ | And more... | |
305
+
306
+ ---
307
+
308
+ ### Dashboard
309
+
310
+ The main overview with:
175
311
 
176
- ## Dashboard
312
+ - **Stat Cards** — active agents, runs today, tokens used (with cost), scheduled tasks
313
+ - **Run Activity Chart** — 14-day bar chart with green (success), yellow (cancelled), red (failure)
314
+ - **Success Rate Donut** — overall success percentage
315
+ - **Active Agent Cards** — fixed-height streaming output from running agents with agent→task title
316
+ - **Activity Timeline** — recent runs with status, duration, tokens
317
+ - **Fleet Status** — agent list with quick-run capability
177
318
 
178
- The dashboard provides:
319
+ **Sidebar navigation:**
320
+ - Dashboard / Agents / Tasks Board / Run History / Approvals / Skills / MCP Servers / Channels
179
321
 
180
- - **Overview** agent status cards with run charts
181
- - **Agents** manage agents with enable/disable toggles
182
- - **Tasks Board** kanban view of pending, completed, and failed runs
183
- - **Run History** searchable table of all executions
184
- - **Skills Library** — browse and manage shared skills
185
- - **Approvals** — review and approve/reject pending tool uses
322
+ **Agent detail page tabs:**
323
+ - Overview (stats, heartbeat status, skills, permissions, recent runs)
324
+ - Config (all settings, system prompt, heartbeat instruction)
325
+ - Runs (full history for this agent)
326
+ - Memory (learned context)
327
+
328
+ ---
329
+
330
+ ### Agent Memory
331
+
332
+ Agents persist context across sessions:
333
+
334
+ 1. Agent includes `[REMEMBER]important context[/REMEMBER]` in its output
335
+ 2. Extracted and appended to `_fleet/memory/<agent-name>.md`
336
+ 3. Injected into the agent's prompt on every future run
337
+ 4. Memory is agent-scoped — shared across all conversations including Slack channels
338
+
339
+ ---
340
+
341
+ ### Run History
342
+
343
+ Every execution is logged in `_fleet/runs/YYYY-MM-DD/`:
344
+
345
+ ```yaml
346
+ ---
347
+ run_id: abc123
348
+ agent: fleet-orchestrator
349
+ task: daily-report
350
+ status: success
351
+ started: 2026-04-03T09:00:00
352
+ completed: 2026-04-03T09:02:30
353
+ duration_seconds: 150
354
+ tokens_used: 4500
355
+ cost_usd: 0.07
356
+ model: claude-opus-4-6
357
+ tags: [heartbeat]
358
+ ---
359
+
360
+ ## Prompt
361
+ ...
362
+
363
+ ## Output
364
+ ...
365
+
366
+ ## Tools Used
367
+ ...
368
+ ```
369
+
370
+ Click any run in the dashboard to see full details in a slideover panel.
371
+
372
+ ---
186
373
 
187
374
  ## Configuration
188
375
 
@@ -192,81 +379,79 @@ The dashboard provides:
192
379
  |---------|---------|-------------|
193
380
  | Fleet Folder | `_fleet` | Root folder for all fleet data |
194
381
  | Claude CLI Path | `claude` | Path to Claude Code CLI |
195
- | Default Model | `default` | Default model for agents |
196
- | Max Concurrent Runs | `3` | Parallel execution limit |
197
- | Run Log Retention | `30` days | Auto-cleanup old run logs |
198
- | Catch Up Missed Tasks | `true` | Run missed tasks on startup |
382
+ | Default Model | `default` | Default model for new agents |
383
+ | AWS Region | `us-east-1` | For AWS Bedrock model support |
384
+ | Max Concurrent Runs | `2` | Parallel task execution limit |
385
+ | Run Log Retention | `30` days | Auto-cleanup old logs |
386
+ | Catch Up Missed Tasks | `true` | Run overdue tasks on startup |
199
387
  | Notification Level | `all` | `all`, `failures-only`, `none` |
200
388
 
201
- ### Agent Permission Modes
389
+ ### Channel Settings
202
390
 
203
- | Mode | Behavior |
204
- |------|----------|
205
- | `bypassPermissions` | Auto-runs everything except deny list |
206
- | `dontAsk` | Only allow-listed commands run |
207
- | `acceptEdits` | File edits auto-approved |
208
- | `plan` | Read-only, no execution |
391
+ | Setting | Default | Description |
392
+ |---------|---------|-------------|
393
+ | Max Concurrent Sessions | `5` | Live claude subprocesses across all channels |
394
+ | Idle Timeout | `15` min | Hibernate sessions after inactivity |
395
+ | Rate Limit | `20` msgs / `5` min | Per-conversation sliding window |
209
396
 
210
- ## Architecture
397
+ ### File Structure
398
+
399
+ All data lives in `_fleet/` as plain markdown:
211
400
 
212
401
  ```
213
- src/
214
- ├── main.ts Plugin entry point
215
- ├── defaults.ts Embedded default agents + skills
216
- ├── fleetRepository.ts File I/O and vault management
217
- ├── types.ts TypeScript interfaces
218
- ├── constants.ts View types and defaults
219
- ├── settingsTab.ts Plugin settings UI
220
- ├── services/
221
- │ ├── chatSession.ts Interactive chat with --resume
222
- │ ├── executionManager.ts Claude CLI process spawning
223
- │ ├── fleetRuntime.ts Runtime state and orchestration
224
- │ └── taskScheduler.ts Cron-based task scheduling
225
- ├── views/
226
- │ ├── dashboardView.ts Main dashboard (3700+ lines)
227
- │ ├── agentsView.ts Sidebar agent list
228
- │ ├── sidebarView.ts Navigation sidebar
229
- │ └── inboxView.ts Inbox view
230
- ├── modals/
231
- │ ├── iconPickerModal.ts Lucide icon selector
232
- │ ├── taskModal.ts Task creation
233
- │ ├── createAgentModal.ts Agent creation wizard
234
- │ └── confirmDeleteModal.ts Deletion confirmation
235
- ├── components/
236
- │ ├── chartRenderer.ts Bar and donut charts
237
- │ ├── dragDrop.ts Drag and drop utilities
238
- │ └── scheduleEditor.ts Cron schedule editor
239
- └── utils/
240
- ├── icons.ts Icon helper
241
- └── markdown.ts Frontmatter parser
402
+ _fleet/
403
+ ├── agents/ Agent folders (agent.md, config.md, HEARTBEAT.md, etc.)
404
+ ├── skills/ Shared skill folders (skill.md, tools.md, etc.)
405
+ ├── tasks/ Task files with frontmatter
406
+ ├── channels/ Channel bindings (Slack, etc.)
407
+ ├── runs/ Execution logs by date
408
+ │ └── YYYY-MM-DD/
409
+ ├── memory/ Agent memory files
410
+ └── chat-images/ Images pasted into chat
242
411
  ```
243
412
 
244
- ## Development
413
+ Everything is searchable, version-controllable, and fully yours.
245
414
 
246
- ```bash
247
- # Clone
248
- git clone https://github.com/denberek/obsidian-agent-fleet.git
249
- cd obsidian-agent-fleet
415
+ ---
250
416
 
251
- # Install dependencies
252
- npm install
417
+ ## FAQ
253
418
 
254
- # Development build (watches for changes)
255
- npm run dev
419
+ **Q: Do I need an API key?**
420
+ Not necessarily. Agent Fleet works with your **Claude Max or Pro subscription** via Claude Code CLI. No separate API key or billing. If you prefer, you can also use an Anthropic API key directly.
256
421
 
257
- # Production build
258
- npm run build
422
+ **Q: Does it work without internet?**
423
+ No — agents need the Claude API to run. But all your data (agents, tasks, skills, memory) is local markdown.
259
424
 
260
- # Type check
261
- npx tsc --noEmit
425
+ **Q: Can I use different models per agent?**
426
+ Yes. Each agent has its own model setting. Supports Anthropic direct (Opus, Sonnet, Haiku) and AWS Bedrock models.
262
427
 
263
- # Run tests
264
- npm test
428
+ **Q: What happens if I delete the plugin?**
429
+ Your `_fleet/` folder stays. All agents, tasks, skills, run logs, and memory are plain markdown files in your vault.
265
430
 
266
- # Symlink to vault for development
267
- ln -s $(pwd) ~/path-to-vault/.obsidian/plugins/agent-fleet
268
- ```
431
+ **Q: Can multiple agents run at the same time?**
432
+ Yes, up to `maxConcurrentRuns` (default 2). Additional tasks queue until a slot opens.
433
+
434
+ **Q: Does the chat remember previous conversations?**
435
+ Yes. Each agent has persistent chat sessions that survive Obsidian restarts via Claude CLI `--resume`.
436
+
437
+ **Q: Does the Slack bot work when Obsidian is closed?**
438
+ No. The bot runs inside Obsidian via Socket Mode — when Obsidian is closed, the bot goes offline. Slack buffers messages briefly during short disconnects.
269
439
 
270
- ## License
440
+ **Q: Can I use multiple agents in Slack?**
441
+ Yes. Type `@agent-name: message` to switch agents within a Slack thread. Each agent maintains its own session. Use `/agents` to see available agents.
442
+
443
+ **Q: What is a heartbeat?**
444
+ An autonomous periodic run — what an agent does on a schedule without user input. Configured via `HEARTBEAT.md` in the agent's folder. Results can be posted to a Slack channel automatically.
445
+
446
+ ---
447
+
448
+ ## Links
449
+
450
+ - [Slack Setup Guide](SLACK_SETUP.md)
451
+ - [Releases](https://github.com/denberek/obsidian-agent-fleet/releases)
452
+ - [npm package](https://www.npmjs.com/package/obsidian-agent-fleet)
453
+ - [Report Issues](https://github.com/denberek/obsidian-agent-fleet/issues)
454
+
455
+ ---
271
456
 
272
- MIT
457
+ © 2026 Denis Berekchiyan. All rights reserved.
package/SLACK_SETUP.md ADDED
@@ -0,0 +1,285 @@
1
+ # Slack Setup Guide
2
+
3
+ Connect your Agent Fleet agents to Slack so you can chat with them from your phone, desktop, or anywhere Slack runs.
4
+
5
+ ---
6
+
7
+ ## Prerequisites
8
+
9
+ Before you start, make sure you have:
10
+
11
+ - **Agent Fleet plugin** installed and running in Obsidian
12
+ - **At least one agent** configured in your fleet (the default Fleet Orchestrator works)
13
+ - **A Slack workspace** where you have permission to install apps (your own workspace or admin access)
14
+
15
+ ---
16
+
17
+ ## Part 1: Create the Slack App
18
+
19
+ ### Step 1 — Create a new app
20
+
21
+ 1. Go to **https://api.slack.com/apps**
22
+ 2. Click **Create New App** → **From scratch**
23
+ 3. **App Name:** `Agent Fleet` (or any name you prefer)
24
+ 4. **Pick a workspace:** select the Slack workspace you want to use
25
+ 5. Click **Create App**
26
+
27
+ ### Step 2 — Enable Socket Mode
28
+
29
+ Socket Mode lets the bot connect to Slack via an outbound WebSocket — no public URL, no port forwarding, works behind any firewall or NAT.
30
+
31
+ 1. In the left sidebar, click **Socket Mode**
32
+ 2. Toggle **Enable Socket Mode** → ON
33
+ 3. You'll be prompted to create an App-Level Token:
34
+ - **Token Name:** `socket-token`
35
+ - **Scope:** select `connections:write`
36
+ - Click **Generate**
37
+ 4. **Copy the `xapp-...` token** — this is your **App Token**. Save it somewhere safe, you won't see it again without regenerating.
38
+
39
+ ### Step 3 — Enable Agents & AI Apps
40
+
41
+ This gives you the native "is thinking..." indicator and threaded assistant conversations.
42
+
43
+ 1. In the left sidebar, click **Agents & AI Apps**
44
+ 2. Click **Opt In** (or toggle ON)
45
+ 3. Save
46
+
47
+ ### Step 4 — Add Bot Token Scopes
48
+
49
+ 1. In the left sidebar, click **OAuth & Permissions**
50
+ 2. Scroll down to **Bot Token Scopes**
51
+ 3. Click **Add an OAuth Scope** and add ALL of the following (one at a time):
52
+
53
+ | Scope | Purpose |
54
+ |-------|---------|
55
+ | `assistant:write` | Native "is thinking..." indicator and thread titles |
56
+ | `chat:write` | Send messages and replies |
57
+ | `commands` | Handle the `/agents` slash command |
58
+ | `im:history` | Read DM conversation history |
59
+ | `im:read` | Access DM metadata |
60
+ | `im:write` | Open DM conversations |
61
+ | `app_mentions:read` | Respond when @mentioned in channels |
62
+ | `reactions:write` | Add/remove emoji reactions (legacy, harmless to keep) |
63
+
64
+ ### Step 5 — Subscribe to Bot Events
65
+
66
+ 1. In the left sidebar, click **Event Subscriptions**
67
+ 2. Toggle **Enable Events** → ON
68
+ 3. Expand **Subscribe to bot events**
69
+ 4. Click **Add Bot User Event** and add all four:
70
+
71
+ | Event | Purpose |
72
+ |-------|---------|
73
+ | `assistant_thread_started` | Detect new assistant conversations |
74
+ | `assistant_thread_context_changed` | Context switching (reserved for future use) |
75
+ | `message.im` | Receive DM messages |
76
+ | `app_mention` | Respond to @mentions in channels |
77
+
78
+ 5. Click **Save Changes** at the bottom of the page
79
+
80
+ ### Step 6 — Enable the Messages Tab
81
+
82
+ 1. In the left sidebar, click **App Home**
83
+ 2. Scroll to **Show Tabs**
84
+ 3. Under **Messages Tab**, check: **Allow users to send Slash commands and messages from the messages tab**
85
+
86
+ ### Step 7 — Register the /agents Slash Command
87
+
88
+ 1. In the left sidebar, click **Slash Commands**
89
+ 2. Click **Create New Command**
90
+ 3. Fill in:
91
+ - **Command:** `/agents`
92
+ - **Short Description:** `List available agents`
93
+ - **Usage Hint:** _(leave blank)_
94
+ 4. Click **Save**
95
+
96
+ ### Step 8 — Install the App to Your Workspace
97
+
98
+ 1. In the left sidebar, click **Install App**
99
+ 2. Click **Install to Workspace**
100
+ 3. Review and approve the permission screen
101
+ 4. **Copy the Bot User OAuth Token** (`xoxb-...`) — this is your **Bot Token**
102
+
103
+ You now have two tokens:
104
+ - **App Token** (`xapp-...`) from Step 2
105
+ - **Bot Token** (`xoxb-...`) from Step 8
106
+
107
+ ---
108
+
109
+ ## Part 2: Configure Agent Fleet
110
+
111
+ ### Step 1 — Add Slack Credentials
112
+
113
+ 1. Open Obsidian
114
+ 2. Go to **Settings → Agent Fleet**
115
+ 3. Scroll down to **Channel Credentials**
116
+ 4. Under **Add a Slack credential:**
117
+ - **Reference name:** `slack` (or any name — this is what your channel file will reference)
118
+ - **Bot token:** paste your `xoxb-...` token
119
+ - **App-level token:** paste your `xapp-...` token
120
+ 5. Click **Add credential**
121
+
122
+ You should see the credential appear in the list above the form.
123
+
124
+ ### Step 2 — Create a Channel
125
+
126
+ **Option A — Via the dashboard (recommended):**
127
+
128
+ 1. Open the Agent Fleet dashboard
129
+ 2. Click the **Channels** tab (last tab)
130
+ 3. Click **+ New Channel**
131
+ 4. Fill in:
132
+ - **Name:** `my-slack`
133
+ - **Type:** Slack (only option for now)
134
+ - **Credential:** select the credential you just added
135
+ - **Enabled:** ON
136
+ - **Default agent:** pick which agent handles messages by default
137
+ - **Allowed agents:** check the agents you want reachable via `@agent-name` prefix (leave unchecked for all)
138
+ - **Per-user sessions:** ON (each Slack user gets their own Claude session)
139
+ - **Allowed users:** enter your Slack user ID (see below how to find it)
140
+ - **Channel context:** optionally add instructions like "Keep replies concise, use Slack formatting"
141
+ 5. Click **Create Channel**
142
+
143
+ **Option B — Via markdown file:**
144
+
145
+ Create `_fleet/channels/my-slack.md` in your vault:
146
+
147
+ ```yaml
148
+ ---
149
+ name: my-slack
150
+ type: slack
151
+ default_agent: fleet-orchestrator
152
+ allowed_agents:
153
+ - fleet-orchestrator
154
+ enabled: true
155
+ credential_ref: slack
156
+ allowed_users:
157
+ - U0AQW6P37N1
158
+ per_user_sessions: true
159
+ channel_context: |
160
+ You are being contacted via Slack. Keep replies concise.
161
+ ---
162
+ ```
163
+
164
+ ### Step 3 — Find Your Slack User ID
165
+
166
+ The `allowed_users` field requires Slack user IDs (not usernames). To find yours:
167
+
168
+ 1. Open Slack
169
+ 2. Click your **avatar** or **profile picture** (top-right on desktop, or tap your name on mobile)
170
+ 3. Click **Profile**
171
+ 4. Click the **⋯** (three dots / more) button
172
+ 5. Click **Copy member ID**
173
+ 6. You'll get something like `U0AQW6P37N1`
174
+
175
+ Paste this into the **Allowed users** field.
176
+
177
+ ### Step 4 — Verify the Connection
178
+
179
+ 1. Go to the **Channels** tab in the Agent Fleet dashboard
180
+ 2. Your channel card should show a **green status dot** within a few seconds
181
+ 3. Status should say **connected**
182
+
183
+ **If the status is red**, open the Obsidian developer console (`Cmd+Opt+I` on Mac, `Ctrl+Shift+I` on Windows) and check for error messages:
184
+
185
+ | Error | Fix |
186
+ |-------|-----|
187
+ | `invalid_auth` | Wrong token — double-check both tokens in Settings |
188
+ | `not_enabled_for_socket_mode` | Go back to api.slack.com → Socket Mode → make sure it's ON |
189
+ | `missing_scope` | A required scope is missing — check Step 4 of Part 1 |
190
+ | `no_permission` | App wasn't reinstalled after adding scopes — reinstall in api.slack.com |
191
+
192
+ ---
193
+
194
+ ## Part 3: Start Chatting
195
+
196
+ ### Send Your First Message
197
+
198
+ 1. Open **Slack**
199
+ 2. Find your bot in the **Apps** section of the left sidebar (not Direct Messages — Agents & AI Apps moves the bot to Apps)
200
+ 3. Click on the bot → click **New chat** to start an assistant thread
201
+ 4. Type a message: `Hey, what can you do?`
202
+ 5. You should see:
203
+ - **"is thinking..."** indicator below the message composer
204
+ - A reply from the agent within 5-30 seconds
205
+
206
+ ### Switch Between Agents
207
+
208
+ If you configured multiple agents in `allowed_agents`, you can switch mid-conversation:
209
+
210
+ ```
211
+ @site-monitor: check if example.com is up
212
+ ```
213
+
214
+ The thread title updates to show the active agent. Each agent gets its own isolated Claude session — switching back and forth resumes where each left off.
215
+
216
+ ### List Available Agents
217
+
218
+ Type `/agents` in Slack. An ephemeral message (only visible to you) lists all agents configured for this channel.
219
+
220
+ ### Use the Bot in Channels
221
+
222
+ You can also invite the bot to Slack channels:
223
+
224
+ 1. Go to a channel (e.g., `#monitoring`)
225
+ 2. Type `/invite @Agent Fleet`
226
+ 3. Now anyone in the channel can mention the bot: `@Agent Fleet check the deployment status`
227
+
228
+ ---
229
+
230
+ ## Troubleshooting
231
+
232
+ ### Bot Doesn't Appear in Slack
233
+
234
+ - Make sure you completed Step 6 (Enable Messages Tab)
235
+ - The bot appears under **Apps** in the sidebar, not under **Direct Messages** (this is how Slack's Agents & AI Apps works)
236
+
237
+ ### Messages Are Silently Dropped
238
+
239
+ - Check that your Slack user ID is in the `allowed_users` list
240
+ - Empty `allowed_users` means NO ONE can reach the bot — add at least one user ID
241
+
242
+ ### "is thinking..." Indicator Doesn't Show
243
+
244
+ - Verify the `assistant:write` scope is added (Step 4 of Part 1)
245
+ - Make sure you **reinstalled the app** after adding scopes (Step 8)
246
+
247
+ ### Bot Stops Working When Obsidian Closes
248
+
249
+ This is expected. The Slack bot runs inside Obsidian via Socket Mode — when Obsidian is closed, the bot goes offline. Slack buffers messages briefly (~1 minute) during disconnects.
250
+
251
+ ### Token Rotation After Reinstall
252
+
253
+ Every time you reinstall the Slack app (required after scope changes), the **Bot Token (`xoxb-...`) rotates**. You must:
254
+ 1. Copy the new bot token from api.slack.com → Install App
255
+ 2. Update it in Obsidian → Settings → Agent Fleet → Channel Credentials (remove old, add new)
256
+
257
+ The **App Token (`xapp-...`) does NOT rotate** on reinstall — it stays the same.
258
+
259
+ ### Multiple Obsidian Instances
260
+
261
+ If you run the plugin on two machines pointed at the same Slack app, one will get kicked off the Socket Mode connection. Only one instance can be active per app token.
262
+
263
+ ---
264
+
265
+ ## Heartbeat → Slack Delivery
266
+
267
+ You can configure agents to post their heartbeat results to Slack automatically:
268
+
269
+ 1. Open the agent's edit page in the dashboard
270
+ 2. Scroll to the **Heartbeat** section
271
+ 3. Enable heartbeat and set a schedule
272
+ 4. Set **Post to channel** to your Slack channel name (e.g., `my-slack`)
273
+ 5. Write the heartbeat instruction
274
+ 6. Save
275
+
276
+ Every time the heartbeat runs, the result is posted to the Slack channel as a DM to the first user in the allowed list, prefixed with the agent's name.
277
+
278
+ ---
279
+
280
+ ## Security Notes
281
+
282
+ - **Credentials** are stored in the plugin's `data.json` inside your vault's `.obsidian` folder. If you sync `.obsidian` across devices, credentials sync too. Do not commit this file to a public git repository.
283
+ - **Allowed users** is checked against Slack's cryptographically signed sender field (Socket Mode envelopes). It cannot be spoofed.
284
+ - **Agents with `approval_required`** cannot be bound to channels — they would deadlock because Slack has no approval UI.
285
+ - **Rate limiting** (default 20 messages per 5 minutes per conversation) protects against accidental or hostile budget burn.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "obsidian-agent-fleet",
3
- "version": "0.4.2",
3
+ "version": "0.4.4",
4
4
  "description": "Obsidian plugin for file-backed AI agents, task scheduling, channels (Slack), heartbeat, and interactive chat.",
5
5
  "main": "plugin/main.js",
6
6
  "bin": {
@@ -11,13 +11,15 @@
11
11
  "plugin/main.js",
12
12
  "plugin/manifest.json",
13
13
  "plugin/styles.css",
14
- "README.md"
14
+ "README.md",
15
+ "SLACK_SETUP.md"
15
16
  ],
16
17
  "scripts": {
17
18
  "build": "node esbuild.config.mjs production",
18
19
  "dev": "node esbuild.config.mjs",
19
20
  "test": "vitest run",
20
- "typecheck": "tsc --noEmit"
21
+ "typecheck": "tsc --noEmit",
22
+ "postinstall": "node bin/cli.js install --auto || true"
21
23
  },
22
24
  "devDependencies": {
23
25
  "@types/node": "^24.5.2",
package/plugin/main.js CHANGED
@@ -3677,7 +3677,8 @@ var DEFAULT_SETTINGS = {
3677
3677
  maxConcurrentChannelSessions: 5,
3678
3678
  channelIdleTimeoutMinutes: 15,
3679
3679
  channelRateLimitPerConversation: 20,
3680
- channelRateLimitWindowMinutes: 5
3680
+ channelRateLimitWindowMinutes: 5,
3681
+ defaultFileHashes: {}
3681
3682
  };
3682
3683
  var FLEET_SUBFOLDERS = ["agents", "skills", "tasks", "runs", "memory", "channels"];
3683
3684
 
@@ -15425,6 +15426,14 @@ function asNumber(value, fallback) {
15425
15426
  function asStringArray(value) {
15426
15427
  return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
15427
15428
  }
15429
+ function simpleHash(str) {
15430
+ let hash = 0;
15431
+ for (let i = 0; i < str.length; i++) {
15432
+ const ch = str.charCodeAt(i);
15433
+ hash = (hash << 5) - hash + ch | 0;
15434
+ }
15435
+ return hash.toString(36);
15436
+ }
15428
15437
  var FleetRepository = class {
15429
15438
  constructor(vault, settings) {
15430
15439
  this.vault = vault;
@@ -15463,6 +15472,39 @@ var FleetRepository = class {
15463
15472
  await this.createFileIfMissing(fullPath, file.content);
15464
15473
  }
15465
15474
  }
15475
+ /**
15476
+ * Update default files that the user hasn't customized. For each default file:
15477
+ * - If missing on disk → write it and store the hash
15478
+ * - If on disk and hash matches stored hash → user hasn't touched it → overwrite
15479
+ * - If on disk and hash differs → user customized it → leave it alone
15480
+ *
15481
+ * Returns the updated hashes map so the caller can persist it to settings.
15482
+ */
15483
+ async updateDefaults(storedHashes) {
15484
+ const root = this.getFleetRoot();
15485
+ const updatedHashes = { ...storedHashes };
15486
+ for (const file of DEFAULT_FILES) {
15487
+ const fullPath = (0, import_obsidian2.normalizePath)(`${root}/${file.path}`);
15488
+ const newHash = simpleHash(file.content);
15489
+ const storedHash = storedHashes[file.path];
15490
+ if (storedHash === newHash) continue;
15491
+ const existing = this.vault.getAbstractFileByPath(fullPath);
15492
+ if (!(existing instanceof import_obsidian2.TFile)) {
15493
+ const parentDir = fullPath.substring(0, fullPath.lastIndexOf("/"));
15494
+ await this.ensureFolder(parentDir);
15495
+ await this.createFileIfMissing(fullPath, file.content);
15496
+ updatedHashes[file.path] = newHash;
15497
+ continue;
15498
+ }
15499
+ const currentContent = await this.vault.cachedRead(existing);
15500
+ const currentHash = simpleHash(currentContent);
15501
+ if (!storedHash || currentHash === storedHash) {
15502
+ await this.vault.modify(existing, file.content);
15503
+ updatedHashes[file.path] = newHash;
15504
+ }
15505
+ }
15506
+ return updatedHashes;
15507
+ }
15466
15508
  async loadAll() {
15467
15509
  this.agents.clear();
15468
15510
  this.skills.clear();
@@ -23054,7 +23096,7 @@ var FleetDashboardView = class extends import_obsidian12.ItemView {
23054
23096
  grid,
23055
23097
  "radio",
23056
23098
  "No channels configured",
23057
- "Create a file under _fleet/channels/ to wire an agent to Slack"
23099
+ "Connect an agent to Slack or another chat platform"
23058
23100
  );
23059
23101
  return;
23060
23102
  }
@@ -26848,6 +26890,11 @@ var AgentFleetPlugin = class extends import_obsidian14.Plugin {
26848
26890
  if (isFirstRun) {
26849
26891
  await this.repository.ensureSamples();
26850
26892
  }
26893
+ const updatedHashes = await this.repository.updateDefaults(this.settings.defaultFileHashes ?? {});
26894
+ if (JSON.stringify(updatedHashes) !== JSON.stringify(this.settings.defaultFileHashes ?? {})) {
26895
+ this.settings.defaultFileHashes = updatedHashes;
26896
+ await this.saveData(this.settings);
26897
+ }
26851
26898
  await this.runtime.initialize();
26852
26899
  await this.verifyClaudeCli(false);
26853
26900
  this.addRibbonIcon("bot", "Agent Fleet Dashboard", () => void this.activateDashboardView());
package/plugin/styles.css CHANGED
@@ -2242,6 +2242,8 @@
2242
2242
  justify-content: center;
2243
2243
  padding: 60px 20px;
2244
2244
  color: var(--af-text-muted);
2245
+ grid-column: 1 / -1;
2246
+ text-align: center;
2245
2247
  }
2246
2248
 
2247
2249
  .af-empty-icon {