@calltelemetry/openclaw-linear 0.7.1 → 0.8.1

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.
Files changed (41) hide show
  1. package/README.md +834 -536
  2. package/index.ts +1 -1
  3. package/openclaw.plugin.json +3 -2
  4. package/package.json +1 -1
  5. package/prompts.yaml +46 -6
  6. package/src/__test__/fixtures/linear-responses.ts +75 -0
  7. package/src/__test__/fixtures/webhook-payloads.ts +113 -0
  8. package/src/__test__/helpers.ts +133 -0
  9. package/src/agent/agent.test.ts +192 -0
  10. package/src/agent/agent.ts +26 -1
  11. package/src/api/linear-api.test.ts +93 -1
  12. package/src/api/linear-api.ts +37 -1
  13. package/src/gateway/dispatch-methods.test.ts +409 -0
  14. package/src/infra/cli.ts +176 -1
  15. package/src/infra/commands.test.ts +276 -0
  16. package/src/infra/doctor.test.ts +19 -0
  17. package/src/infra/doctor.ts +30 -25
  18. package/src/infra/multi-repo.test.ts +163 -0
  19. package/src/infra/multi-repo.ts +29 -0
  20. package/src/infra/notify.test.ts +155 -16
  21. package/src/infra/notify.ts +26 -15
  22. package/src/infra/observability.test.ts +85 -0
  23. package/src/pipeline/artifacts.test.ts +26 -3
  24. package/src/pipeline/dispatch-state.ts +1 -0
  25. package/src/pipeline/e2e-dispatch.test.ts +584 -0
  26. package/src/pipeline/e2e-planning.test.ts +478 -0
  27. package/src/pipeline/intent-classify.test.ts +285 -0
  28. package/src/pipeline/intent-classify.ts +259 -0
  29. package/src/pipeline/pipeline.test.ts +69 -0
  30. package/src/pipeline/pipeline.ts +47 -18
  31. package/src/pipeline/planner.test.ts +159 -40
  32. package/src/pipeline/planner.ts +108 -60
  33. package/src/pipeline/tier-assess.test.ts +89 -0
  34. package/src/pipeline/webhook.ts +424 -251
  35. package/src/tools/claude-tool.ts +6 -0
  36. package/src/tools/cli-shared.test.ts +155 -0
  37. package/src/tools/code-tool.test.ts +210 -0
  38. package/src/tools/code-tool.ts +2 -2
  39. package/src/tools/dispatch-history-tool.test.ts +315 -0
  40. package/src/tools/planner-tools.test.ts +1 -1
  41. package/src/tools/planner-tools.ts +10 -2
package/README.md CHANGED
@@ -3,348 +3,492 @@
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 anything?** The bot understands natural language — no magic commands needed.
15
+ - **Say "let's plan the features"?** A planner interviews you, writes user stories, and builds your full issue hierarchy.
16
+ - **Plan looks good?** A different AI model automatically audits the plan before dispatch.
17
+ - **Agent goes silent?** A watchdog kills it and retries automatically.
18
+ - **Want updates?** Get notified on Discord, Slack, Telegram, or Signal.
26
19
 
27
20
  ---
28
21
 
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 |
22
+ ## Quick Start
46
23
 
47
- ---
24
+ ### 1. Install the plugin
48
25
 
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
26
+ ```bash
27
+ openclaw plugins install @calltelemetry/openclaw-linear
84
28
  ```
85
29
 
86
- ---
30
+ ### 2. Create a Linear OAuth app
31
+
32
+ Go to **Linear Settings > API > Applications** and create an app:
87
33
 
88
- ## Architecture
34
+ - Set **Webhook URL** to `https://your-domain.com/linear/webhook`
35
+ - Set **Redirect URI** to `https://your-domain.com/linear/oauth/callback`
36
+ - Enable events: **Agent Sessions**, **Comments**, **Issues**
37
+ - Save your **Client ID** and **Client Secret**
89
38
 
90
- ### Dispatch Pipeline (v2)
39
+ > You also need a **workspace webhook** (Settings > API > Webhooks) pointing to the same URL with Comment + Issue + User events enabled. Both webhooks are required.
40
+
41
+ ### 3. Set credentials
42
+
43
+ ```bash
44
+ export LINEAR_CLIENT_ID="your_client_id"
45
+ export LINEAR_CLIENT_SECRET="your_client_secret"
46
+ ```
47
+
48
+ For systemd services, add these to your unit file:
49
+
50
+ ```ini
51
+ [Service]
52
+ Environment=LINEAR_CLIENT_ID=your_client_id
53
+ Environment=LINEAR_CLIENT_SECRET=your_client_secret
54
+ ```
55
+
56
+ Then reload: `systemctl --user daemon-reload && systemctl --user restart openclaw-gateway`
91
57
 
92
- When an issue is assigned, the plugin runs a multi-stage pipeline:
58
+ ### 4. Authorize
93
59
 
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"]
60
+ ```bash
61
+ openclaw openclaw-linear auth
104
62
  ```
105
63
 
106
- ### Hard-Enforced vs. LLM-Mediated
64
+ This opens your browser. Approve the authorization, then restart:
107
65
 
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 |
66
+ ```bash
67
+ systemctl --user restart openclaw-gateway
68
+ ```
116
69
 
117
- ### State Machine
70
+ ### 5. Verify
118
71
 
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
72
+ ```bash
73
+ openclaw openclaw-linear status
128
74
  ```
129
75
 
130
- All transitions use compare-and-swap (CAS) to prevent races. `dispatch-state.json` is the canonical source of truth.
76
+ You should see a valid token and connected status. Check the gateway logs for a clean startup:
131
77
 
132
- ### Project Planner Pipeline
78
+ ```
79
+ Linear agent extension registered (agent: default, token: profile, orchestration: enabled)
80
+ ```
133
81
 
134
- When `@ctclaw plan this project` is commented on a root issue, the plugin enters planning mode:
82
+ Test the webhook endpoint:
135
83
 
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"]
84
+ ```bash
85
+ curl -s -X POST https://your-domain.com/linear/webhook \
86
+ -H "Content-Type: application/json" \
87
+ -d '{"type":"test","action":"ping"}'
88
+ # Returns: "ok"
145
89
  ```
146
90
 
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.
91
+ That's it. Create an issue in Linear and watch the agent respond.
92
+
93
+ ---
94
+
95
+ ## How It Works — Step by Step
148
96
 
