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 +352 -167
- package/SLACK_SETUP.md +285 -0
- package/package.json +5 -3
- package/plugin/main.js +49 -2
- package/plugin/styles.css +2 -0
package/README.md
CHANGED
|
@@ -1,157 +1,288 @@
|
|
|
1
1
|
# Agent Fleet for Obsidian
|
|
2
2
|
|
|
3
|
-
**
|
|
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
|
|
5
|
+

|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
---
|
|
8
8
|
|
|
9
|
-
|
|
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
|
-
|
|
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
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
27
|
+
🧠 **Agent Memory** — Agents persist context across sessions using `[REMEMBER]` tags stored as markdown.
|
|
39
28
|
|
|
40
|
-
|
|
41
|
-
|
|
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 →
|
|
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
|
-
|
|
64
|
+
### First Launch
|
|
46
65
|
|
|
47
|
-
On first launch, Agent Fleet creates a `_fleet/` folder in your vault
|
|
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 (
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
83
|
-
|
|
84
|
-
|
|
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
|
-
|
|
88
|
-
|
|
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
|
-
|
|
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
|
-
|
|
160
|
+
---
|
|
94
161
|
|
|
95
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
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
|
-
**
|
|
121
|
-
-
|
|
122
|
-
-
|
|
123
|
-
- `
|
|
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
|
-
|
|
203
|
+
**Important:** Obsidian must be running for channels to work. When Obsidian is closed, the bot goes offline.
|
|
126
204
|
|
|
127
|
-
|
|
205
|
+
---
|
|
128
206
|
|
|
129
|
-
|
|
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
|
-
|
|
209
|
+
The chat panel is a first-class Obsidian view — dock it in the sidebar, center, or any split.
|
|
138
210
|
|
|
139
|
-
|
|
140
|
-
-
|
|
141
|
-
-
|
|
142
|
-
-
|
|
143
|
-
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
| `
|
|
172
|
-
| `
|
|
173
|
-
|
|
|
174
|
-
|
|
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
|
-
|
|
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
|
-
|
|
319
|
+
**Sidebar navigation:**
|
|
320
|
+
- Dashboard / Agents / Tasks Board / Run History / Approvals / Skills / MCP Servers / Channels
|
|
179
321
|
|
|
180
|
-
|
|
181
|
-
-
|
|
182
|
-
-
|
|
183
|
-
-
|
|
184
|
-
-
|
|
185
|
-
|
|
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
|
-
|
|
|
197
|
-
|
|
|
198
|
-
|
|
|
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
|
-
###
|
|
389
|
+
### Channel Settings
|
|
202
390
|
|
|
203
|
-
|
|
|
204
|
-
|
|
205
|
-
| `
|
|
206
|
-
| `
|
|
207
|
-
| `
|
|
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
|
-
|
|
397
|
+
### File Structure
|
|
398
|
+
|
|
399
|
+
All data lives in `_fleet/` as plain markdown:
|
|
211
400
|
|
|
212
401
|
```
|
|
213
|
-
|
|
214
|
-
├──
|
|
215
|
-
├──
|
|
216
|
-
├──
|
|
217
|
-
├──
|
|
218
|
-
├──
|
|
219
|
-
|
|
220
|
-
├──
|
|
221
|
-
|
|
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
|
-
|
|
413
|
+
Everything is searchable, version-controllable, and fully yours.
|
|
245
414
|
|
|
246
|
-
|
|
247
|
-
# Clone
|
|
248
|
-
git clone https://github.com/denberek/obsidian-agent-fleet.git
|
|
249
|
-
cd obsidian-agent-fleet
|
|
415
|
+
---
|
|
250
416
|
|
|
251
|
-
|
|
252
|
-
npm install
|
|
417
|
+
## FAQ
|
|
253
418
|
|
|
254
|
-
|
|
255
|
-
|
|
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
|
-
|
|
258
|
-
|
|
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
|
-
|
|
261
|
-
|
|
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
|
-
|
|
264
|
-
|
|
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
|
-
|
|
267
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
"
|
|
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());
|