@calltelemetry/openclaw-linear 0.7.1 → 0.8.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 CHANGED
@@ -3,348 +3,435 @@
3
3
  [![OpenClaw](https://img.shields.io/badge/OpenClaw-v2026.2+-blue)](https://github.com/calltelemetry/openclaw)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
5
5
 
6
- An OpenClaw plugin that connects Linear to AI agents. Issues get triaged automatically, agents respond to `@mentions`, and a worker-audit pipeline runs when you assign work -- with an inactivity watchdog that kills and respawns stuck sessions.
6
+ Connect Linear to AI agents. Issues get triaged, implemented, and audited automatically.
7
7
 
8
8
  ---
9
9
 
10
- ## Table of Contents
11
-
12
- - [Features](#features)
13
- - [How It Works](#how-it-works)
14
- - [Architecture](#architecture)
15
- - [Project Layout](#project-layout)
16
- - [Getting Started](#getting-started)
17
- - [Usage](#usage)
18
- - [Configuration](#configuration)
19
- - [Prompt Customization](#prompt-customization)
20
- - [Notifications](#notifications)
21
- - [Coding Tool](#coding-tool-code_run)
22
- - [Inactivity Watchdog](#inactivity-watchdog)
23
- - [CLI Reference](#cli-reference)
24
- - [Troubleshooting](#troubleshooting)
25
- - [License](#license)
10
+ ## What It Does
11
+
12
+ - **New issue?** Agent estimates story points, adds labels, sets priority.
13
+ - **Assign to agent?** A worker implements it, an independent auditor verifies it, done.
14
+ - **Comment `@qa review this`?** The QA agent responds with its expertise.
15
+ - **Say "plan this project"?** A planner interviews you and builds your full issue hierarchy.
16
+ - **Agent goes silent?** A watchdog kills it and retries automatically.
17
+ - **Want updates?** Get notified on Discord, Slack, Telegram, or Signal.
26
18
 
27
19
  ---
28
20
 
29
- ## Features
30
-
31
- | Feature | Description |
32
- |---------|-------------|
33
- | **Auto-triage** | New issues get story point estimates, labels, and priority automatically |
34
- | **@mention routing** | `@qa`, `@infra`, `@docs` in comments route to specialized agents |
35
- | **Worker-audit pipeline** | Assign an issue and a worker implements it, then an independent auditor verifies |
36
- | **Hard-enforced audit** | Audit triggers in plugin code, not as an LLM decision. Workers cannot self-certify. |
37
- | **Inactivity watchdog** | Kills agent sessions with no I/O, retries once, escalates on double failure |
38
- | **Branded replies** | Each agent posts with its own name and avatar in Linear |
39
- | **Real-time progress** | Agent activity (thinking, acting, responding) streams to Linear's UI |
40
- | **Unified `code_run`** | One tool, three backends (Codex, Claude Code, Gemini), configurable per agent |
41
- | **Issue management** | Agents use `linearis` CLI to update status, close issues, add comments |
42
- | **Project planner** | Interactive interview builds out Linear issue hierarchies with dependency DAGs |
43
- | **Customizable prompts** | `prompts.yaml` -- edit worker, audit, planner, and rework prompts without rebuilding |
44
- | **Multi-channel notifications** | Dispatch events fan out to Discord, Slack, Telegram, Signal, or any OpenClaw channel |
45
- | **Artifact logging** | Every dispatch writes structured logs to `.claw/` in the worktree |
21
+ ## Quick Start
46
22
 
47
- ---
23
+ ### 1. Install the plugin
48
24
 
49
- ## How It Works
50
-
51
- ```mermaid
52
- sequenceDiagram
53
- participant You
54
- participant Linear
55
- participant Plugin
56
- participant Agents
57
-
58
- You->>Linear: Create issue
59
- Linear->>Plugin: Webhook (Issue.create)
60
- Plugin->>Agents: Triage agent
61
- Agents-->>Plugin: Estimate + labels
62
- Plugin-->>Linear: Update issue
63
- Plugin-->>Linear: Post assessment
64
-
65
- You->>Linear: Assign to agent
66
- Linear->>Plugin: Webhook (Issue.update)
67
- Plugin->>Agents: Worker agent
68
- Agents-->>Linear: Streaming status
69
- Plugin->>Agents: Audit agent (automatic)
70
- Agents-->>Plugin: JSON verdict
71
- Plugin-->>Linear: Result comment
72
-
73
- You->>Linear: Comment "@qa review"
74
- Linear->>Plugin: Webhook (Comment)
75
- Plugin->>Agents: QA agent
76
- Agents-->>Plugin: Response
77
- Plugin-->>Linear: Branded comment
78
-
79
- You->>Linear: Comment "@ctclaw plan this project"
80
- Linear->>Plugin: Webhook (Comment)
81
- Plugin->>Agents: Planner agent
82
- Agents-->>Linear: Creates epics + issues + dependency DAG
83
- Agents-->>Linear: Interview question
25
+ ```bash
26
+ openclaw plugins install @calltelemetry/openclaw-linear
84
27
  ```
85
28
 
86
- ---
29
+ ### 2. Create a Linear OAuth app
87
30
 
88
- ## Architecture
31
+ Go to **Linear Settings > API > Applications** and create an app:
89
32
 
90
- ### Dispatch Pipeline (v2)
33
+ - Set **Webhook URL** to `https://your-domain.com/linear/webhook`
34
+ - Set **Redirect URI** to `https://your-domain.com/linear/oauth/callback`
35
+ - Enable events: **Agent Sessions**, **Comments**, **Issues**
36
+ - Save your **Client ID** and **Client Secret**
91
37
 
92
- When an issue is assigned, the plugin runs a multi-stage pipeline:
38
+ > You also need a **workspace webhook** (Settings > API > Webhooks) pointing to the same URL with Comment + Issue + User events enabled. Both webhooks are required.
93
39
 
94
- ```mermaid
95
- flowchart TD
96
- A[Issue Assigned] --> B["**DISPATCH**<br/>Tier assessment, worktree creation,<br/>state registration"]
97
- B --> C["**WORKER** *(sub-agent)*<br/>Plans + implements solution.<br/>Posts summary comment.<br/>CANNOT mark issue as Done."]
98
- C -->|"plugin code — automatic,<br/>not LLM-mediated"| D["**AUDIT** *(sub-agent)*<br/>Independent auditor reads issue body,<br/>verifies criteria, runs tests,<br/>returns JSON verdict."]
99
- D --> E["**VERDICT** *(plugin code)*"]
100
- E -->|PASS| F["Done + notify"]
101
- E -->|"FAIL ≤ max"| G["Rework (attempt++)"]
102
- G --> C
103
- E -->|"FAIL > max"| H["Stuck + escalate"]
40
+ ### 3. Set credentials
41
+
42
+ ```bash
43
+ export LINEAR_CLIENT_ID="your_client_id"
44
+ export LINEAR_CLIENT_SECRET="your_client_secret"
104
45
  ```
105
46
 
106
- ### Hard-Enforced vs. LLM-Mediated
47
+ For systemd services, add these to your unit file:
48
+
49
+ ```ini
50
+ [Service]
51
+ Environment=LINEAR_CLIENT_ID=your_client_id
52
+ Environment=LINEAR_CLIENT_SECRET=your_client_secret
53
+ ```
107
54
 
108
- | Layer | Mechanism | Can be skipped? |
109
- |-------|-----------|-----------------|
110
- | Worker spawn | Plugin code (`runAgent`) | No |
111
- | Audit trigger | Plugin code (fires after worker completes) | No |
112
- | Verdict processing | Plugin code (pass/fail/escalate) | No |
113
- | Inactivity watchdog | Plugin code (timer-based kill + retry) | No |
114
- | Worker implementation | LLM-mediated (agent decides how to code) | N/A |
115
- | Audit evaluation | LLM-mediated (agent decides if criteria are met) | N/A |
55
+ Then reload: `systemctl --user daemon-reload && systemctl --user restart openclaw-gateway`
116
56
 
117
- ### State Machine
57
+ ### 4. Authorize
118
58
 
119
- ```mermaid
120
- stateDiagram-v2
121
- [*] --> DISPATCHED
122
- DISPATCHED --> WORKING
123
- WORKING --> AUDITING
124
- AUDITING --> DONE
125
- AUDITING --> WORKING : FAIL (attempt++)
126
- WORKING --> STUCK : watchdog kill 2x
127
- AUDITING --> STUCK : attempt > max
59
+ ```bash
60
+ openclaw openclaw-linear auth
128
61
  ```
129
62
 
130
- All transitions use compare-and-swap (CAS) to prevent races. `dispatch-state.json` is the canonical source of truth.
63
+ This opens your browser. Approve the authorization, then restart:
131
64
 
132
- ### Project Planner Pipeline
65
+ ```bash
66
+ systemctl --user restart openclaw-gateway
67
+ ```
133
68
 
134
- When `@ctclaw plan this project` is commented on a root issue, the plugin enters planning mode:
69
+ ### 5. Verify
135
70
 
136
- ```mermaid
137
- flowchart TD
138
- A["Comment: 'plan this project'"] --> B["INITIATE<br/>Register session, post welcome"]
139
- B --> C["INTERVIEW<br/>Agent asks questions,<br/>creates issues + DAG"]
140
- C -->|user responds| C
141
- C -->|"'finalize plan'"| D["AUDIT<br/>DAG validation, completeness checks"]
142
- D -->|Pass| E["APPROVED<br/>Project ready for dispatch"]
143
- D -->|Fail| C
144
- C -->|"'abandon'"| F["ABANDONED"]
71
+ ```bash
72
+ openclaw openclaw-linear status
145
73
  ```
146
74
 
147
- During planning mode, the planner creates epics, sub-issues, and dependency relationships (`blocks`/`blocked_by`) via 5 dedicated tools. Issue dispatch is blocked for projects in planning mode.
75
+ You should see a valid token and connected status. Check the gateway logs for a clean startup:
76
+
77
+ ```
78
+ Linear agent extension registered (agent: default, token: profile, orchestration: enabled)
79
+ ```
148
80
 
149
- ### Webhook Event Router
81
+ Test the webhook endpoint:
150
82
 
151
- ```mermaid
152
- flowchart TD
153
- A["POST /linear/webhook"] --> B{"Event Type"}
154
- B --> C["AgentSessionEvent.created → Dispatch pipeline"]
155
- B --> D["AgentSessionEvent.prompted → Resume session"]
156
- B --> E["Comment.create → @mention routing<br/>or planning mode"]
157
- B --> F["Issue.create → Auto-triage"]
158
- B --> G["Issue.update → Dispatch if assigned"]
159
- B --> H["AppUserNotification → Direct response"]
83
+ ```bash
84
+ curl -s -X POST https://your-domain.com/linear/webhook \
85
+ -H "Content-Type: application/json" \
86
+ -d '{"type":"test","action":"ping"}'
87
+ # Returns: "ok"
160
88
  ```
161
89
 
162
- All handlers respond `200 OK` within 5 seconds (Linear requirement), then process asynchronously.
90
+ That's it. Create an issue in Linear and watch the agent respond.
163
91
 
164
- ### Two Webhook Systems
92
+ ---
165
93
 
166
- Linear delivers events through two separate webhook paths:
94
+ ## How It Works Step by Step
167
95
 
168
- 1. **Workspace webhook** (Settings > API > Webhooks) -- Comment, Issue, User events
169
- 2. **OAuth app webhook** (Settings > API > Applications) -- `AgentSessionEvent` (created/prompted)
96
+ Every issue moves through a clear pipeline. Here's exactly what happens at each stage and what you'll see in Linear.
170
97
 
171
- Both must point to: `https://<your-domain>/linear/webhook`
98
+ ```
99
+ ┌─────────┐ ┌──────────┐ ┌────────┐ ┌───────┐ ┌──────────┐
100
+ │ Triage │───▶│ Dispatch │───▶│ Worker │───▶│ Audit │───▶│ Done ✔ │
101
+ │(auto) │ │(you │ │(auto) │ │(auto) │ │ │
102
+ │ │ │ assign) │ │ │ │ │ └──────────┘
103
+ └─────────┘ └──────────┘ └────────┘ └───┬───┘
104
+
105
+ ┌─────────────┤
106
+ ▼ ▼
107
+ ┌──────────┐ ┌───────────────┐
108
+ │ Rework │ │ Needs Your │
109
+ │ (auto │ │ Help ⚠ │
110
+ │ retry) │ │ (escalated) │
111
+ └────┬─────┘ └───────────────┘
112
+
113
+ └──▶ back to Worker
114
+ ```
172
115
 
173
- ### Deduplication
116
+ ### Stage 1: Triage (automatic)
174
117
 
175
- A 60-second sliding window prevents double-handling:
118
+ **Trigger:** You create a new issue.
176
119
 
177
- | Key Pattern | Prevents |
178
- |---|---|
179
- | `session:{id}` | Same session processed by both Issue.update and AgentSessionEvent |
180
- | `comment:{id}` | Same comment webhook delivered twice |
181
- | `assigned:{issueId}:{viewerId}` | Rapid re-assignment events |
182
- | `issue-create:{id}` | Duplicate Issue.create webhooks |
120
+ The agent reads your issue, estimates story points, adds labels, sets priority, and posts an assessment comment — all within seconds.
183
121
 
184
- ---
122
+ **What you'll see in Linear:**
123
+
124
+ > **[Mal]** This looks like a medium complexity change — the search API integration touches both the backend GraphQL schema and the frontend query layer. I've estimated 3 points and tagged it `backend` + `frontend`.
125
+
126
+ The estimate, labels, and priority are applied silently to the issue fields. You don't need to do anything.
127
+
128
+ ### Stage 2: Dispatch (you assign the issue)
129
+
130
+ **Trigger:** You assign the issue to the agent (or it gets auto-assigned after planning).
131
+
132
+ The agent assesses complexity, picks an appropriate model, creates an isolated git worktree, and starts working.
133
+
134
+ **What you'll see in Linear:**
135
+
136
+ > **Dispatched** as **senior** (anthropic/claude-opus-4-6)
137
+ > > Complex multi-service refactor with migration concerns
138
+ >
139
+ > Worktree: `/home/claw/worktrees/ENG-100` (fresh)
140
+ > Branch: `codex/ENG-100`
141
+ >
142
+ > **Status:** Worker is starting now. An independent audit runs automatically after implementation.
143
+ >
144
+ > **While you wait:**
145
+ > - Check progress: `/dispatch status ENG-100`
146
+ > - Cancel: `/dispatch escalate ENG-100 "reason"`
147
+ > - All dispatches: `/dispatch list`
148
+
149
+ **Complexity tiers:**
150
+
151
+ | Tier | Model | When |
152
+ |---|---|---|
153
+ | Junior | claude-haiku-4-5 | Simple config changes, typos, one-file fixes |
154
+ | Medior | claude-sonnet-4-6 | Standard features, multi-file changes |
155
+ | Senior | claude-opus-4-6 | Complex refactors, architecture changes |
156
+
157
+ ### Stage 3: Implementation (automatic)
158
+
159
+ The worker agent reads the issue, plans its approach, writes code, and runs tests — all in the isolated worktree. You don't need to do anything during this stage.
160
+
161
+ If this is a **retry** after a failed audit, the worker gets the previous audit feedback as context so it knows exactly what to fix.
162
+
163
+ **Notifications you'll receive:**
164
+ > `ENG-100 working on it (attempt 1)`
165
+
166
+ ### Stage 4: Audit (automatic)
167
+
168
+ After the worker finishes, a separate auditor agent independently verifies the work. The auditor checks the issue requirements against what was actually implemented.
169
+
170
+ This is **not optional** — the worker cannot mark its own work as done. The audit is triggered by the plugin, not by the AI.
171
+
172
+ **Notifications you'll receive:**
173
+ > `ENG-100 checking the work...`
174
+
175
+ ### Stage 5: Verdict
176
+
177
+ The audit produces one of three outcomes:
178
+
179
+ #### Pass — Issue is done
180
+
181
+ The issue is marked done automatically. A summary is posted.
182
+
183
+ **What you'll see in Linear:**
184
+
185
+ > ## Done
186
+ >
187
+ > This issue has been implemented and verified.
188
+ >
189
+ > **What was checked:**
190
+ > - API endpoint returns correct response format
191
+ > - Tests pass for edge cases
192
+ > - Error handling covers timeout scenarios
193
+ >
194
+ > **Test results:** 14 tests passed, 0 failed
195
+ >
196
+ > ---
197
+ > *Completed on attempt 1. Artifacts: `/home/claw/worktrees/ENG-100/.claw/`*
198
+
199
+ **Notification:** `✅ ENG-100 done! Ready for review.`
200
+
201
+ #### Fail (retries left) — Automatic rework
202
+
203
+ The worker gets the audit feedback and tries again. You don't need to do anything.
204
+
205
+ **What you'll see in Linear:**
206
+
207
+ > ## Needs More Work
208
+ >
209
+ > The implementation was checked and some things need to be addressed. Retrying automatically.
210
+ >
211
+ > **Attempt 1 of 3**
212
+ >
213
+ > **What needs fixing:**
214
+ > - Missing input validation on the search endpoint
215
+ > - No test for empty query string
216
+ >
217
+ > **Test results:** 12 passed, 2 failed
218
+
219
+ **Notification:** `ENG-100 needs more work (attempt 1). Issues: missing validation, no empty query test`
220
+
221
+ #### Fail (no retries left) — Needs your help
222
+
223
+ After all retries are exhausted (default: 3 attempts), the issue is escalated to you.
224
+
225
+ **What you'll see in Linear:**
226
+
227
+ > ## Needs Your Help
228
+ >
229
+ > The automatic retries didn't fix these issues:
230
+ >
231
+ > **What went wrong:**
232
+ > - Search pagination still returns duplicate results
233
+ > - Integration test flaky on CI
234
+ >
235
+ > **Test results:** 10 passed, 4 failed
236
+ >
237
+ > ---
238
+ > *Please review and either:*
239
+ > - *Update the issue description with clearer requirements, then re-assign*
240
+ > - *Fix the issues manually in the worktree at `/home/claw/worktrees/ENG-100`*
241
+
242
+ **Notification:** `🚨 ENG-100 needs your help — couldn't fix it after 3 tries`
243
+
244
+ **What you can do:**
245
+ 1. **Clarify the issue** — Add more detail to the description, then re-assign to try again
246
+ 2. **Fix it yourself** — The agent's work is in the worktree, ready to edit
247
+ 3. **Force retry** — `/dispatch retry ENG-100`
248
+ 4. **Check logs** — Worker output in `.claw/worker-*.md`, audit verdicts in `.claw/audit-*.json`
249
+
250
+ ### Stage 6: Timeout (if the agent goes silent)
251
+
252
+ If the agent produces no output for 2 minutes (configurable), the watchdog kills it and retries once. If the retry also times out, the issue is escalated.
253
+
254
+ **What you'll see in Linear:**
255
+
256
+ > ## Agent Timed Out
257
+ >
258
+ > The agent stopped responding for over 120s and was automatically restarted, but the retry also failed.
259
+ >
260
+ > **What to do:** Re-assign this issue to try again. If it keeps timing out, the issue might be too complex — try breaking it into smaller issues.
261
+
262
+ **Notification:** `⚡ ENG-100 timed out (no activity for 120s). Will retry.`
263
+
264
+ ### What's in the worktree
185
265
 
186
- ## Project Layout
187
-
188
- ```
189
- openclaw-linear/
190
- |-- index.ts Plugin entry point, route/hook/service registration
191
- |-- openclaw.plugin.json Plugin metadata and config schema
192
- |-- prompts.yaml Externalized worker/audit/rework prompt templates
193
- |-- coding-tools.json Backend config (default tool, per-agent overrides)
194
- |-- package.json
195
- |-- README.md
196
- |-- docs/
197
- | |-- architecture.md Internal architecture reference
198
- | +-- troubleshooting.md Diagnostic commands and common issues
199
- +-- src/
200
- |-- pipeline/ Core dispatch lifecycle
201
- | |-- webhook.ts Event router -- 6 webhook handlers, dispatch logic
202
- | |-- pipeline.ts v2 pipeline: spawnWorker, triggerAudit, processVerdict
203
- | |-- dispatch-state.ts File-backed state, CAS transitions, session mapping
204
- | |-- dispatch-service.ts Background monitor: stale detection, recovery, cleanup
205
- | |-- active-session.ts In-memory session registry (issueId -> session)
206
- | |-- tier-assess.ts Issue complexity assessment (junior/medior/senior)
207
- | |-- artifacts.ts .claw/ directory: manifest, logs, verdicts, summaries
208
- | |-- planner.ts Project planner orchestration (interview, audit)
209
- | +-- planning-state.ts File-backed planning state (mirrors dispatch-state)
210
- |
211
- |-- agent/ Agent execution & monitoring
212
- | |-- agent.ts Embedded runner + subprocess fallback, retry on watchdog kill
213
- | +-- watchdog.ts InactivityWatchdog class + per-agent config resolver
214
- |
215
- |-- tools/ Tool registration & CLI backends
216
- | |-- tools.ts Tool registration (code_run + orchestration)
217
- | |-- code-tool.ts Unified code_run dispatcher
218
- | |-- cli-shared.ts Shared helpers (buildLinearApi, resolveSession, defaults)
219
- | |-- claude-tool.ts Claude Code CLI runner (JSONL -> Linear activities)
220
- | |-- codex-tool.ts Codex CLI runner (JSONL -> Linear activities)
221
- | |-- gemini-tool.ts Gemini CLI runner (JSONL -> Linear activities)
222
- | |-- orchestration-tools.ts spawn_agent / ask_agent for multi-agent delegation
223
- | +-- planner-tools.ts 5 planning tools (create/link/update issues, audit DAG)
224
- |
225
- |-- api/ Linear API & auth
226
- | |-- linear-api.ts GraphQL client, token resolution, auto-refresh
227
- | |-- auth.ts OAuth provider registration
228
- | +-- oauth-callback.ts HTTP handler for OAuth redirect
229
- |
230
- +-- infra/ Infrastructure utilities
231
- |-- cli.ts CLI subcommands (auth, status, worktrees, prompts)
232
- |-- codex-worktree.ts Git worktree create/remove/status/PR helpers
233
- +-- notify.ts Multi-channel notifier (Discord, Slack, Telegram, Signal)
266
+ Every dispatch creates a `.claw/` folder inside the worktree with everything the agent did:
267
+
268
+ ```
269
+ /home/claw/worktrees/ENG-100/
270
+ ├── .claw/
271
+ │ ├── manifest.json # Issue metadata, tier, status, attempt count
272
+ │ ├── worker-0.md # What the worker did on attempt 1
273
+ │ ├── worker-1.md # What the worker did on attempt 2 (if retried)
274
+ │ ├── audit-0.json # Audit verdict for attempt 1
275
+ │ ├── audit-1.json # Audit verdict for attempt 2
276
+ │ ├── log.jsonl # Timeline of every phase with timing
277
+ └── summary.md # Final summary (written on done or stuck)
278
+ ├── src/ # your code, modified by the agent
279
+ ├── tests/
280
+ └── ...
234
281
  ```
235
282
 
283
+ If something went wrong, start with `log.jsonl` — it shows every phase, how long it took, and a preview of the output.
284
+
236
285
  ---
237
286
 
238
- ## Getting Started
287
+ ## Planning a Project
239
288
 
240
- ### Prerequisites
289
+ For larger work, the planner helps you break a project into issues with dependencies, then dispatches them automatically.
241
290
 
242
- - **OpenClaw** gateway running (v2026.2+)
243
- - **Linear** workspace with API access
244
- - **Public URL** for webhook delivery (Cloudflare Tunnel recommended)
245
- - **Coding CLIs** (at least one): `codex`, `claude`, `gemini` -- installed in PATH
246
- - **linearis** CLI -- for issue management
291
+ ### Start planning
247
292
 
248
- ### 1. Install the Plugin
293
+ Comment on any issue that belongs to a Linear project:
249
294
 
250
- ```bash
251
- openclaw plugins install @calltelemetry/openclaw-linear
252
- ```
295
+ > `@ctclaw plan this project`
253
296
 
254
- ### 2. Create a Linear OAuth App
297
+ The planner enters **interview mode** and asks you questions:
255
298
 
256
- Go to **Linear Settings > API > Applications** and create a new application:
299
+ > Entering planning mode for **Search Feature**. What are the main feature areas you'd like to build?
257
300
 
258
- - **Webhook URL:** `https://<your-domain>/linear/webhook`
259
- - **Redirect URI:** `https://<your-domain>/linear/oauth/callback`
260
- - Enable webhook events: **Agent Sessions**, **Comments**, **Issues**
301
+ ### Build the plan
261
302
 
262
- Save the **Client ID** and **Client Secret**.
303
+ Reply with your ideas. The planner creates issues, sets dependencies, and asks follow-up questions:
263
304
 
264
- ### 3. Set Credentials
305
+ > I've created 3 issues:
306
+ > - **PROJ-2:** Build search API endpoint (3 pts, blocks PROJ-3)
307
+ > - **PROJ-3:** Search results page (2 pts, blocked by PROJ-2)
308
+ > - **PROJ-4:** Autocomplete suggestions (1 pt, independent)
309
+ >
310
+ > Should the autocomplete call a separate endpoint or share the search API?
265
311
 
266
- Add to your gateway environment or plugin config:
312
+ Keep replying until the plan looks right. The planner updates issues in real time.
267
313
 
268
- ```bash
269
- export LINEAR_CLIENT_ID="your_client_id"
270
- export LINEAR_CLIENT_SECRET="your_client_secret"
271
- ```
314
+ ### Finalize
272
315
 
273
- For systemd:
316
+ When you're happy with the plan, comment:
274
317
 
275
- ```ini
276
- [Service]
277
- Environment=LINEAR_CLIENT_ID=your_client_id
278
- Environment=LINEAR_CLIENT_SECRET=your_client_secret
279
- ```
318
+ > `finalize plan`
280
319
 
281
- Then reload: `systemctl --user daemon-reload && systemctl --user restart openclaw-gateway`
320
+ The planner runs a validation check:
321
+ - Every issue has a description (50+ characters)
322
+ - Every issue has an estimate
323
+ - Every issue has a priority
324
+ - No circular dependencies
282
325
 
283
- ### 4. Expose the Gateway
326
+ **If validation passes:**
284
327
 
285
- Linear needs HTTPS access to deliver webhooks. [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/) is recommended.
328
+ > ## Plan Approved
329
+ >
330
+ > The plan for **Search Feature** passed all checks.
331
+ > **3 issues** created with valid dependency graph.
286
332
 
287
- ```bash
288
- # Install cloudflared
289
- sudo dnf install -y cloudflared # RHEL/Rocky/Alma
333
+ The project enters **DAG dispatch mode** — issues are assigned to the agent automatically, respecting dependency order. Up to 3 issues run in parallel. As each completes, newly unblocked issues start.
290
334
 
291
- # Create and configure tunnel
292
- cloudflared tunnel login
293
- cloudflared tunnel create openclaw
294
- cloudflared tunnel route dns openclaw linear.yourdomain.com
295
- ```
335
+ **If validation fails:**
296
336
 
297
- Create `~/.cloudflared/config.yml`:
337
+ > ## Plan Audit Failed
338
+ >
339
+ > **Problems:**
340
+ > - PROJ-2: description too short (< 50 chars)
341
+ > - PROJ-3: missing estimate
342
+ >
343
+ > Please address these issues, then say "finalize plan" again.
298
344
 
299
- ```yaml
300
- tunnel: <TUNNEL_ID>
301
- credentials-file: ~/.cloudflared/<TUNNEL_ID>.json
345
+ Fix the issues and try again. You can also say `abandon planning` to exit without dispatching.
302
346
 
303
- ingress:
304
- - hostname: linear.yourdomain.com
305
- service: http://localhost:18789
306
- - service: http_status:404
307
- ```
347
+ ### DAG dispatch progress
308
348
 
309
- Start the tunnel:
349
+ As issues complete, you'll get progress notifications:
310
350
 
311
- ```bash
312
- sudo cloudflared service install
313
- sudo systemctl enable --now cloudflared
314
- ```
351
+ > `📊 Search Feature: 2/3 complete`
315
352
 
316
- Verify:
353
+ When everything is done:
317
354
 
318
- ```bash
319
- curl -s https://linear.yourdomain.com/linear/webhook \
320
- -X POST -H "Content-Type: application/json" \
321
- -d '{"type":"test","action":"ping"}'
322
- # Should return: "ok"
323
- ```
355
+ > `✅ Search Feature: complete (3/3 issues)`
324
356
 
325
- ### 5. Authorize with Linear
357
+ If an issue gets stuck (all retries failed), dependent issues are blocked and you'll be notified.
326
358
 
327
- ```bash
328
- openclaw openclaw-linear auth
329
- ```
359
+ ---
330
360
 
331
- This opens your browser to authorize the agent. Then restart and verify:
361
+ ## Quick Reference
332
362
 
333
- ```bash
334
- systemctl --user restart openclaw-gateway
335
- openclaw openclaw-linear status
363
+ | What you do in Linear | What happens |
364
+ |---|---|
365
+ | Create a new issue | Agent triages — adds estimate, labels, priority |
366
+ | Assign an issue to the agent | Worker → Audit → Done (or retry, or escalate) |
367
+ | Comment `@qa check the tests` | QA agent responds |
368
+ | Comment `@ctclaw plan this project` | Planning interview starts |
369
+ | Reply during planning | Issues created/updated, follow-up questions |
370
+ | Comment `finalize plan` | Validates, then auto-dispatches |
371
+ | Comment `abandon planning` | Exits planning mode |
372
+ | `/dispatch list` | Shows all active dispatches |
373
+ | `/dispatch retry CT-123` | Re-runs a stuck dispatch |
374
+ | `/dispatch status CT-123` | Detailed dispatch info |
375
+ | Add `<!-- repos: api, frontend -->` to issue body | Multi-repo dispatch |
376
+
377
+ ---
378
+
379
+ ## Configuration
380
+
381
+ Add settings under the plugin entry in `openclaw.json`:
382
+
383
+ ```json
384
+ {
385
+ "plugins": {
386
+ "entries": {
387
+ "openclaw-linear": {
388
+ "config": {
389
+ "defaultAgentId": "coder",
390
+ "maxReworkAttempts": 2,
391
+ "enableAudit": true
392
+ }
393
+ }
394
+ }
395
+ }
396
+ }
336
397
  ```
337
398
 
338
- ### 6. Configure Agents
399
+ ### Plugin Settings
400
+
401
+ | Key | Type | Default | What it does |
402
+ |---|---|---|---|
403
+ | `defaultAgentId` | string | `"default"` | Which agent runs the pipeline |
404
+ | `enableAudit` | boolean | `true` | Run auditor after implementation |
405
+ | `enableOrchestration` | boolean | `true` | Allow `spawn_agent` / `ask_agent` tools |
406
+ | `maxReworkAttempts` | number | `2` | Max audit failures before escalation |
407
+ | `codexBaseRepo` | string | `"/home/claw/ai-workspace"` | Git repo for worktrees |
408
+ | `worktreeBaseDir` | string | `"~/.openclaw/worktrees"` | Where worktrees are created |
409
+ | `repos` | object | — | Multi-repo map (see [Multi-Repo](#multi-repo)) |
410
+ | `dispatchStatePath` | string | `"~/.openclaw/linear-dispatch-state.json"` | Dispatch state file |
411
+ | `promptsPath` | string | — | Custom prompts file path |
412
+ | `notifications` | object | — | Notification targets (see [Notifications](#notifications)) |
413
+ | `inactivitySec` | number | `120` | Kill agent if silent this long |
414
+ | `maxTotalSec` | number | `7200` | Max total agent session time |
415
+ | `toolTimeoutSec` | number | `600` | Max single `code_run` time |
416
+
417
+ ### Environment Variables
418
+
419
+ | Variable | Required | What it does |
420
+ |---|---|---|
421
+ | `LINEAR_CLIENT_ID` | Yes | OAuth app client ID |
422
+ | `LINEAR_CLIENT_SECRET` | Yes | OAuth app client secret |
423
+ | `LINEAR_API_KEY` | No | Personal API key (fallback) |
339
424
 
340
- Create `~/.openclaw/agent-profiles.json`:
425
+ ### Agent Profiles
426
+
427
+ Define your agents in `~/.openclaw/agent-profiles.json`:
341
428
 
342
429
  ```json
343
430
  {
344
431
  "agents": {
345
432
  "coder": {
346
433
  "label": "Coder",
347
- "mission": "Full-stack engineer. Plans, implements, and ships code.",
434
+ "mission": "Full-stack engineer. Plans, implements, ships.",
348
435
  "isDefault": true,
349
436
  "mentionAliases": ["coder"],
350
437
  "avatarUrl": "https://example.com/coder.png",
@@ -356,23 +443,18 @@ Create `~/.openclaw/agent-profiles.json`:
356
443
  },
357
444
  "qa": {
358
445
  "label": "QA",
359
- "mission": "Test engineer. Quality guardian, test strategy.",
360
- "mentionAliases": ["qa", "tester"],
361
- "watchdog": {
362
- "inactivitySec": 120,
363
- "maxTotalSec": 3600,
364
- "toolTimeoutSec": 600
365
- }
446
+ "mission": "Test engineer. Reviews code, writes tests.",
447
+ "mentionAliases": ["qa", "tester"]
366
448
  }
367
449
  }
368
450
  }
369
451
  ```
370
452
 
371
- Each agent name must match an agent in `~/.openclaw/openclaw.json`. One agent must have `isDefault: true` -- this agent handles issue assignments and the dispatch pipeline.
453
+ One agent must have `"isDefault": true` that's the one that handles triage and the dispatch pipeline.
372
454
 
373
- ### 7. Configure Coding Tools
455
+ ### Coding Tools
374
456
 
375
- Create `coding-tools.json` in the plugin root:
457
+ Create `coding-tools.json` in the plugin root to configure which CLI backend agents use:
376
458
 
377
459
  ```json
378
460
  {
@@ -386,166 +468,125 @@ Create `coding-tools.json` in the plugin root:
386
468
  }
387
469
  ```
388
470
 
389
- ### 8. Install linearis
471
+ The agent calls `code_run` without knowing which backend is active. Resolution order: explicit `backend` parameter > per-agent override > global default > `"claude"`.
390
472
 
391
- ```bash
392
- npm install -g linearis
393
- npx clawhub install linearis
394
- echo "lin_api_YOUR_KEY" > ~/.linear_api_token
395
- ```
396
-
397
- ### 9. Verify
398
-
399
- ```bash
400
- systemctl --user restart openclaw-gateway
401
- ```
473
+ ---
402
474
 
403
- Check logs for a clean startup:
475
+ ## Notifications
404
476
 
405
- ```
406
- [plugins] Linear agent extension registered (agent: default, token: profile,
407
- codex: codex-cli 0.101.0, claude: 2.1.45, gemini: 0.28.2, orchestration: enabled)
408
- ```
477
+ Get notified when dispatches start, pass audit, fail, or get stuck.
409
478
 
410
- Test the webhook:
479
+ ### Setup
411
480
 
412
- ```bash
413
- curl -s -X POST https://your-domain.com/linear/webhook \
414
- -H "Content-Type: application/json" \
415
- -d '{"type":"test","action":"ping"}'
416
- # Should return: "ok"
481
+ ```json
482
+ {
483
+ "notifications": {
484
+ "targets": [
485
+ { "channel": "discord", "target": "1471743433566715974" },
486
+ { "channel": "telegram", "target": "-1003884997363" },
487
+ { "channel": "slack", "target": "C0123456789", "accountId": "my-acct" }
488
+ ],
489
+ "events": {
490
+ "auditing": false
491
+ },
492
+ "richFormat": true
493
+ }
494
+ }
417
495
  ```
418
496
 
419
- ---
420
-
421
- ## Usage
497
+ - **`targets`** — Where to send notifications (channel name + ID)
498
+ - **`events`** — Toggle specific events off (all on by default)
499
+ - **`richFormat`** — Set to `true` for Discord embeds with colors and Telegram HTML formatting
422
500
 
423
- Once set up, the plugin responds to Linear events automatically:
501
+ ### Events
424
502
 
425
- | What you do in Linear | What happens |
503
+ | Event | When it fires |
426
504
  |---|---|
427
- | Create a new issue | Agent triages it (estimate, labels, priority) and posts an assessment |
428
- | Assign an issue to the agent | Worker-audit pipeline runs with watchdog protection |
429
- | Trigger an agent session | Agent responds directly in the session |
430
- | Comment `@qa check the tests` | QA agent responds with its expertise |
431
- | Comment `@ctclaw plan this project` | Planner agent enters interview mode, builds issue DAG |
432
- | Reply during planning mode | Planner creates/updates issues and asks next question |
433
- | Comment "finalize plan" | DAG audit runs: cycles, orphans, missing estimates/priorities |
434
- | Ask "close this issue" | Agent runs `linearis issues update API-123 --status Done` |
435
- | Ask "use gemini to review" | Agent calls `code_run` with `backend: "gemini"` |
436
-
437
- ### Pipeline Behavior
438
-
439
- When an issue is assigned:
505
+ | `dispatch` | Issue dispatched to pipeline |
506
+ | `working` | Worker started |
507
+ | `auditing` | Audit in progress |
508
+ | `audit_pass` | Audit passed, issue done |
509
+ | `audit_fail` | Audit failed, worker retrying |
510
+ | `escalation` | Too many failures, needs human |
511
+ | `stuck` | Dispatch stale for 2+ hours |
512
+ | `watchdog_kill` | Agent killed for inactivity |
440
513
 
441
- 1. **Tier assessment** -- Evaluates complexity (junior/medior/senior), selects model tier
442
- 2. **Worktree creation** -- Isolated git worktree for the implementation
443
- 3. **Worker runs** -- Worker agent plans and implements, posts summary comment
444
- 4. **Audit runs** -- Independent auditor verifies against issue body, returns JSON verdict
445
- 5. **Verdict** -- Pass: issue done. Fail: worker re-spawns with gaps (up to `maxReworkAttempts`). Too many failures: stuck + escalation notification.
446
- 6. **Watchdog** -- If the worker goes silent (no I/O), the watchdog kills it and retries once. Double failure escalates to stuck.
514
+ ### Test It
447
515
 
448
- Workers **cannot** mark issues as done -- that's handled entirely by plugin verdict processing code.
516
+ ```bash
517
+ openclaw openclaw-linear notify test # Test all targets
518
+ openclaw openclaw-linear notify test --channel discord # Test one channel
519
+ openclaw openclaw-linear notify status # Show config
520
+ ```
449
521
 
450
522
  ---
451
523
 
452
- ## Configuration
524
+ ## Prompt Customization
453
525
 
454
- ### Plugin Config
526
+ Worker, audit, and rework prompts live in `prompts.yaml`. You can customize them without rebuilding.
455
527
 
456
- Set in `openclaw.json` under the plugin entry:
528
+ ### Three Layers
457
529
 
458
- | Key | Type | Default | Description |
459
- |---|---|---|---|
460
- | `defaultAgentId` | string | `"default"` | Agent ID for pipeline workers and audit |
461
- | `enableAudit` | boolean | `true` | Run auditor stage after implementation |
462
- | `enableOrchestration` | boolean | `true` | Allow `spawn_agent`/`ask_agent` tools |
463
- | `codexBaseRepo` | string | `"/home/claw/ai-workspace"` | Git repo for worktrees |
464
- | `codexModel` | string | -- | Default Codex model |
465
- | `codexTimeoutMs` | number | `600000` | Legacy timeout for coding CLIs (ms) |
466
- | `worktreeBaseDir` | string | `"~/.openclaw/worktrees"` | Base directory for worktrees |
467
- | `dispatchStatePath` | string | `"~/.openclaw/linear-dispatch-state.json"` | Dispatch state file |
468
- | `notifications` | object | -- | [Notification targets and event toggles](#notifications) |
469
- | `promptsPath` | string | -- | Override path for `prompts.yaml` |
470
- | `maxReworkAttempts` | number | `2` | Max audit failures before escalation |
471
- | `inactivitySec` | number | `120` | Kill sessions with no I/O for this long |
472
- | `maxTotalSec` | number | `7200` | Max total agent session runtime |
473
- | `toolTimeoutSec` | number | `600` | Max runtime for a single `code_run` invocation |
530
+ Prompts merge in this order (later layers override earlier ones):
474
531
 
475
- ### Environment Variables
532
+ 1. **Built-in defaults** — Ship with the plugin, always available
533
+ 2. **Your global file** — Set `promptsPath` in config to point to your custom YAML
534
+ 3. **Per-project file** — Drop a `prompts.yaml` in the worktree's `.claw/` folder
476
535
 
477
- | Variable | Required | Description |
478
- |---|---|---|
479
- | `LINEAR_CLIENT_ID` | Yes | OAuth app client ID |
480
- | `LINEAR_CLIENT_SECRET` | Yes | OAuth app client secret |
481
- | `LINEAR_API_KEY` | No | Personal API key (fallback if no OAuth) |
482
- | `LINEAR_REDIRECT_URI` | No | Override the OAuth callback URL |
483
- | `OPENCLAW_GATEWAY_PORT` | No | Gateway port (default: 18789) |
536
+ Each layer only overrides the specific sections you define. Everything else keeps its default.
484
537
 
485
- ### Agent Profile Fields
538
+ ### Example Custom Prompts
486
539
 
487
- | Field | Required | Description |
488
- |---|---|---|
489
- | `label` | Yes | Display name on Linear comments |
490
- | `mission` | Yes | Role description (injected as context) |
491
- | `isDefault` | One agent | Handles triage and the dispatch pipeline |
492
- | `mentionAliases` | Yes | `@mention` triggers (e.g., `["qa", "tester"]`) |
493
- | `avatarUrl` | No | Avatar URL for branded comments |
494
- | `watchdog.inactivitySec` | No | Inactivity kill threshold (default: 120) |
495
- | `watchdog.maxTotalSec` | No | Max total session runtime (default: 7200) |
496
- | `watchdog.toolTimeoutSec` | No | Max single `code_run` runtime (default: 600) |
540
+ ```yaml
541
+ worker:
542
+ system: "You are a senior engineer. Write clean, tested code."
543
+ task: |
544
+ Issue: {{identifier}} {{title}}
497
545
 
498
- ---
546
+ {{description}}
499
547
 
500
- ## Prompt Customization
548
+ Workspace: {{worktreePath}}
501
549
 
502
- Worker, audit, and rework prompts live in `prompts.yaml`. Edit to customize without rebuilding.
550
+ Implement this issue. Write tests. Commit your work.
503
551
 
504
- ### Managing Prompts
552
+ audit:
553
+ system: "You are a strict code auditor."
505
554
 
506
- ```bash
507
- openclaw openclaw-linear prompts show # Print current prompts.yaml
508
- openclaw openclaw-linear prompts path # Print resolved file path
509
- openclaw openclaw-linear prompts validate # Validate structure and template variables
555
+ rework:
556
+ addendum: |
557
+ PREVIOUS AUDIT FAILED. Fix these gaps:
558
+ {{gaps}}
510
559
  ```
511
560
 
512
561
  ### Template Variables
513
562
 
514
- | Variable | Description |
563
+ | Variable | What it contains |
515
564
  |---|---|
516
- | `{{identifier}}` | Issue identifier (e.g., `API-123`) |
565
+ | `{{identifier}}` | Issue ID (e.g., `API-123`) |
517
566
  | `{{title}}` | Issue title |
518
567
  | `{{description}}` | Full issue body |
519
568
  | `{{worktreePath}}` | Path to the git worktree |
520
- | `{{tier}}` | Assessed complexity tier |
521
- | `{{attempt}}` | Current attempt number (0-based) |
522
- | `{{gaps}}` | Audit gaps from previous attempt (rework only) |
569
+ | `{{tier}}` | Complexity tier (junior/medior/senior) |
570
+ | `{{attempt}}` | Current attempt number |
571
+ | `{{gaps}}` | Audit gaps from previous attempt |
523
572
 
524
- ### Override Path
573
+ ### CLI
525
574
 
526
- ```json
527
- {
528
- "plugins": {
529
- "entries": {
530
- "openclaw-linear": {
531
- "config": {
532
- "promptsPath": "/path/to/my/prompts.yaml"
533
- }
534
- }
535
- }
536
- }
537
- }
575
+ ```bash
576
+ openclaw openclaw-linear prompts show # View current prompts
577
+ openclaw openclaw-linear prompts path # Show file path
578
+ openclaw openclaw-linear prompts validate # Check for errors
538
579
  ```
539
580
 
540
581
  ---
541
582
 
542
- ## Notifications
583
+ ## Multi-Repo
543
584
 
544
- Dispatch lifecycle events fan out to any combination of OpenClaw channels -- Discord, Slack, Telegram, Signal, or any channel the runtime supports.
585
+ Sometimes a feature touches more than one repo your API and your frontend, for example. Multi-repo lets the agent work on both at the same time, in separate worktrees.
545
586
 
546
- ### Configuration
587
+ ### Step 1: Tell the plugin where your repos live
547
588
 
548
- Add a `notifications` object to your plugin config:
589
+ Add a `repos` map to your plugin config in `openclaw.json`. The **key** is a short name you pick, the **value** is the absolute path to that repo on disk:
549
590
 
550
591
  ```json
551
592
  {
@@ -553,15 +594,10 @@ Add a `notifications` object to your plugin config:
553
594
  "entries": {
554
595
  "openclaw-linear": {
555
596
  "config": {
556
- "notifications": {
557
- "targets": [
558
- { "channel": "discord", "target": "1471743433566715974" },
559
- { "channel": "slack", "target": "C0123456789", "accountId": "my-acct" },
560
- { "channel": "telegram", "target": "-1003884997363" }
561
- ],
562
- "events": {
563
- "auditing": false
564
- }
597
+ "repos": {
598
+ "api": "/home/claw/repos/api",
599
+ "frontend": "/home/claw/repos/frontend",
600
+ "shared": "/home/claw/repos/shared-libs"
565
601
  }
566
602
  }
567
603
  }
@@ -570,162 +606,281 @@ Add a `notifications` object to your plugin config:
570
606
  }
571
607
  ```
572
608
 
573
- **`targets`** -- Array of notification destinations. Each target specifies:
609
+ Restart the gateway after saving: `systemctl --user restart openclaw-gateway`
574
610
 
575
- | Field | Required | Description |
576
- |---|---|---|
577
- | `channel` | Yes | OpenClaw channel name: `discord`, `slack`, `telegram`, `signal`, etc. |
578
- | `target` | Yes | Channel/group/user ID to send to |
579
- | `accountId` | No | Account ID for multi-account setups (Slack) |
611
+ ### Step 1.5: Sync labels to Linear (optional)
580
612
 
581
- **`events`** -- Per-event-type toggles. All events are enabled by default. Set to `false` to suppress.
613
+ If you plan to use labels (Method B below) to tag issues, run this to create the `repo:xxx` labels automatically:
582
614
 
583
- ### Events
615
+ ```bash
616
+ openclaw openclaw-linear repos sync
617
+ ```
584
618
 
585
- | Event | Kind | Example Message |
586
- |---|---|---|
587
- | Dispatch | `dispatch` | `API-123 dispatched -- Fix auth bug` |
588
- | Worker started | `working` | `API-123 worker started (attempt 0)` |
589
- | Audit in progress | `auditing` | `API-123 audit in progress` |
590
- | Audit passed | `audit_pass` | `API-123 passed audit. PR ready.` |
591
- | Audit failed | `audit_fail` | `API-123 failed audit (attempt 1). Gaps: no tests, missing validation` |
592
- | Escalation | `escalation` | `API-123 needs human review -- audit failed 3x` |
593
- | Stale detection | `stuck` | `API-123 stuck -- stale 2h` |
594
- | Watchdog kill | `watchdog_kill` | `API-123 killed by watchdog (no I/O for 120s). Retrying (attempt 0).` |
619
+ This reads your `repos` config and creates matching labels (`repo:api`, `repo:frontend`, etc.) in every Linear team. To preview without creating anything:
595
620
 
596
- ### Delivery
621
+ ```bash
622
+ openclaw openclaw-linear repos check
623
+ ```
597
624
 
598
- Messages route through OpenClaw's native runtime channel API:
625
+ The check command also validates your repo paths — it'll warn you if a path doesn't exist, isn't a git repo, or is a **submodule** (which won't work with multi-repo dispatch).
599
626
 
600
- - **Discord** -- `runtime.channel.discord.sendMessageDiscord()`
601
- - **Slack** -- `runtime.channel.slack.sendMessageSlack()` (passes `accountId` for multi-workspace)
602
- - **Telegram** -- `runtime.channel.telegram.sendMessageTelegram()` (silent mode)
603
- - **Signal** -- `runtime.channel.signal.sendMessageSignal()`
604
- - **Other** -- Falls back to `openclaw message send` CLI
627
+ ### Step 2: Tag the issue
605
628
 
606
- Failures are isolated per target -- one channel going down doesn't block the others.
629
+ When you write an issue in Linear that needs multiple repos, tell the plugin which ones. Pick **one** of these methods:
607
630
 
608
- ### Notify CLI
631
+ #### Method A: HTML comment in the issue body (recommended)
632
+
633
+ Put this line anywhere in the issue description — it's invisible in Linear's UI:
634
+
635
+ ```
636
+ <!-- repos: api, frontend -->
637
+ ```
638
+
639
+ Full example of what an issue body might look like:
609
640
 
610
- ```bash
611
- openclaw openclaw-linear notify status # Show configured targets and suppressed events
612
- openclaw openclaw-linear notify test # Send test notification to all targets
613
- openclaw openclaw-linear notify test --channel discord # Test only discord targets
614
- openclaw openclaw-linear notify setup # Interactive target setup
615
641
  ```
642
+ The search endpoint needs to be added to the API, and the frontend
643
+ needs a new search page that calls it.
644
+
645
+ <!-- repos: api, frontend -->
646
+
647
+ Acceptance criteria:
648
+ - GET /api/search?q=term returns results
649
+ - /search page renders results with pagination
650
+ ```
651
+
652
+ #### Method B: Linear labels
653
+
654
+ Create labels in Linear called `repo:api` and `repo:frontend`, then add them to the issue. The part after `repo:` must match the key in your config.
655
+
656
+ #### Method C: Do nothing (config default)
657
+
658
+ If you don't tag the issue at all, the plugin uses your `codexBaseRepo` setting (a single repo). This is how it worked before multi-repo existed — nothing changes for single-repo issues.
659
+
660
+ ### What happens when you dispatch
661
+
662
+ When the agent picks up a multi-repo issue, the dispatch comment tells you:
663
+
664
+ > **Dispatched** as **senior** (anthropic/claude-opus-4-6)
665
+ >
666
+ > Worktrees:
667
+ > - `api` → `/home/claw/worktrees/ENG-100/api`
668
+ > - `frontend` → `/home/claw/worktrees/ENG-100/frontend`
669
+ >
670
+ > Branch: `codex/ENG-100`
671
+
672
+ The agent gets access to all the worktrees and can edit files across repos in one session. Each repo gets its own git branch.
673
+
674
+ ### Priority order
675
+
676
+ If an issue has both a body marker and labels, the body marker wins. Full order:
677
+
678
+ 1. `<!-- repos: ... -->` in the issue body
679
+ 2. `repo:xxx` labels on the issue
680
+ 3. `codexBaseRepo` from config (single repo fallback)
681
+
682
+ ### Common mistakes
683
+
684
+ | Problem | Fix |
685
+ |---|---|
686
+ | Agent only sees one repo | The name in `<!-- repos: api -->` must exactly match a key in your `repos` config. Check spelling. |
687
+ | "Could not create worktree" error | The path in your `repos` config doesn't exist, or it's not a git repo. Run `ls /home/claw/repos/api/.git` to check. |
688
+ | Comment marker not detected | Must be `<!-- repos: name1, name2 -->` with the exact format. No extra spaces around `<!--` or `-->`. |
689
+ | Labels not picked up | Labels must be formatted `repo:name` (lowercase, no spaces). The `name` part must match a `repos` config key. |
616
690
 
617
691
  ---
618
692
 
619
- ## Coding Tool (`code_run`)
693
+ ## Dispatch Management
620
694
 
621
- One tool dispatches to three CLI backends. Agents call `code_run` without knowing which backend is active.
695
+ ### Slash Commands
622
696
 
623
- ### Supported Backends
697
+ Type these in any agent session — they run instantly, no AI involved:
624
698
 
625
- | Backend | CLI | Stream Format | Key Flags |
626
- |---|---|---|---|
627
- | **Claude Code** (Anthropic) | `claude` | JSONL (`stream-json`) | `--print`, `--dangerously-skip-permissions` |
628
- | **Codex** (OpenAI) | `codex` | JSONL | `--full-auto`, `--ephemeral` |
629
- | **Gemini CLI** (Google) | `gemini` | JSONL (`stream-json`) | `--yolo`, `-o stream-json` |
699
+ | Command | What it does |
700
+ |---|---|
701
+ | `/dispatch list` | Show all active dispatches with age, tier, status |
702
+ | `/dispatch status CT-123` | Detailed info for one dispatch |
703
+ | `/dispatch retry CT-123` | Re-run a stuck dispatch |
704
+ | `/dispatch escalate CT-123 "needs review"` | Force a dispatch to stuck status |
630
705
 
631
- All three backends have inactivity watchdog protection. Each line of JSONL output ticks the watchdog timer. If a CLI goes silent beyond the configured threshold, the process is killed with SIGTERM (+ SIGKILL after 5s).
706
+ ### Gateway API
632
707
 
633
- ### Backend Resolution Priority
708
+ For programmatic access, the plugin registers these RPC methods:
634
709
 
635
- 1. **Explicit `backend` parameter** -- Agent passes `backend: "gemini"` (or any alias)
636
- 2. **Per-agent override** -- `agentCodingTools` in `coding-tools.json`
637
- 3. **Global default** -- `codingTool` in `coding-tools.json`
638
- 4. **Hardcoded fallback** -- `"claude"`
710
+ | Method | What it does |
711
+ |---|---|
712
+ | `dispatch.list` | List dispatches (filterable by status, tier) |
713
+ | `dispatch.get` | Get full dispatch details |
714
+ | `dispatch.retry` | Re-dispatch a stuck issue |
715
+ | `dispatch.escalate` | Force-stuck with a reason |
716
+ | `dispatch.cancel` | Remove an active dispatch |
717
+ | `dispatch.stats` | Counts by status and tier |
718
+
719
+ ---
720
+
721
+ ## Watchdog
722
+
723
+ If an agent goes silent (LLM timeout, API hang, CLI lockup), the watchdog handles it automatically:
724
+
725
+ 1. No output for `inactivitySec` → kill and retry once
726
+ 2. Second silence → escalate to stuck (you get notified, see [Stage 6](#stage-6-timeout-if-the-agent-goes-silent) above)
727
+
728
+ | Setting | Default | What it controls |
729
+ |---|---|---|
730
+ | `inactivitySec` | 120s | Kill if no output for this long |
731
+ | `maxTotalSec` | 7200s (2 hrs) | Hard ceiling on total session time |
732
+ | `toolTimeoutSec` | 600s (10 min) | Max time for a single `code_run` call |
733
+
734
+ Configure per-agent in `agent-profiles.json` or globally in plugin config.
639
735
 
640
736
  ---
641
737
 
642
- ## Inactivity Watchdog
738
+ ## Testing & Verification
643
739
 
644
- Agent sessions can go silent when LLM providers rate-limit, APIs hang, or CLI tools lock up. The watchdog detects silence and kills stuck sessions.
740
+ ### Health check
645
741
 
646
- ### How It Works
742
+ Run the doctor to verify your setup. It checks auth, config, prompts, connectivity, and dispatch health — and tells you exactly how to fix anything that's wrong:
647
743
 
648
- ```mermaid
649
- flowchart TD
650
- A[Agent starts] --> B["Watchdog timer starts<br/>(inactivitySec countdown)"]
651
- B --> C{"I/O event?"}
652
- C -->|"JSONL line, stderr,<br/>stream callback"| D[Timer resets]
653
- D --> C
654
- C -->|"No I/O for inactivitySec"| E[KILL]
655
- E --> F[Retry once]
656
- F -->|Success| G[Continue pipeline]
657
- F -->|Killed again| H["STUCK (escalation)"]
658
- B --> I{"Total runtime<br/>> maxTotalSec?"}
659
- I -->|Yes| J["KILL (no retry)"]
744
+ ```bash
745
+ openclaw openclaw-linear doctor
660
746
  ```
661
747
 
662
- ### Three Timeout Dimensions
748
+ Example output:
663
749
 
664
- | Timeout | Scope | Default | Description |
665
- |---------|-------|---------|-------------|
666
- | `inactivitySec` | Per I/O gap | 120s (2 min) | Kill if no stdout/stderr/callback for this long |
667
- | `maxTotalSec` | Per agent session | 7200s (2 hrs) | Hard ceiling on total session runtime |
668
- | `toolTimeoutSec` | Per `code_run` call | 600s (10 min) | Max runtime for a single CLI invocation |
750
+ ```
751
+ ┌──────────────────────────────────────────────┐
752
+ │ Linear Plugin Doctor │
753
+ └──────────────────────────────────────────────┘
669
754
 
670
- ### Config Resolution Order
755
+ Authentication & Tokens
756
+ ✔ Access token found (source: profile)
757
+ ✔ Token not expired (23h remaining)
758
+ ✔ API reachable — logged in as Test (TestOrg)
671
759
 
672
- 1. **Agent profile** -- `~/.openclaw/agent-profiles.json` `agents.{id}.watchdog`
673
- 2. **Plugin config** -- `openclaw.json` `inactivitySec` / `maxTotalSec` / `toolTimeoutSec`
674
- 3. **Hardcoded defaults** -- 120s / 7200s / 600s
760
+ Agent Configuration
761
+ agent-profiles.json loaded (2 agents)
762
+ Default agent: coder
675
763
 
676
- ### Per-Agent Configuration
764
+ Coding Tools
765
+ ✔ coding-tools.json loaded (default: claude)
766
+ ✔ claude: found at /usr/local/bin/claude
677
767
 
678
- ```json
679
- {
680
- "agents": {
681
- "coder": {
682
- "watchdog": {
683
- "inactivitySec": 180,
684
- "maxTotalSec": 7200,
685
- "toolTimeoutSec": 900
686
- }
687
- },
688
- "reviewer": {
689
- "watchdog": {
690
- "inactivitySec": 60,
691
- "maxTotalSec": 600,
692
- "toolTimeoutSec": 300
693
- }
694
- }
695
- }
696
- }
768
+ Files & Directories
769
+ ✔ Dispatch state: 1 active, 5 completed
770
+ Prompts valid (5/5 sections, 4/4 variables)
771
+
772
+ Connectivity
773
+ Linear API reachable
774
+ Webhook gateway responding
775
+
776
+ Dispatch Health
777
+ ✔ No stale dispatches
778
+ 2 completed dispatches older than 7 days
779
+ → Run: openclaw openclaw-linear doctor --fix to clean up
780
+
781
+ Summary: 11 passed, 1 warning, 0 errors
697
782
  ```
698
783
 
699
- ### Artifact Logging
784
+ Every warning and error includes a `→` line telling you what to do. Run `doctor --fix` to auto-repair what it can.
700
785
 
701
- Every dispatch writes structured artifacts to `.claw/` in the worktree:
786
+ ### Unit tests
702
787
 
788
+ 422 tests covering the full pipeline — triage, dispatch, audit, planning, notifications, and infrastructure:
789
+
790
+ ```bash
791
+ cd ~/claw-extensions/linear
792
+ npx vitest run # Run all tests
793
+ npx vitest run --reporter=verbose # See every test name
794
+ npx vitest run src/pipeline/ # Just pipeline tests
703
795
  ```
704
- .claw/
705
- manifest.json Issue metadata + lifecycle timestamps
706
- plan.md Implementation plan
707
- worker-{N}.md Worker output per attempt (truncated to 8KB)
708
- audit-{N}.json Audit verdict per attempt
709
- log.jsonl Append-only structured interaction log
710
- summary.md Agent-curated final summary
796
+
797
+ ### UAT (live integration tests)
798
+
799
+ The UAT script runs against your real Linear workspace. It creates actual issues, triggers the pipeline, and verifies the results.
800
+
801
+ ```bash
802
+ # Run all UAT scenarios
803
+ npx tsx scripts/uat-linear.ts
804
+
805
+ # Run a specific scenario
806
+ npx tsx scripts/uat-linear.ts --test dispatch
807
+ npx tsx scripts/uat-linear.ts --test planning
808
+ npx tsx scripts/uat-linear.ts --test mention
711
809
  ```
712
810
 
713
- Watchdog kills are logged to `log.jsonl` with phase `"watchdog"`:
811
+ **What each scenario does:**
714
812
 
715
- ```json
716
- {
717
- "ts": "2026-02-18T12:00:00Z",
718
- "phase": "watchdog",
719
- "attempt": 0,
720
- "agent": "coder",
721
- "success": false,
722
- "watchdog": {
723
- "reason": "inactivity",
724
- "silenceSec": 120,
725
- "thresholdSec": 120,
726
- "retried": true
727
- }
728
- }
813
+ #### `--test dispatch` (Single issue, full pipeline)
814
+
815
+ 1. Creates a test issue in Linear
816
+ 2. Assigns it to the agent
817
+ 3. Waits for the dispatch comment (confirms the agent picked it up)
818
+ 4. Waits for the audit result (pass, fail, or escalation)
819
+ 5. Reports success/failure with timing
820
+
821
+ **Expected output:**
822
+
823
+ ```
824
+ [dispatch] Created issue ENG-200: "UAT: simple config tweak"
825
+ [dispatch] Assigned to agent — waiting for dispatch comment...
826
+ [dispatch] ✔ Dispatch confirmed (12s) — assessed as junior
827
+ [dispatch] Waiting for audit result...
828
+ [dispatch] ✔ Audit passed (94s) — issue marked done
829
+ [dispatch] Total: 106s
830
+ ```
831
+
832
+ #### `--test planning` (Project planning flow)
833
+
834
+ 1. Creates a root issue in a test project
835
+ 2. Posts `plan this project` comment
836
+ 3. Waits for the planner's welcome message
837
+ 4. Posts feature requirements
838
+ 5. Waits for the planner to create issues
839
+ 6. Posts `finalize plan`
840
+ 7. Waits for plan approval or failure
841
+
842
+ **Expected output:**
843
+
844
+ ```
845
+ [planning] Created project "UAT Planning Test"
846
+ [planning] Posted "plan this project" — waiting for welcome...
847
+ [planning] ✔ Welcome received (8s)
848
+ [planning] Posted feature description — waiting for response...
849
+ [planning] ✔ Planner created 3 issues (15s)
850
+ [planning] Posted "finalize plan" — waiting for audit...
851
+ [planning] ✔ Plan approved (6s) — 3 issues queued for dispatch
852
+ [planning] Total: 29s
853
+ ```
854
+
855
+ #### `--test mention` (Agent routing)
856
+
857
+ 1. Creates a test issue
858
+ 2. Posts a comment mentioning a specific agent (e.g., `@kaylee`)
859
+ 3. Waits for that agent to respond
860
+ 4. Verifies the response came from the right agent
861
+
862
+ **Expected output:**
863
+
864
+ ```
865
+ [mention] Created issue ENG-201
866
+ [mention] Posted "@kaylee analyze this issue"
867
+ [mention] ✔ Kaylee responded (18s)
868
+ [mention] Total: 18s
869
+ ```
870
+
871
+ ### Verify notifications
872
+
873
+ ```bash
874
+ openclaw openclaw-linear notify test # Send test to all targets
875
+ openclaw openclaw-linear notify test --channel discord # Test one channel
876
+ openclaw openclaw-linear notify status # Show what's configured
877
+ ```
878
+
879
+ ### Verify prompts
880
+
881
+ ```bash
882
+ openclaw openclaw-linear prompts validate # Check for template errors
883
+ openclaw openclaw-linear prompts show # View the active prompts
729
884
  ```
730
885
 
731
886
  ---
@@ -733,20 +888,39 @@ Watchdog kills are logged to `log.jsonl` with phase `"watchdog"`:
733
888
  ## CLI Reference
734
889
 
735
890
  ```bash
736
- openclaw openclaw-linear auth # Run OAuth authorization
737
- openclaw openclaw-linear status # Check connection and token status
738
- openclaw openclaw-linear worktrees # List active worktrees
891
+ # Auth & status
892
+ openclaw openclaw-linear auth # Run OAuth flow
893
+ openclaw openclaw-linear status # Check connection
894
+
895
+ # Worktrees
896
+ openclaw openclaw-linear worktrees # List active worktrees
739
897
  openclaw openclaw-linear worktrees --prune <path> # Remove a worktree
740
- openclaw openclaw-linear prompts show # Print current prompts
741
- openclaw openclaw-linear prompts path # Print resolved prompts file path
742
- openclaw openclaw-linear prompts validate # Validate prompt structure
743
- openclaw openclaw-linear notify status # Show notification targets and event toggles
744
- openclaw openclaw-linear notify test # Send test notification to all targets
745
- openclaw openclaw-linear notify test --channel slack # Test specific channel only
746
- openclaw openclaw-linear notify setup # Interactive notification target setup
747
- openclaw openclaw-linear doctor # Run comprehensive health checks
748
- openclaw openclaw-linear doctor --fix # Auto-fix safe issues
749
- openclaw openclaw-linear doctor --json # Output results as JSON
898
+
899
+ # Multi-repo
900
+ openclaw openclaw-linear repos check # Validate paths, preview labels
901
+ openclaw openclaw-linear repos sync # Create missing repo: labels in Linear
902
+
903
+ # Prompts
904
+ openclaw openclaw-linear prompts show # View current prompts
905
+ openclaw openclaw-linear prompts path # Show file path
906
+ openclaw openclaw-linear prompts validate # Check for errors
907
+
908
+ # Notifications
909
+ openclaw openclaw-linear notify status # Show targets & events
910
+ openclaw openclaw-linear notify test # Test all targets
911
+ openclaw openclaw-linear notify test --channel discord # Test one channel
912
+ openclaw openclaw-linear notify setup # Interactive setup
913
+
914
+ # Dispatch
915
+ /dispatch list # Active dispatches
916
+ /dispatch status <identifier> # Dispatch details
917
+ /dispatch retry <identifier> # Re-run stuck dispatch
918
+ /dispatch escalate <identifier> [reason] # Force to stuck
919
+
920
+ # Health
921
+ openclaw openclaw-linear doctor # Run health checks
922
+ openclaw openclaw-linear doctor --fix # Auto-fix issues
923
+ openclaw openclaw-linear doctor --json # JSON output
750
924
  ```
751
925
 
752
926
  ---
@@ -759,25 +933,31 @@ Quick checks:
759
933
  systemctl --user status openclaw-gateway # Is the gateway running?
760
934
  openclaw openclaw-linear status # Is the token valid?
761
935
  journalctl --user -u openclaw-gateway -f # Watch live logs
762
- linearis issues list -l 1 # Is linearis authenticated?
763
- openclaw openclaw-linear prompts validate # Are prompts valid?
764
936
  ```
765
937
 
766
938
  ### Common Issues
767
939
 
768
- | Problem | Cause | Fix |
769
- |---|---|---|
770
- | Agent goes silent, no response | LLM provider timeout or rate limit | Watchdog auto-kills after `inactivitySec` and retries. Check logs for `Watchdog KILL`. |
771
- | Dispatch stuck after watchdog | Both retry attempts failed | Check `.claw/log.jsonl` for watchdog entries. Re-assign issue to retry. |
772
- | Agent says "closing" but doesn't | No issue management tool | Install `linearis`: `npx clawhub install linearis` |
773
- | `code_run` uses wrong backend | Config mismatch | Check `coding-tools.json` |
774
- | Claude Code "nested session" error | `CLAUDECODE` env var set | Plugin handles this automatically |
775
- | Gateway rejects plugin config keys | Strict validator | Custom config goes in `coding-tools.json` |
776
- | Webhook events not arriving | Wrong URL | Both webhooks must point to `/linear/webhook` |
777
- | OAuth token expired | Tokens expire ~24h | Auto-refreshes; restart gateway if stuck |
778
- | Audit always fails | Bad prompt template | Run `openclaw openclaw-linear prompts validate` |
779
-
780
- See [docs/troubleshooting.md](docs/troubleshooting.md) for detailed diagnostic commands.
940
+ | Problem | Fix |
941
+ |---|---|
942
+ | Agent goes silent | Watchdog auto-kills after `inactivitySec` and retries. Check logs for `Watchdog KILL`. |
943
+ | Dispatch stuck after watchdog | Both retries failed. Check `.claw/log.jsonl`. Re-assign issue to restart. |
944
+ | `code_run` uses wrong backend | Check `coding-tools.json` explicit backend > per-agent > global default. |
945
+ | Webhook events not arriving | Both webhooks must point to `/linear/webhook`. Check tunnel is running. |
946
+ | OAuth token expired | Auto-refreshes. If stuck, re-run `openclaw openclaw-linear auth` and restart. |
947
+ | Audit always fails | Run `openclaw openclaw-linear prompts validate` to check prompt syntax. |
948
+ | Multi-repo not detected | Markers must be `<!-- repos: name1, name2 -->`. Names must match `repos` config keys. |
949
+ | `/dispatch` not responding | Restart gateway. Check plugin loaded with `openclaw doctor`. |
950
+ | Rich notifications are plain text | Set `"richFormat": true` in notifications config. |
951
+ | Gateway rejects config keys | Strict validator. Run `openclaw doctor --fix`. |
952
+
953
+ For detailed diagnostics, see [docs/troubleshooting.md](docs/troubleshooting.md).
954
+
955
+ ---
956
+
957
+ ## Further Reading
958
+
959
+ - [Architecture](docs/architecture.md) — Internal design, state machines, diagrams
960
+ - [Troubleshooting](docs/troubleshooting.md) — Diagnostic commands, curl examples, log analysis
781
961
 
782
962
  ---
783
963