149
- ### Webhook Event Router
97
+ Every issue moves through a clear pipeline. Here's exactly what happens at each stage and what you'll see in Linear.
150
98
 
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"]
99
+ ```
100
+ ┌─────────┐ ┌──────────┐ ┌────────┐ ┌───────┐ ┌──────────┐
101
+ Triage │───▶│ Dispatch │───▶│ Worker │───▶│ Audit │───▶│ Done ✔ │
102
+ │(auto) │ │(you │ │(auto) │ │(auto) │ │ │
103
+ │ │ assign) │ │ │ │ │ └──────────┘
104
+ └─────────┘ └──────────┘ └────────┘ └───┬───┘
105
+
106
+ ┌─────────────┤
107
+ ▼ ▼
108
+ ┌──────────┐ ┌───────────────┐
109
+ │ Rework │ │ Needs Your │
110
+ │ (auto │ │ Help ⚠ │
111
+ │ retry) │ │ (escalated) │
112
+ └────┬─────┘ └───────────────┘
113
+
114
+ └──▶ back to Worker
160
115
  ```
161
116
 
162
- All handlers respond `200 OK` within 5 seconds (Linear requirement), then process asynchronously.
117
+ ### Stage 1: Triage (automatic)
163
118
 
164
- ### Two Webhook Systems
119
+ **Trigger:** You create a new issue.
165
120
 
166
- Linear delivers events through two separate webhook paths:
121
+ The agent reads your issue, estimates story points, adds labels, sets priority, and posts an assessment comment — all within seconds.
167
122
 
168
- 1. **Workspace webhook** (Settings > API > Webhooks) -- Comment, Issue, User events
169
- 2. **OAuth app webhook** (Settings > API > Applications) -- `AgentSessionEvent` (created/prompted)
123
+ **What you'll see in Linear:**
170
124
 
171
- Both must point to: `https://<your-domain>/linear/webhook`
125
+ > **[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`.
172
126
 
173
- ### Deduplication
127
+ The estimate, labels, and priority are applied silently to the issue fields. You don't need to do anything.
174
128
 
175
- A 60-second sliding window prevents double-handling:
129
+ ### Stage 2: Dispatch (you assign the issue)
176
130
 
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 |
131
+ **Trigger:** You assign the issue to the agent (or it gets auto-assigned after planning).
132
+
133
+ The agent assesses complexity, picks an appropriate model, creates an isolated git worktree, and starts working.
134
+
135
+ **What you'll see in Linear:**
136
+
137
+ > **Dispatched** as **senior** (anthropic/claude-opus-4-6)
138
+ > > Complex multi-service refactor with migration concerns
139
+ >
140
+ > Worktree: `/home/claw/worktrees/ENG-100` (fresh)
141
+ > Branch: `codex/ENG-100`
142
+ >
143
+ > **Status:** Worker is starting now. An independent audit runs automatically after implementation.
144
+ >
145
+ > **While you wait:**
146
+ > - Check progress: `/dispatch status ENG-100`
147
+ > - Cancel: `/dispatch escalate ENG-100 "reason"`
148
+ > - All dispatches: `/dispatch list`
149
+
150
+ **Complexity tiers:**
151
+
152
+ | Tier | Model | When |
153
+ |---|---|---|
154
+ | Junior | claude-haiku-4-5 | Simple config changes, typos, one-file fixes |
155
+ | Medior | claude-sonnet-4-6 | Standard features, multi-file changes |
156
+ | Senior | claude-opus-4-6 | Complex refactors, architecture changes |
157
+
158
+ ### Stage 3: Implementation (automatic)
159
+
160
+ 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.
161
+
162
+ 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.
163
+
164
+ **Notifications you'll receive:**
165
+ > `ENG-100 working on it (attempt 1)`
166
+
167
+ ### Stage 4: Audit (automatic)
168
+
169
+ After the worker finishes, a separate auditor agent independently verifies the work. The auditor checks the issue requirements against what was actually implemented.
170
+
171
+ This is **not optional** — the worker cannot mark its own work as done. The audit is triggered by the plugin, not by the AI.
172
+
173
+ **Notifications you'll receive:**
174
+ > `ENG-100 checking the work...`
175
+
176
+ ### Stage 5: Verdict
177
+
178
+ The audit produces one of three outcomes:
179
+
180
+ #### Pass — Issue is done
181
+
182
+ The issue is marked done automatically. A summary is posted.
183
+
184
+ **What you'll see in Linear:**
185
+
186
+ > ## Done
187
+ >
188
+ > This issue has been implemented and verified.
189
+ >
190
+ > **What was checked:**
191
+ > - API endpoint returns correct response format
192
+ > - Tests pass for edge cases
193
+ > - Error handling covers timeout scenarios
194
+ >
195
+ > **Test results:** 14 tests passed, 0 failed
196
+ >
197
+ > ---
198
+ > *Completed on attempt 1. Artifacts: `/home/claw/worktrees/ENG-100/.claw/`*
199
+
200
+ **Notification:** `✅ ENG-100 done! Ready for review.`
201
+
202
+ #### Fail (retries left) — Automatic rework
203
+
204
+ The worker gets the audit feedback and tries again. You don't need to do anything.
205
+
206
+ **What you'll see in Linear:**
207
+
208
+ > ## Needs More Work
209
+ >
210
+ > The implementation was checked and some things need to be addressed. Retrying automatically.
211
+ >
212
+ > **Attempt 1 of 3**
213
+ >
214
+ > **What needs fixing:**
215
+ > - Missing input validation on the search endpoint
216
+ > - No test for empty query string
217
+ >
218
+ > **Test results:** 12 passed, 2 failed
219
+
220
+ **Notification:** `ENG-100 needs more work (attempt 1). Issues: missing validation, no empty query test`
221
+
222
+ #### Fail (no retries left) — Needs your help
223
+
224
+ After all retries are exhausted (default: 3 attempts), the issue is escalated to you.
225
+
226
+ **What you'll see in Linear:**
227
+
228
+ > ## Needs Your Help
229
+ >
230
+ > The automatic retries didn't fix these issues:
231
+ >
232
+ > **What went wrong:**
233
+ > - Search pagination still returns duplicate results
234
+ > - Integration test flaky on CI
235
+ >
236
+ > **Test results:** 10 passed, 4 failed
237
+ >
238
+ > ---
239
+ > *Please review and either:*
240
+ > - *Update the issue description with clearer requirements, then re-assign*
241
+ > - *Fix the issues manually in the worktree at `/home/claw/worktrees/ENG-100`*
242
+
243
+ **Notification:** `🚨 ENG-100 needs your help — couldn't fix it after 3 tries`
244
+
245
+ **What you can do:**
246
+ 1. **Clarify the issue** — Add more detail to the description, then re-assign to try again
247
+ 2. **Fix it yourself** — The agent's work is in the worktree, ready to edit
248
+ 3. **Force retry** — `/dispatch retry ENG-100`
249
+ 4. **Check logs** — Worker output in `.claw/worker-*.md`, audit verdicts in `.claw/audit-*.json`
250
+
251
+ ### Stage 6: Timeout (if the agent goes silent)
252
+
253
+ 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.
254
+
255
+ **What you'll see in Linear:**
256
+
257
+ > ## Agent Timed Out
258
+ >
259
+ > The agent stopped responding for over 120s and was automatically restarted, but the retry also failed.
260
+ >
261
+ > **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.
262
+
263
+ **Notification:** `⚡ ENG-100 timed out (no activity for 120s). Will retry.`
264
+
265
+ ### What's in the worktree
266
+
267
+ Every dispatch creates a `.claw/` folder inside the worktree with everything the agent did:
268
+
269
+ ```
270
+ /home/claw/worktrees/ENG-100/
271
+ ├── .claw/
272
+ │ ├── manifest.json # Issue metadata, tier, status, attempt count
273
+ │ ├── worker-0.md # What the worker did on attempt 1
274
+ │ ├── worker-1.md # What the worker did on attempt 2 (if retried)
275
+ │ ├── audit-0.json # Audit verdict for attempt 1
276
+ │ ├── audit-1.json # Audit verdict for attempt 2
277
+ │ ├── log.jsonl # Timeline of every phase with timing
278
+ │ └── summary.md # Final summary (written on done or stuck)
279
+ ├── src/ # ← your code, modified by the agent
280
+ ├── tests/
281
+ └── ...
282
+ ```
283
+
284
+ If something went wrong, start with `log.jsonl` — it shows every phase, how long it took, and a preview of the output.
183
285
 
184
286
  ---
185
287
 
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)
288
+ ## Comment Routing — Talk Naturally
289
+
290
+ You don't need to memorize magic commands. The bot uses an LLM-based intent classifier to understand what you want from any comment.
291
+
292
+ ```
293
+ User comment Intent Classifier (small model, ~2s) → Route to handler
294
+ (on failure)
295
+ Regex fallback Route to handler
234
296
  ```
