@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.
- package/README.md +834 -536
- package/index.ts +1 -1
- package/openclaw.plugin.json +3 -2
- package/package.json +1 -1
- package/prompts.yaml +46 -6
- package/src/__test__/fixtures/linear-responses.ts +75 -0
- package/src/__test__/fixtures/webhook-payloads.ts +113 -0
- package/src/__test__/helpers.ts +133 -0
- package/src/agent/agent.test.ts +192 -0
- package/src/agent/agent.ts +26 -1
- package/src/api/linear-api.test.ts +93 -1
- package/src/api/linear-api.ts +37 -1
- package/src/gateway/dispatch-methods.test.ts +409 -0
- package/src/infra/cli.ts +176 -1
- package/src/infra/commands.test.ts +276 -0
- package/src/infra/doctor.test.ts +19 -0
- package/src/infra/doctor.ts +30 -25
- package/src/infra/multi-repo.test.ts +163 -0
- package/src/infra/multi-repo.ts +29 -0
- package/src/infra/notify.test.ts +155 -16
- package/src/infra/notify.ts +26 -15
- package/src/infra/observability.test.ts +85 -0
- package/src/pipeline/artifacts.test.ts +26 -3
- package/src/pipeline/dispatch-state.ts +1 -0
- package/src/pipeline/e2e-dispatch.test.ts +584 -0
- package/src/pipeline/e2e-planning.test.ts +478 -0
- package/src/pipeline/intent-classify.test.ts +285 -0
- package/src/pipeline/intent-classify.ts +259 -0
- package/src/pipeline/pipeline.test.ts +69 -0
- package/src/pipeline/pipeline.ts +47 -18
- package/src/pipeline/planner.test.ts +159 -40
- package/src/pipeline/planner.ts +108 -60
- package/src/pipeline/tier-assess.test.ts +89 -0
- package/src/pipeline/webhook.ts +424 -251
- package/src/tools/claude-tool.ts +6 -0
- package/src/tools/cli-shared.test.ts +155 -0
- package/src/tools/code-tool.test.ts +210 -0
- package/src/tools/code-tool.ts +2 -2
- package/src/tools/dispatch-history-tool.test.ts +315 -0
- package/src/tools/planner-tools.test.ts +1 -1
- package/src/tools/planner-tools.ts +10 -2
package/README.md
CHANGED
|
@@ -3,348 +3,492 @@
|
|
|
3
3
|
[](https://github.com/calltelemetry/openclaw)
|
|
4
4
|
[](LICENSE)
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
Connect Linear to AI agents. Issues get triaged, implemented, and audited — automatically.
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
-
##
|
|
11
|
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
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
|
-
##
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
58
|
+
### 4. Authorize
|
|
93
59
|
|
|
94
|
-
```
|
|
95
|
-
|
|
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
|
-
|
|
64
|
+
This opens your browser. Approve the authorization, then restart:
|
|
107
65
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
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
|
-
###
|
|
70
|
+
### 5. Verify
|
|
118
71
|
|
|
119
|
-
```
|
|
120
|
-
|
|
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
|
-
|
|
76
|
+
You should see a valid token and connected status. Check the gateway logs for a clean startup:
|
|
131
77
|
|
|
132
|
-
|
|
78
|
+
```
|
|
79
|
+
Linear agent extension registered (agent: default, token: profile, orchestration: enabled)
|
|
80
|
+
```
|
|
133
81
|
|
|
134
|
-
|
|
82
|
+
Test the webhook endpoint:
|
|
135
83
|
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
```
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
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
|
-
|
|
117
|
+
### Stage 1: Triage (automatic)
|
|
163
118
|
|
|
164
|
-
|
|
119
|
+
**Trigger:** You create a new issue.
|
|
165
120
|
|
|
166
|
-
|
|
121
|
+
The agent reads your issue, estimates story points, adds labels, sets priority, and posts an assessment comment — all within seconds.
|
|
167
122
|
|
|
168
|
-
|
|
169
|
-
2. **OAuth app webhook** (Settings > API > Applications) -- `AgentSessionEvent` (created/prompted)
|
|
123
|
+
**What you'll see in Linear:**
|
|
170
124
|
|
|
171
|
-
|
|
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
|
-
|
|
127
|
+
The estimate, labels, and priority are applied silently to the issue fields. You don't need to do anything.
|
|
174
128
|
|
|
175
|
-
|
|
129
|
+
### Stage 2: Dispatch (you assign the issue)
|
|
176
130
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
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
|
-
##
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
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
|
-
##
|
|
315
|
+
## Planning a Project
|
|
239
316
|
|
|
240
|
-
|
|
317
|
+
For larger work, the planner helps you break a project into issues with dependencies, then dispatches them automatically.
|
|
241
318
|
|
|
242
|
-
|
|
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
|
-
|
|
321
|
+
Comment on any issue that belongs to a Linear project — use natural language:
|
|
249
322
|
|
|
250
|
-
|
|
251
|
-
openclaw plugins install @calltelemetry/openclaw-linear
|
|
252
|
-
```
|
|
323
|
+
> "let's plan out the features for this project"
|
|
253
324
|
|
|
254
|
-
|
|
325
|
+
The planner enters **interview mode** and asks you questions one at a time:
|
|
255
326
|
|
|
256
|
-
|
|
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
|
-
|
|
259
|
-
- **Redirect URI:** `https://<your-domain>/linear/oauth/callback`
|
|
260
|
-
- Enable webhook events: **Agent Sessions**, **Comments**, **Issues**
|
|
331
|
+
### Build the plan
|
|
261
332
|
|
|
262
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
352
|
+
### Finalize & Cross-Model Review
|
|
274
353
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
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
|
-
|
|
359
|
+
**If validation passes, a cross-model review runs automatically:**
|
|
282
360
|
|
|
283
|
-
|
|
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
|
-
|
|
367
|
+
A different AI model (always the complement of your primary model) reviews the plan for gaps:
|
|
286
368
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
300
|
-
tunnel: <TUNNEL_ID>
|
|
301
|
-
credentials-file: ~/.cloudflared/<TUNNEL_ID>.json
|
|
382
|
+
**If validation fails:**
|
|
302
383
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
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
|
-
|
|
395
|
+
Fix the issues and try again. You can also say "cancel" or "stop planning" to exit without dispatching.
|
|
310
396
|
|
|
311
|
-
|
|
312
|
-
sudo cloudflared service install
|
|
313
|
-
sudo systemctl enable --now cloudflared
|
|
314
|
-
```
|
|
397
|
+
### DAG dispatch progress
|
|
315
398
|
|
|
316
|
-
|
|
399
|
+
After approval, issues are assigned to the agent automatically in dependency order. Up to 3 issues run in parallel.
|
|
317
400
|
|
|
318
|
-
|
|
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
|
-
|
|
403
|
+
When everything is done:
|
|
326
404
|
|
|
327
|
-
|
|
328
|
-
openclaw openclaw-linear auth
|
|
329
|
-
```
|
|
405
|
+
> `✅ Search Feature: complete (3/3 issues)`
|
|
330
406
|
|
|
331
|
-
|
|
407
|
+
If an issue gets stuck (all retries failed), dependent issues are blocked and you'll be notified.
|
|
332
408
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
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
|
-
###
|
|
452
|
+
### Plugin Settings
|
|
339
453
|
|
|
340
|
-
|
|
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,
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
514
|
+
Create `coding-tools.json` in the plugin root to configure which CLI backend agents use:
|
|
374
515
|
|
|
375
|
-
|
|
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": "
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
400
|
-
|
|
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
|
-
|
|
544
|
+
Set `claudeApiKey` in the plugin config:
|
|
404
545
|
|
|
405
|
-
```
|
|
406
|
-
|
|
407
|
-
|
|
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
|
-
|
|
411
|
-
|
|
412
|
-
|
|
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
|
-
##
|
|
566
|
+
## Notifications
|
|
422
567
|
|
|
423
|
-
|
|
568
|
+
Get notified when dispatches start, pass audit, fail, or get stuck.
|
|
424
569
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
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
|
-
|
|
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
|
-
|
|
592
|
+
### Events
|
|
440
593
|
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
615
|
+
## Prompt Customization
|
|
453
616
|
|
|
454
|
-
|
|
617
|
+
Worker, audit, and rework prompts live in `prompts.yaml`. You can customize them without rebuilding.
|
|
455
618
|
|
|
456
|
-
|
|
619
|
+
### Three Layers
|
|
457
620
|
|
|
458
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
###
|
|
629
|
+
### Example Custom Prompts
|
|
486
630
|
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
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
|
-
|
|
639
|
+
Workspace: {{worktreePath}}
|
|
501
640
|
|
|
502
|
-
|
|
641
|
+
Implement this issue. Write tests. Commit your work.
|
|
503
642
|
|
|
504
|
-
|
|
643
|
+
audit:
|
|
644
|
+
system: "You are a strict code auditor."
|
|
505
645
|
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
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 |
|
|
654
|
+
| Variable | What it contains |
|
|
515
655
|
|---|---|
|
|
516
|
-
| `{{identifier}}` | Issue
|
|
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}}` |
|
|
521
|
-
| `{{attempt}}` | Current attempt number
|
|
522
|
-
| `{{gaps}}` | Audit gaps from previous attempt
|
|
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
|
-
###
|
|
668
|
+
### CLI
|
|
525
669
|
|
|
526
|
-
```
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
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
|
-
##
|
|
678
|
+
## Multi-Repo
|
|
543
679
|
|
|
544
|
-
|
|
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
|
-
###
|
|
682
|
+
### Step 1: Tell the plugin where your repos live
|
|
547
683
|
|
|
548
|
-
Add a `
|
|
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
|
-
"
|
|
557
|
-
"
|
|
558
|
-
|
|
559
|
-
|
|
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
|
-
|
|
704
|
+
Restart the gateway after saving: `systemctl --user restart openclaw-gateway`
|
|
574
705
|
|
|
575
|
-
|
|
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
|
-
|
|
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
|
-
|
|
710
|
+
```bash
|
|
711
|
+
openclaw openclaw-linear repos sync
|
|
712
|
+
```
|
|
584
713
|
|
|
585
|
-
|
|
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
|
-
|
|
716
|
+
```bash
|
|
717
|
+
openclaw openclaw-linear repos check
|
|
718
|
+
```
|
|
597
719
|
|
|
598
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
726
|
+
#### Method A: HTML comment in the issue body (recommended)
|
|
609
727
|
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
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
|
-
##
|
|
788
|
+
## Dispatch Management
|
|
620
789
|
|
|
621
|
-
|
|
790
|
+
### Slash Commands
|
|
622
791
|
|
|
623
|
-
|
|
792
|
+
Type these in any agent session — they run instantly, no AI involved:
|
|
624
793
|
|
|
625
|
-
|
|
|
626
|
-
|
|
627
|
-
|
|
|
628
|
-
|
|
|
629
|
-
|
|
|
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
|
-
|
|
801
|
+
### Gateway API
|
|
632
802
|
|
|
633
|
-
|
|
803
|
+
For programmatic access, the plugin registers these RPC methods:
|
|
634
804
|
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
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
|
-
##
|
|
816
|
+
## Watchdog
|
|
817
|
+
|
|
818
|
+
If an agent goes silent (LLM timeout, API hang, CLI lockup), the watchdog handles it automatically:
|
|
643
819
|
|
|
644
|
-
|
|
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
|
-
|
|
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
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
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
|
-
|
|
843
|
+
Example output:
|
|
663
844
|
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
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
|
-
|
|
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
|
-
|
|
673
|
-
|
|
674
|
-
|
|
855
|
+
Agent Configuration
|
|
856
|
+
✔ agent-profiles.json loaded (2 agents)
|
|
857
|
+
✔ Default agent: coder
|
|
675
858
|
|
|
676
|
-
|
|
859
|
+
Coding Tools
|
|
860
|
+
✔ coding-tools.json loaded (default: codex)
|
|
861
|
+
✔ codex: found at /usr/local/bin/codex
|
|
677
862
|
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
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
|
-
|
|
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
|
-
```
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
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
|
-
|
|
737
|
-
openclaw openclaw-linear
|
|
738
|
-
openclaw openclaw-linear
|
|
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
|
-
|
|
741
|
-
|
|
742
|
-
openclaw openclaw-linear
|
|
743
|
-
openclaw openclaw-linear
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
openclaw openclaw-linear
|
|
747
|
-
openclaw openclaw-linear
|
|
748
|
-
openclaw openclaw-linear
|
|
749
|
-
|
|
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 |
|
|
769
|
-
|
|
770
|
-
| Agent goes silent
|
|
771
|
-
| Dispatch stuck after watchdog | Both
|
|
772
|
-
|
|
|
773
|
-
|
|
|
774
|
-
|
|
|
775
|
-
|
|
|
776
|
-
|
|
|
777
|
-
|
|
|
778
|
-
|
|
|
779
|
-
|
|
780
|
-
|
|
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
|
|