235
297
 
298
+ **What the bot understands:**
299
+
300
+ | What you say | What happens |
301
+ |---|---|
302
+ | "let's plan the features for this" | Starts planning interview |
303
+ | "looks good, ship it" (during planning) | Runs plan audit + cross-model review |
304
+ | "nevermind, cancel this" (during planning) | Exits planning mode |
305
+ | "hey kaylee can you look at this?" | Routes to Kaylee (no `@` needed) |
306
+ | "what can I do here?" | Default agent responds (not silently dropped) |
307
+ | "fix the search bug" | Default agent dispatches work |
308
+
309
+ `@mentions` still work as a fast path — if you write `@kaylee`, the classifier is skipped entirely for speed.
310
+
311
+ > **Tip:** Configure `classifierAgentId` to point to a small/fast model agent (like Haiku) for low-latency, low-cost intent classification. The classifier only needs ~300 tokens per call.
312
+
236
313
  ---
237
314
 
238
- ## Getting Started
315
+ ## Planning a Project
239
316
 
240
- ### Prerequisites
317
+ For larger work, the planner helps you break a project into issues with dependencies, then dispatches them automatically.
241
318
 
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
319
+ ### Start planning
247
320
 
248
- ### 1. Install the Plugin
321
+ Comment on any issue that belongs to a Linear project — use natural language:
249
322
 
250
- ```bash
251
- openclaw plugins install @calltelemetry/openclaw-linear
252
- ```
323
+ > "let's plan out the features for this project"
253
324
 
254
- ### 2. Create a Linear OAuth App
325
+ The planner enters **interview mode** and asks you questions one at a time:
255
326
 
256
- Go to **Linear Settings > API > Applications** and create a new application:
327
+ > I'm entering planning mode for **Search Feature**. I'll interview you about the features you want to build, then structure everything into Linear issues.
328
+ >
329
+ > Let's start — what is this project about, and what are the main feature areas?
257
330
 
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**
331
+ ### Build the plan
261
332
 
262
- Save the **Client ID** and **Client Secret**.
333
+ Reply with your ideas. The planner creates issues with **user stories** and **acceptance criteria**, sets dependencies, and asks follow-up questions:
263
334
 
264
- ### 3. Set Credentials
335
+ > I've created 3 issues:
336
+ > - **PROJ-2:** Build search API endpoint (3 pts, blocks PROJ-3)
337
+ > - **PROJ-3:** Search results page (2 pts, blocked by PROJ-2)
338
+ > - **PROJ-4:** Autocomplete suggestions (1 pt, independent)
339
+ >
340
+ > For PROJ-2, here's what I wrote for acceptance criteria:
341
+ > - *Given* a user sends a search query, *When* results exist, *Then* they are returned with pagination
342
+ >
343
+ > Does that cover it? Should the autocomplete call a separate endpoint or share the search API?
265
344
 
266
- Add to your gateway environment or plugin config:
345
+ The planner proactively asks for:
346
+ - **User stories** — "As a [role], I want [feature] so that [benefit]"
347
+ - **Acceptance criteria** — Given/When/Then format
348
+ - **UAT test scenarios** — How to manually verify the feature
267
349
 
268
- ```bash
269
- export LINEAR_CLIENT_ID="your_client_id"
270
- export LINEAR_CLIENT_SECRET="your_client_secret"
271
- ```
350
+ Keep replying until the plan looks right. The planner updates issues in real time.
272
351
 
273
- For systemd:
352
+ ### Finalize & Cross-Model Review
274
353
 
275
- ```ini
276
- [Service]
277
- Environment=LINEAR_CLIENT_ID=your_client_id
278
- Environment=LINEAR_CLIENT_SECRET=your_client_secret
279
- ```
354
+ When you're happy, say something like "looks good" or "finalize plan". The planner runs a validation check:
355
+ - Every issue has a description (50+ characters) with acceptance criteria
356
+ - Every non-epic issue has an estimate and priority
357
+ - No circular dependencies in the DAG
280
358
 
281
- Then reload: `systemctl --user daemon-reload && systemctl --user restart openclaw-gateway`
359
+ **If validation passes, a cross-model review runs automatically:**
282
360
 
283
- ### 4. Expose the Gateway
361
+ > ## Plan Passed Checks
362
+ >
363
+ > **3 issues** with valid dependency graph.
364
+ >
365
+ > Let me have **Codex** audit this and make recommendations.
284
366
 
285
- Linear needs HTTPS access to deliver webhooks. [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/) is recommended.
367
+ A different AI model (always the complement of your primary model) reviews the plan for gaps:
286
368
 
287
- ```bash
288
- # Install cloudflared
289
- sudo dnf install -y cloudflared # RHEL/Rocky/Alma
369
+ | Your primary model | Auto-reviewer |
370
+ |---|---|
371
+ | Claude / Anthropic | Codex |
372
+ | Codex / OpenAI | Gemini |
373
+ | Gemini / Google | Codex |
374
+ | Other (Kimi, Mistral, etc.) | Gemini |
290
375
 
291
- # Create and configure tunnel
292
- cloudflared tunnel login
293
- cloudflared tunnel create openclaw
294
- cloudflared tunnel route dns openclaw linear.yourdomain.com
295
- ```
376
+ After the review, the planner summarizes recommendations and asks you to approve:
296
377
 
297
- Create `~/.cloudflared/config.yml`:
378
+ > Codex suggested adding error handling scenarios to PROJ-2 and noted PROJ-4 could be split into frontend/backend. I've updated PROJ-2's acceptance criteria. The PROJ-4 split is optional — your call.
379
+ >
380
+ > If you're happy with this plan, say **approve plan** to start dispatching.
298
381
 
299
- ```yaml
300
- tunnel: <TUNNEL_ID>
301
- credentials-file: ~/.cloudflared/<TUNNEL_ID>.json
382
+ **If validation fails:**
302
383
 
303
- ingress:
304
- - hostname: linear.yourdomain.com
305
- service: http://localhost:18789
306
- - service: http_status:404
307
- ```
384
+ > ## Plan Audit Failed
385
+ >
386
+ > **Problems:**
387
+ > - PROJ-2: description too short (< 50 chars)
388
+ > - PROJ-3: missing estimate
389
+ >
390
+ > **Warnings:**
391
+ > - PROJ-4: no acceptance criteria found in description
392
+ >
393
+ > Please address these issues, then say "finalize plan" again.
308
394
 
309
- Start the tunnel:
395
+ Fix the issues and try again. You can also say "cancel" or "stop planning" to exit without dispatching.
310
396
 
311
- ```bash
312
- sudo cloudflared service install
313
- sudo systemctl enable --now cloudflared
314
- ```
397
+ ### DAG dispatch progress
315
398
 
316
- Verify:
399
+ After approval, issues are assigned to the agent automatically in dependency order. Up to 3 issues run in parallel.
317
400
 
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
- ```
401
+ > `📊 Search Feature: 2/3 complete`
324
402
 
325
- ### 5. Authorize with Linear
403
+ When everything is done:
326
404
 
327
- ```bash
328
- openclaw openclaw-linear auth
329
- ```
405
+ > `✅ Search Feature: complete (3/3 issues)`
330
406
 
331
- This opens your browser to authorize the agent. Then restart and verify:
407
+ If an issue gets stuck (all retries failed), dependent issues are blocked and you'll be notified.
332
408
 
333
- ```bash
334
- systemctl --user restart openclaw-gateway
335
- openclaw openclaw-linear status
409
+ ---
410
+
411
+ ## Quick Reference
412
+
413
+ | What you do in Linear | What happens |
414
+ |---|---|
415
+ | Create a new issue | Agent triages — adds estimate, labels, priority |
416
+ | Assign an issue to the agent | Worker → Audit → Done (or retry, or escalate) |
417
+ | Comment anything on an issue | Intent classifier routes to the right handler |
418
+ | Mention an agent by name (with or without `@`) | That agent responds |
419
+ | Ask a question or request work | Default agent handles it |
420
+ | Say "plan this project" (on a project issue) | Planning interview starts |
421
+ | Reply during planning | Issues created/updated with user stories & AC |
422
+ | Say "looks good" / "finalize plan" | Validates → cross-model review → approval |
423
+ | Say "approve plan" (after review) | Dispatches all issues in dependency order |
424
+ | Say "cancel" / "abandon planning" | Exits planning mode |
425
+ | `/dispatch list` | Shows all active dispatches |
426
+ | `/dispatch retry CT-123` | Re-runs a stuck dispatch |
427
+ | `/dispatch status CT-123` | Detailed dispatch info |
428
+ | Add `<!-- repos: api, frontend -->` to issue body | Multi-repo dispatch |
429
+
430
+ ---
431
+
432
+ ## Configuration
433
+
434
+ Add settings under the plugin entry in `openclaw.json`:
435
+
436
+ ```json
437
+ {
438
+ "plugins": {
439
+ "entries": {
440
+ "openclaw-linear": {
441
+ "config": {
442
+ "defaultAgentId": "coder",
443
+ "maxReworkAttempts": 2,
444
+ "enableAudit": true
445
+ }
446
+ }
447
+ }
448
+ }
449
+ }
336
450
  ```
337
451
 
338
- ### 6. Configure Agents
452
+ ### Plugin Settings
339
453
 
340
- Create `~/.openclaw/agent-profiles.json`:
454
+ | Key | Type | Default | What it does |
455
+ |---|---|---|---|
456
+ | `defaultAgentId` | string | `"default"` | Which agent runs the pipeline |
457
+ | `classifierAgentId` | string | — | Agent for intent classification (use a small/fast model like Haiku) |
458
+ | `plannerReviewModel` | string | auto | Cross-model plan reviewer: `"claude"`, `"codex"`, or `"gemini"`. Auto-detects the complement of your primary model. |
459
+ | `enableAudit` | boolean | `true` | Run auditor after implementation |
460
+ | `enableOrchestration` | boolean | `true` | Allow `spawn_agent` / `ask_agent` tools |
461
+ | `maxReworkAttempts` | number | `2` | Max audit failures before escalation |
462
+ | `codexBaseRepo` | string | `"/home/claw/ai-workspace"` | Git repo for worktrees |
463
+ | `worktreeBaseDir` | string | `"~/.openclaw/worktrees"` | Where worktrees are created |
464
+ | `repos` | object | — | Multi-repo map (see [Multi-Repo](#multi-repo)) |
465
+ | `dispatchStatePath` | string | `"~/.openclaw/linear-dispatch-state.json"` | Dispatch state file |
466
+ | `planningStatePath` | string | `"~/.openclaw/linear-planning-state.json"` | Planning session state file |
467
+ | `promptsPath` | string | — | Custom prompts file path |
468
+ | `notifications` | object | — | Notification targets (see [Notifications](#notifications)) |
469
+ | `inactivitySec` | number | `120` | Kill agent if silent this long |
470
+ | `maxTotalSec` | number | `7200` | Max total agent session time |
471
+ | `toolTimeoutSec` | number | `600` | Max single `code_run` time |
472
+ | `claudeApiKey` | string | — | Anthropic API key for Claude CLI (passed as `ANTHROPIC_API_KEY` env var). Required if using Claude backend. |
473
+
474
+ ### Environment Variables
475
+
476
+ | Variable | Required | What it does |
477
+ |---|---|---|
478
+ | `LINEAR_CLIENT_ID` | Yes | OAuth app client ID |
479
+ | `LINEAR_CLIENT_SECRET` | Yes | OAuth app client secret |
480
+ | `LINEAR_API_KEY` | No | Personal API key (fallback) |
481
+
482
+ ### Agent Profiles
483
+
484
+ Define your agents in `~/.openclaw/agent-profiles.json`:
341
485
 
342
486
  ```json
343
487
  {
344
488
  "agents": {
345
489
  "coder": {
346
490
  "label": "Coder",
347
- "mission": "Full-stack engineer. Plans, implements, and ships code.",
491
+ "mission": "Full-stack engineer. Plans, implements, ships.",
348
492
  "isDefault": true,
349
493
  "mentionAliases": ["coder"],
350
494
  "avatarUrl": "https://example.com/coder.png",
@@ -356,27 +500,30 @@ Create `~/.openclaw/agent-profiles.json`:
356
500
  },
357
501
  "qa": {
358
502
  "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
- }
503
+ "mission": "Test engineer. Reviews code, writes tests.",
504
+ "mentionAliases": ["qa", "tester"]
366
505
  }
367
506
  }
368
507
  }
369
508
  ```
370
509
 
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.
510
+ One agent must have `"isDefault": true` that's the one that handles triage and the dispatch pipeline.
511
+
512
+ ### Coding Tools
372
513
 
373
- ### 7. Configure Coding Tools
514
+ Create `coding-tools.json` in the plugin root to configure which CLI backend agents use:
374
515
 
375
- Create `coding-tools.json` in the plugin root:
516
+ > **Warning Claude Code (Anthropic) and headless/automated usage**
517
+ >
518
+ > Calling Claude Code via CLI in a headless or automated context (which is how this plugin
519
+ > uses it) may violate [Anthropic's Terms of Service](https://www.anthropic.com/terms).
520
+ > The default backend is **Codex CLI** (OpenAI). **Gemini CLI** (Google) is used as the
521
+ > cross-model reviewer. If you choose to use Claude despite this, you do so at your own risk.
522
+ > See [Claude API Key](#claude-api-key) below for opt-in configuration.
376
523
 
377
524
  ```json
378
525
  {
379
- "codingTool": "claude",
526
+ "codingTool": "codex",
380
527
  "agentCodingTools": {},
381
528
  "backends": {
382
529
  "claude": { "aliases": ["claude", "claude code", "anthropic"] },
@@ -386,166 +533,155 @@ Create `coding-tools.json` in the plugin root:
386
533
  }
387
534
  ```
388
535
 
389
- ### 8. Install linearis
536
+ The agent calls `code_run` without knowing which backend is active. Resolution order: explicit `backend` parameter > per-agent override > global default > `"codex"`.
390
537
 
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
538
+ #### Claude API Key
398
539
 
399
- ```bash
400
- systemctl --user restart openclaw-gateway
401
- ```
540
+ If you opt in to using Claude as a backend (despite the TOS concerns noted above), you can
541
+ provide an Anthropic API key so the Claude CLI authenticates via API key instead of its
542
+ built-in interactive auth.
402
543
 
403
- Check logs for a clean startup:
544
+ Set `claudeApiKey` in the plugin config:
404
545
 
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)
546
+ ```json
547
+ {
548
+ "plugins": {
549
+ "entries": {
550
+ "openclaw-linear": {
551
+ "config": {
552
+ "claudeApiKey": "sk-ant-..."
553
+ }
554
+ }
555
+ }
556
+ }
557
+ }
408
558
  ```
409
559
 
410
- Test the webhook:
411
-
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"
417
- ```
560
+ The key is passed to the Claude CLI subprocess as the `ANTHROPIC_API_KEY` environment variable.
561
+ You can also set `ANTHROPIC_API_KEY` as a process-level environment variable (e.g., in your
562
+ systemd unit file) as a fallback. The plugin config value takes precedence if both are set.
418
563
 
419
564
  ---
420
565
 
421
- ## Usage
566
+ ## Notifications
422
567
 
423
- Once set up, the plugin responds to Linear events automatically:
568
+ Get notified when dispatches start, pass audit, fail, or get stuck.
424
569
 
425
- | What you do in Linear | What happens |
426
- |---|---|
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"` |
570
+ ### Setup
571
+
572
+ ```json
573
+ {
574
+ "notifications": {
575
+ "targets": [
576
+ { "channel": "discord", "target": "1471743433566715974" },
577
+ { "channel": "telegram", "target": "-1003884997363" },
578
+ { "channel": "slack", "target": "C0123456789", "accountId": "my-acct" }
579
+ ],
580
+ "events": {
581
+ "auditing": false
582
+ },
583
+ "richFormat": true
584
+ }
585
+ }
586
+ ```
436
587
 
437
- ### Pipeline Behavior
588
+ - **`targets`** — Where to send notifications (channel name + ID)
589
+ - **`events`** — Toggle specific events off (all on by default)
590
+ - **`richFormat`** — Set to `true` for Discord embeds with colors and Telegram HTML formatting
438
591
 
439
- When an issue is assigned:
592
+ ### Events
440
593
 
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.
594
+ | Event | When it fires |
595
+ |---|---|
596
+ | `dispatch` | Issue dispatched to pipeline |
597
+ | `working` | Worker started |
598
+ | `auditing` | Audit in progress |
599
+ | `audit_pass` | Audit passed, issue done |
600
+ | `audit_fail` | Audit failed, worker retrying |
601
+ | `escalation` | Too many failures, needs human |
602
+ | `stuck` | Dispatch stale for 2+ hours |
603
+ | `watchdog_kill` | Agent killed for inactivity |
447
604
 
448
- Workers **cannot** mark issues as done -- that's handled entirely by plugin verdict processing code.
605
+ ### Test It
606
+
607
+ ```bash
608
+ openclaw openclaw-linear notify test # Test all targets
609
+ openclaw openclaw-linear notify test --channel discord # Test one channel
610
+ openclaw openclaw-linear notify status # Show config
611
+ ```
449
612
 
450
613
  ---
451
614
 
452
- ## Configuration
615
+ ## Prompt Customization
453
616
 
454
- ### Plugin Config
617
+ Worker, audit, and rework prompts live in `prompts.yaml`. You can customize them without rebuilding.
455
618
 
456
- Set in `openclaw.json` under the plugin entry:
619
+ ### Three Layers
457
620
 
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 |
621
+ Prompts merge in this order (later layers override earlier ones):
474
622
 
475
- ### Environment Variables
623
+ 1. **Built-in defaults** — Ship with the plugin, always available
624
+ 2. **Your global file** — Set `promptsPath` in config to point to your custom YAML
625
+ 3. **Per-project file** — Drop a `prompts.yaml` in the worktree's `.claw/` folder
476
626
 
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) |
627
+ Each layer only overrides the specific sections you define. Everything else keeps its default.
484
628
 
485
- ### Agent Profile Fields
629
+ ### Example Custom Prompts
486
630
 
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) |
631
+ ```yaml
632
+ worker:
633
+ system: "You are a senior engineer. Write clean, tested code."
634
+ task: |
635
+ Issue: {{identifier}} {{title}}
497
636
 
498
- ---
637
+ {{description}}
499
638
 
500
- ## Prompt Customization
639
+ Workspace: {{worktreePath}}
501
640
 
502
- Worker, audit, and rework prompts live in `prompts.yaml`. Edit to customize without rebuilding.
641
+ Implement this issue. Write tests. Commit your work.
503
642
 
504
- ### Managing Prompts
643
+ audit:
644
+ system: "You are a strict code auditor."
505
645
 
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
646
+ rework:
647
+ addendum: |
648
+ PREVIOUS AUDIT FAILED. Fix these gaps:
649
+ {{gaps}}
510
650
  ```
511
651
 
512
652
  ### Template Variables
513
653
 
514
- | Variable | Description |
654
+ | Variable | What it contains |
515
655
  |---|---|
516
- | `{{identifier}}` | Issue identifier (e.g., `API-123`) |
656
+ | `{{identifier}}` | Issue ID (e.g., `API-123`) |
517
657
  | `{{title}}` | Issue title |
518
658
  | `{{description}}` | Full issue body |
519
659
  | `{{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) |
660
+ | `{{tier}}` | Complexity tier (junior/medior/senior) |
661
+ | `{{attempt}}` | Current attempt number |
662
+ | `{{gaps}}` | Audit gaps from previous attempt |
663
+ | `{{projectName}}` | Project name (planner prompts) |
664
+ | `{{planSnapshot}}` | Current plan structure (planner prompts) |
665
+ | `{{reviewModel}}` | Name of cross-model reviewer (planner review) |
666
+ | `{{crossModelFeedback}}` | Review recommendations (planner review) |
523
667
 
524
- ### Override Path
668
+ ### CLI
525
669
 
526
- ```json
527
- {
528
- "plugins": {
529
- "entries": {
530
- "openclaw-linear": {
531
- "config": {
532
- "promptsPath": "/path/to/my/prompts.yaml"
533
- }
534
- }
535
- }
536
- }
537
- }
670
+ ```bash
671
+ openclaw openclaw-linear prompts show # View current prompts
672
+ openclaw openclaw-linear prompts path # Show file path
673
+ openclaw openclaw-linear prompts validate # Check for errors
538
674
  ```
539
675
 
540
676
  ---
541
677
 
542
- ## Notifications
678
+ ## Multi-Repo
543
679
 
544
- Dispatch lifecycle events fan out to any combination of OpenClaw channels -- Discord, Slack, Telegram, Signal, or any channel the runtime supports.
680
+ 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
681
 
546
- ### Configuration
682
+ ### Step 1: Tell the plugin where your repos live
547
683
 
548
- Add a `notifications` object to your plugin config:
684
+ 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
685
 
550
686
  ```json
551
687
  {
@@ -553,15 +689,10 @@ Add a `notifications` object to your plugin config:
553
689
  "entries": {
554
690
  "openclaw-linear": {
555
691
  "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
- }
692
+ "repos": {
693
+ "api": "/home/claw/repos/api",
694
+ "frontend": "/home/claw/repos/frontend",
695
+ "shared": "/home/claw/repos/shared-libs"
565
696
  }
566
697
  }
567
698
  }
@@ -570,162 +701,301 @@ Add a `notifications` object to your plugin config:
570
701
  }
571
702
  ```
572
703
 
573
- **`targets`** -- Array of notification destinations. Each target specifies:
704
+ Restart the gateway after saving: `systemctl --user restart openclaw-gateway`
574
705
 
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) |
706
+ ### Step 1.5: Sync labels to Linear (optional)
580
707
 
581
- **`events`** -- Per-event-type toggles. All events are enabled by default. Set to `false` to suppress.
708
+ If you plan to use labels (Method B below) to tag issues, run this to create the `repo:xxx` labels automatically:
582
709
 
583
- ### Events
710
+ ```bash
711
+ openclaw openclaw-linear repos sync
712
+ ```
584
713
 
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).` |
714
+ This reads your `repos` config and creates matching labels (`repo:api`, `repo:frontend`, etc.) in every Linear team. To preview without creating anything:
595
715
 
596
- ### Delivery
716
+ ```bash
717
+ openclaw openclaw-linear repos check
718
+ ```
597
719
 
598
- Messages route through OpenClaw's native runtime channel API:
720
+ 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
721
 
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
722
+ ### Step 2: Tag the issue
605
723
 
606
- Failures are isolated per target -- one channel going down doesn't block the others.
724
+ When you write an issue in Linear that needs multiple repos, tell the plugin which ones. Pick **one** of these methods:
607
725
 
608
- ### Notify CLI
726
+ #### Method A: HTML comment in the issue body (recommended)
609
727
 
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
728
+ Put this line anywhere in the issue description — it's invisible in Linear's UI:
729
+
730
+ ```
731
+ <!-- repos: api, frontend -->
732
+ ```
733
+
734
+ Full example of what an issue body might look like:
735
+
736
+ ```
737
+ The search endpoint needs to be added to the API, and the frontend
738
+ needs a new search page that calls it.
739
+
740
+ <!-- repos: api, frontend -->
741
+
742
+ Acceptance criteria:
743
+ - GET /api/search?q=term returns results
744
+ - /search page renders results with pagination
615
745
  ```
616
746
 
747
+ #### Method B: Linear labels
748
+
749
+ 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.
750
+
751
+ #### Method C: Do nothing (config default)
752
+
753
+ 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.
754
+
755
+ ### What happens when you dispatch
756
+
757
+ When the agent picks up a multi-repo issue, the dispatch comment tells you:
758
+
759
+ > **Dispatched** as **senior** (anthropic/claude-opus-4-6)
760
+ >
761
+ > Worktrees:
762
+ > - `api` → `/home/claw/worktrees/ENG-100/api`
763
+ > - `frontend` → `/home/claw/worktrees/ENG-100/frontend`
764
+ >
765
+ > Branch: `codex/ENG-100`
766
+
767
+ The agent gets access to all the worktrees and can edit files across repos in one session. Each repo gets its own git branch.
768
+
769
+ ### Priority order
770
+
771
+ If an issue has both a body marker and labels, the body marker wins. Full order:
772
+
773
+ 1. `<!-- repos: ... -->` in the issue body
774
+ 2. `repo:xxx` labels on the issue
775
+ 3. `codexBaseRepo` from config (single repo fallback)
776
+
777
+ ### Common mistakes
778
+
779
+ | Problem | Fix |
780
+ |---|---|
781
+ | Agent only sees one repo | The name in `<!-- repos: api -->` must exactly match a key in your `repos` config. Check spelling. |
782
+ | "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. |
783
+ | Comment marker not detected | Must be `<!-- repos: name1, name2 -->` with the exact format. No extra spaces around `<!--` or `-->`. |
784
+ | Labels not picked up | Labels must be formatted `repo:name` (lowercase, no spaces). The `name` part must match a `repos` config key. |
785
+
617
786
  ---
618
787
 
619
- ## Coding Tool (`code_run`)
788
+ ## Dispatch Management
620
789
 
621
- One tool dispatches to three CLI backends. Agents call `code_run` without knowing which backend is active.
790
+ ### Slash Commands
622
791
 
623
- ### Supported Backends
792
+ Type these in any agent session — they run instantly, no AI involved:
624
793
 
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` |
794
+ | Command | What it does |
795
+ |---|---|
796
+ | `/dispatch list` | Show all active dispatches with age, tier, status |
797
+ | `/dispatch status CT-123` | Detailed info for one dispatch |
798
+ | `/dispatch retry CT-123` | Re-run a stuck dispatch |
799
+ | `/dispatch escalate CT-123 "needs review"` | Force a dispatch to stuck status |
630
800
 
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).
801
+ ### Gateway API
632
802
 
633
- ### Backend Resolution Priority
803
+ For programmatic access, the plugin registers these RPC methods:
634
804
 
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"`
805
+ | Method | What it does |
806
+ |---|---|
807
+ | `dispatch.list` | List dispatches (filterable by status, tier) |
808
+ | `dispatch.get` | Get full dispatch details |
809
+ | `dispatch.retry` | Re-dispatch a stuck issue |
810
+ | `dispatch.escalate` | Force-stuck with a reason |
811
+ | `dispatch.cancel` | Remove an active dispatch |
812
+ | `dispatch.stats` | Counts by status and tier |
639
813
 
640
814
  ---
641
815
 
642
- ## Inactivity Watchdog
816
+ ## Watchdog
817
+
818
+ If an agent goes silent (LLM timeout, API hang, CLI lockup), the watchdog handles it automatically:
643
819
 
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.
820
+ 1. No output for `inactivitySec` kill and retry once
821
+ 2. Second silence → escalate to stuck (you get notified, see [Stage 6](#stage-6-timeout-if-the-agent-goes-silent) above)
645
822
 
646
- ### How It Works
823
+ | Setting | Default | What it controls |
824
+ |---|---|---|
825
+ | `inactivitySec` | 120s | Kill if no output for this long |
826
+ | `maxTotalSec` | 7200s (2 hrs) | Hard ceiling on total session time |
827
+ | `toolTimeoutSec` | 600s (10 min) | Max time for a single `code_run` call |
647
828
 
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)"]
829
+ Configure per-agent in `agent-profiles.json` or globally in plugin config.
830
+
831
+ ---
832
+
833
+ ## Testing & Verification
834
+
835
+ ### Health check
836
+
837
+ 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:
838
+
839
+ ```bash
840
+ openclaw openclaw-linear doctor
660
841
  ```
661
842
 
662
- ### Three Timeout Dimensions
843
+ Example output:
663
844
 
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 |
845
+ ```
846
+ ┌──────────────────────────────────────────────┐
847
+ │ Linear Plugin Doctor │
848
+ └──────────────────────────────────────────────┘
669
849
 
670
- ### Config Resolution Order
850
+ Authentication & Tokens
851
+ ✔ Access token found (source: profile)
852
+ ✔ Token not expired (23h remaining)
853
+ ✔ API reachable — logged in as Test (TestOrg)
671
854
 
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
855
+ Agent Configuration
856
+ agent-profiles.json loaded (2 agents)
857
+ Default agent: coder
675
858
 
676
- ### Per-Agent Configuration
859
+ Coding Tools
860
+ ✔ coding-tools.json loaded (default: codex)
861
+ ✔ codex: found at /usr/local/bin/codex
677
862
 
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
- }
863
+ Files & Directories
864
+ ✔ Dispatch state: 1 active, 5 completed
865
+ Prompts valid (5/5 sections, 4/4 variables)
866
+
867
+ Connectivity
868
+ Linear API reachable
869
+ Webhook gateway responding
870
+
871
+ Dispatch Health
872
+ ✔ No stale dispatches
873
+ 2 completed dispatches older than 7 days
874
+ → Run: openclaw openclaw-linear doctor --fix to clean up
875
+
876
+ Summary: 11 passed, 1 warning, 0 errors
697
877
  ```
698
878
 
699
- ### Artifact Logging
879
+ Every warning and error includes a `→` line telling you what to do. Run `doctor --fix` to auto-repair what it can.
700
880
 
701
- Every dispatch writes structured artifacts to `.claw/` in the worktree:
881
+ ### Unit tests
702
882
 
883
+ 454 tests covering the full pipeline — triage, dispatch, audit, planning, intent classification, cross-model review, notifications, and infrastructure:
884
+
885
+ ```bash
886
+ cd ~/claw-extensions/linear
887
+ npx vitest run # Run all tests
888
+ npx vitest run --reporter=verbose # See every test name
889
+ npx vitest run src/pipeline/ # Just pipeline tests
703
890
  ```
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
891
+
892
+ ### UAT (live integration tests)
893
+
894
+ The UAT script runs against your real Linear workspace. It creates actual issues, triggers the pipeline, and verifies the results.
895
+
896
+ ```bash
897
+ # Run all UAT scenarios
898
+ npx tsx scripts/uat-linear.ts
899
+
900
+ # Run a specific scenario
901
+ npx tsx scripts/uat-linear.ts --test dispatch
902
+ npx tsx scripts/uat-linear.ts --test planning
903
+ npx tsx scripts/uat-linear.ts --test mention
904
+ npx tsx scripts/uat-linear.ts --test intent
711
905
  ```
712
906
 
713
- Watchdog kills are logged to `log.jsonl` with phase `"watchdog"`:
907
+ **What each scenario does:**
908
+
909
+ #### `--test dispatch` (Single issue, full pipeline)
910
+
911
+ 1. Creates a test issue in Linear
912
+ 2. Assigns it to the agent
913
+ 3. Waits for the dispatch comment (confirms the agent picked it up)
914
+ 4. Waits for the audit result (pass, fail, or escalation)
915
+ 5. Reports success/failure with timing
916
+
917
+ **Expected output:**
714
918
 
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
- }
919
+ ```
920
+ [dispatch] Created issue ENG-200: "UAT: simple config tweak"
921
+ [dispatch] Assigned to agent — waiting for dispatch comment...
922
+ [dispatch] ✔ Dispatch confirmed (12s) — assessed as junior
923
+ [dispatch] Waiting for audit result...
924
+ [dispatch] ✔ Audit passed (94s) — issue marked done
925
+ [dispatch] Total: 106s
926
+ ```
927
+
928
+ #### `--test planning` (Project planning flow)
929
+
930
+ 1. Creates a root issue in a test project
931
+ 2. Posts `plan this project` comment
932
+ 3. Waits for the planner's welcome message
933
+ 4. Posts feature requirements
934
+ 5. Waits for the planner to create issues
935
+ 6. Posts `finalize plan`
936
+ 7. Waits for plan approval or failure
937
+
938
+ **Expected output:**
939
+
940
+ ```
941
+ [planning] Created project "UAT Planning Test"
942
+ [planning] Posted "plan this project" — waiting for welcome...
943
+ [planning] ✔ Welcome received (8s)
944
+ [planning] Posted feature description — waiting for response...
945
+ [planning] ✔ Planner created 3 issues (15s)
946
+ [planning] Posted "finalize plan" — waiting for audit...
947
+ [planning] ✔ Plan approved (6s) — 3 issues queued for dispatch
948
+ [planning] Total: 29s
949
+ ```
950
+
951
+ #### `--test mention` (Agent routing)
952
+
953
+ 1. Creates a test issue
954
+ 2. Posts a comment mentioning a specific agent (e.g., `@kaylee`)
955
+ 3. Waits for that agent to respond
956
+ 4. Verifies the response came from the right agent
957
+
958
+ **Expected output:**
959
+
960
+ ```
961
+ [mention] Created issue ENG-201
962
+ [mention] Posted "@kaylee analyze this issue"
963
+ [mention] ✔ Kaylee responded (18s)
964
+ [mention] Total: 18s
965
+ ```
966
+
967
+ #### `--test intent` (Natural language routing)
968
+
969
+ 1. Creates a test issue and posts a question (no `@mention`)
970
+ 2. Verifies the bot responds (not silently dropped)
971
+ 3. Posts a comment with an agent name but no `@` prefix
972
+ 4. Verifies that agent responds
973
+ 5. Tests plan review flow with cross-model audit
974
+
975
+ **Expected output:**
976
+
977
+ ```
978
+ [intent] Created issue ENG-202
979
+ [intent] Posted "what can I do with this?" — waiting for response...
980
+ [intent] ✔ Bot responded to question (12s)
981
+ [intent] Posted "hey kaylee analyze this" — waiting for response...
982
+ [intent] ✔ Kaylee responded without @mention (15s)
983
+ [intent] Total: 27s
984
+ ```
985
+
986
+ ### Verify notifications
987
+
988
+ ```bash
989
+ openclaw openclaw-linear notify test # Send test to all targets
990
+ openclaw openclaw-linear notify test --channel discord # Test one channel
991
+ openclaw openclaw-linear notify status # Show what's configured
992
+ ```
993
+
994
+ ### Verify prompts
995
+
996
+ ```bash
997
+ openclaw openclaw-linear prompts validate # Check for template errors
998
+ openclaw openclaw-linear prompts show # View the active prompts
729
999
  ```
730
1000
 
731
1001
  ---
@@ -733,20 +1003,39 @@ Watchdog kills are logged to `log.jsonl` with phase `"watchdog"`:
733
1003
  ## CLI Reference
734
1004
 
735
1005
  ```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
1006
+ # Auth & status
1007
+ openclaw openclaw-linear auth # Run OAuth flow
1008
+ openclaw openclaw-linear status # Check connection
1009
+
1010
+ # Worktrees
1011
+ openclaw openclaw-linear worktrees # List active worktrees
739
1012
  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
1013
+
1014
+ # Multi-repo
1015
+ openclaw openclaw-linear repos check # Validate paths, preview labels
1016
+ openclaw openclaw-linear repos sync # Create missing repo: labels in Linear
1017
+
1018
+ # Prompts
1019
+ openclaw openclaw-linear prompts show # View current prompts
1020
+ openclaw openclaw-linear prompts path # Show file path
1021
+ openclaw openclaw-linear prompts validate # Check for errors
1022
+
1023
+ # Notifications
1024
+ openclaw openclaw-linear notify status # Show targets & events
1025
+ openclaw openclaw-linear notify test # Test all targets
1026
+ openclaw openclaw-linear notify test --channel discord # Test one channel
1027
+ openclaw openclaw-linear notify setup # Interactive setup
1028
+
1029
+ # Dispatch
1030
+ /dispatch list # Active dispatches
1031
+ /dispatch status <identifier> # Dispatch details
1032
+ /dispatch retry <identifier> # Re-run stuck dispatch
1033
+ /dispatch escalate <identifier> [reason] # Force to stuck
1034
+
1035
+ # Health
1036
+ openclaw openclaw-linear doctor # Run health checks
1037
+ openclaw openclaw-linear doctor --fix # Auto-fix issues
1038
+ openclaw openclaw-linear doctor --json # JSON output
750
1039
  ```
751
1040
 
752
1041
  ---
@@ -759,25 +1048,34 @@ Quick checks:
759
1048
  systemctl --user status openclaw-gateway # Is the gateway running?
760
1049
  openclaw openclaw-linear status # Is the token valid?
761
1050
  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
1051
  ```
765
1052
 
766
1053
  ### Common Issues
767
1054
 
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.
1055
+ | Problem | Fix |
1056
+ |---|---|
1057
+ | Agent goes silent | Watchdog auto-kills after `inactivitySec` and retries. Check logs for `Watchdog KILL`. |
1058
+ | Dispatch stuck after watchdog | Both retries failed. Check `.claw/log.jsonl`. Re-assign issue to restart. |
1059
+ | `code_run` uses wrong backend | Check `coding-tools.json` explicit backend > per-agent > global default. |
1060
+ | Webhook events not arriving | Both webhooks must point to `/linear/webhook`. Check tunnel is running. |
1061
+ | OAuth token expired | Auto-refreshes. If stuck, re-run `openclaw openclaw-linear auth` and restart. |
1062
+ | Audit always fails | Run `openclaw openclaw-linear prompts validate` to check prompt syntax. |
1063
+ | Multi-repo not detected | Markers must be `<!-- repos: name1, name2 -->`. Names must match `repos` config keys. |
1064
+ | `/dispatch` not responding | Restart gateway. Check plugin loaded with `openclaw doctor`. |
1065
+ | Comments ignored (no response) | Check logs for intent classification results. If classifier fails, regex fallback may not match. |
1066
+ | Intent classifier slow | Set `classifierAgentId` to a small model agent (Haiku). Default uses your primary model. |
1067
+ | Cross-model review fails | The reviewer model CLI must be installed. Check logs for "cross-model review unavailable". |
1068
+ | Rich notifications are plain text | Set `"richFormat": true` in notifications config. |
1069
+ | Gateway rejects config keys | Strict validator. Run `openclaw doctor --fix`. |
1070
+
1071
+ For detailed diagnostics, see [docs/troubleshooting.md](docs/troubleshooting.md).
1072
+
1073
+ ---
1074
+
1075
+ ## Further Reading
1076
+
1077
+ - [Architecture](docs/architecture.md) — Internal design, state machines, diagrams
1078
+ - [Troubleshooting](docs/troubleshooting.md) — Diagnostic commands, curl examples, log analysis
781
1079
 
782
1080
  ---
783
1081