@qelos/aidev 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/.env.aidev.example +81 -62
  2. package/CONTRIBUTING.md +78 -78
  3. package/LICENSE +21 -21
  4. package/README.md +499 -467
  5. package/dist/__tests__/clickup-format.test.d.ts +2 -0
  6. package/dist/__tests__/clickup-format.test.d.ts.map +1 -0
  7. package/dist/__tests__/clickup-format.test.js +256 -0
  8. package/dist/__tests__/clickup-format.test.js.map +1 -0
  9. package/dist/__tests__/hooks.test.d.ts +2 -0
  10. package/dist/__tests__/hooks.test.d.ts.map +1 -0
  11. package/dist/__tests__/hooks.test.js +329 -0
  12. package/dist/__tests__/hooks.test.js.map +1 -0
  13. package/dist/__tests__/init.test.js +33 -0
  14. package/dist/__tests__/init.test.js.map +1 -1
  15. package/dist/__tests__/local-provider.test.js +31 -31
  16. package/dist/__tests__/platform.test.js +5 -5
  17. package/dist/__tests__/providers.test.js +166 -0
  18. package/dist/__tests__/providers.test.js.map +1 -1
  19. package/dist/__tests__/run.test.js +21 -8
  20. package/dist/__tests__/run.test.js.map +1 -1
  21. package/dist/cli.js +5 -1
  22. package/dist/cli.js.map +1 -1
  23. package/dist/commands/help.d.ts.map +1 -1
  24. package/dist/commands/help.js +67 -61
  25. package/dist/commands/help.js.map +1 -1
  26. package/dist/commands/init.d.ts +1 -0
  27. package/dist/commands/init.d.ts.map +1 -1
  28. package/dist/commands/init.js +125 -0
  29. package/dist/commands/init.js.map +1 -1
  30. package/dist/commands/run.d.ts +2 -1
  31. package/dist/commands/run.d.ts.map +1 -1
  32. package/dist/commands/run.js +248 -119
  33. package/dist/commands/run.js.map +1 -1
  34. package/dist/config.d.ts.map +1 -1
  35. package/dist/config.js +16 -1
  36. package/dist/config.js.map +1 -1
  37. package/dist/github.js +23 -23
  38. package/dist/hooks.d.ts +106 -0
  39. package/dist/hooks.d.ts.map +1 -0
  40. package/dist/hooks.js +146 -0
  41. package/dist/hooks.js.map +1 -0
  42. package/dist/providers/clickup-format.d.ts +16 -0
  43. package/dist/providers/clickup-format.d.ts.map +1 -0
  44. package/dist/providers/clickup-format.js +255 -0
  45. package/dist/providers/clickup-format.js.map +1 -0
  46. package/dist/providers/clickup.d.ts.map +1 -1
  47. package/dist/providers/clickup.js +8 -6
  48. package/dist/providers/clickup.js.map +1 -1
  49. package/dist/providers/index.d.ts.map +1 -1
  50. package/dist/providers/index.js +2 -1
  51. package/dist/providers/index.js.map +1 -1
  52. package/dist/providers/linear.js +70 -70
  53. package/dist/providers/monday.js +39 -39
  54. package/dist/providers/trello.d.ts +32 -0
  55. package/dist/providers/trello.d.ts.map +1 -0
  56. package/dist/providers/trello.js +227 -0
  57. package/dist/providers/trello.js.map +1 -0
  58. package/dist/types.d.ts +12 -0
  59. package/dist/types.d.ts.map +1 -1
  60. package/package.json +51 -50
  61. package/scripts/run-tests.cjs +18 -18
package/README.md CHANGED
@@ -1,467 +1,499 @@
1
- # @qelos/aidev
2
-
3
- [![npm version](https://img.shields.io/npm/v/%40qelos%2Faidev.svg?style=flat-square)](https://www.npmjs.com/package/@qelos/aidev)
4
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](./LICENSE)
5
- [![Node.js](https://img.shields.io/badge/node-%3E%3D18-brightgreen.svg?style=flat-square)](https://nodejs.org)
6
-
7
- **aidev** turns your tasks into merged code — automatically.
8
-
9
- It polls your task manager (ClickUp, Jira, Linear, Monday.com, Notion, or local markdown files), checks whether tasks are clear, runs Claude, Cursor, or Windsurf to implement them, pushes a branch, and moves the task to review. All without touching your keyboard.
10
-
11
- ```
12
- Task (ClickUp / Jira / Monday / Notion / local) → AI implements → git push → "in review"
13
- ```
14
-
15
- ---
16
-
17
- ## Table of Contents
18
-
19
- - [How it works](#how-it-works)
20
- - [Quick start](#quick-start)
21
- - [Commands](#commands)
22
- - [Concurrency lock](#concurrency-lock)
23
- - [Configuration](#configuration)
24
- - [AI agents](#ai-agents)
25
- - [Dev notes mode](#dev-notes-mode)
26
- - [Scheduling](#scheduling)
27
- - [Logging](#logging)
28
- - [Providers](#providers)
29
- - [Contributing](#contributing)
30
-
31
- ---
32
-
33
- ## How it works
34
-
35
- 1. **Fetch** — pulls all tasks tagged with your configured tag from ClickUp
36
- 2. **Filter** — skips done/cancelled tasks and tasks that already have a branch
37
- 3. **Clarify** — in `smart` mode, asks the AI if the task description is clear enough; if not, posts a question as a comment (prefixed with `[aidev]`) and marks the task `pending`
38
- 4. **Wait** — pending tasks are re-checked on the next run; if a human replied or the trigger word is found, implementation proceeds with the conversation as context
39
- 5. **Implement** — checks out a fresh branch (or reuses an existing one), runs your configured AI agent(s), falls back to the next agent if one fails
40
- 6. **Ship** — commits all changes, pushes the branch, posts a comment with the branch name and a PR link, moves the task to your "in review" status
41
-
42
- ---
43
-
44
- ## Quick start
45
-
46
- ```bash
47
- npm install -g @qelos/aidev
48
- ```
49
-
50
- Navigate to your project and run the interactive setup:
51
-
52
- ```bash
53
- cd my-project
54
- aidev init
55
- ```
56
-
57
- The wizard will ask for your ClickUp credentials, git settings, and preferred AI agents. Sensitive values (API keys) can be left blank if they are already set as environment variables in your shell.
58
-
59
- Once configured:
60
-
61
- ```bash
62
- aidev run
63
- ```
64
-
65
- ---
66
-
67
- ## Commands
68
-
69
- | Command | Description |
70
- |---|---|
71
- | `aidev init` | Interactive setup — creates `.env.aidev` |
72
- | `aidev run` | Process all open + pending-with-replies tasks |
73
- | `aidev run open` | Only open (non-pending) tasks |
74
- | `aidev run pending` | Only pending tasks — check for human replies |
75
- | `aidev stop` | Stop any running aidev process in the current directory |
76
- | `aidev schedule set` | Interactive cron picker for this directory |
77
- | `aidev schedule set "<expr>"` | Set a specific cron expression |
78
- | `aidev schedule get` | Show the current schedule for this directory |
79
- | `aidev help` | Show command and config reference |
80
-
81
- ### Global flags
82
-
83
- | Flag | Description |
84
- |---|---|
85
- | `-e, --env <path>` | Load config from a custom env file instead of `.env.aidev` |
86
- | `-V, --version` | Print version |
87
-
88
- **Examples**
89
-
90
- ```bash
91
- # Use a shared env file for a staging environment
92
- aidev --env /shared/.env.staging run
93
-
94
- # Only process tasks that are waiting for a reply
95
- aidev run pending
96
-
97
- # Schedule to run every 30 minutes
98
- aidev schedule set "*/30 * * * *"
99
- ```
100
-
101
- ---
102
-
103
- ## Concurrency lock
104
-
105
- `aidev run` writes a PID lock file (`.aidev.lock`) in the current directory when it starts and removes it when it finishes. If a second invocation detects a live process already holding the lock, it logs a warning and exits immediately — preventing two agents from committing to the same branch at the same time.
106
-
107
- ```
108
- $ aidev run
109
- [aidev] aidev is already running in this directory (PID 12345). Use "aidev stop" to terminate it.
110
- ```
111
-
112
- Use `aidev stop` to send `SIGTERM` to the running process and clean up the lock file:
113
-
114
- ```bash
115
- aidev stop
116
- ```
117
-
118
- Stale lock files (left behind by a crash) are detected automatically — the next `aidev run` will overwrite them if the stored PID is no longer alive.
119
-
120
- ---
121
-
122
- ## Configuration
123
-
124
- Run `aidev init` for an interactive setup, or create `.env.aidev` manually using `.env.aidev.example` as a template.
125
-
126
- ### Global env file (`AIDEV_ENV_EXTEND`)
127
-
128
- If you work across multiple projects, you can keep shared settings (API keys, agent list, etc.) in a single global file and reference it from each project's `.env.aidev`:
129
-
130
- ```bash
131
- # ~/.aidev.global
132
- CLICKUP_API_KEY=pk_...
133
- CLICKUP_TEAM_ID=123456
134
- AGENTS=claude,cursor
135
- ```
136
-
137
- ```bash
138
- # my-project/.env.aidev — project-specific values override the global ones
139
- AIDEV_ENV_EXTEND=~/.aidev.global
140
- CLICKUP_TAG=my-project
141
- ```
142
-
143
- **Priority order (highest → lowest):**
144
-
145
- 1. Shell environment variables (e.g. set in `~/.zshrc`) — never overwritten
146
- 2. Local `.env.aidev` values
147
- 3. `AIDEV_ENV_EXTEND` file values (global base)
148
-
149
- `AIDEV_ENV_EXTEND` can be set in two ways:
150
-
151
- - **Per-project** — add `AIDEV_ENV_EXTEND=/path/to/file` inside `.env.aidev`
152
- - **Shell-wide** — `export AIDEV_ENV_EXTEND=~/.aidev.global` in `~/.zshrc` (applies to every project automatically)
153
-
154
- `aidev init` will ask for this path and pre-fill it if the variable is already in your shell environment.
155
-
156
- ### ClickUp
157
-
158
- | Variable | Default | Description |
159
- |---|---|---|
160
- | `CLICKUP_API_KEY` | — | Personal API token — can be set as a shell env var |
161
- | `CLICKUP_TEAM_ID` | — | Workspace / team ID — can be set as a shell env var |
162
- | `CLICKUP_TAG` | — | Tasks with this tag will be picked up (set to `*` to match all tasks) |
163
- | `CLICKUP_PENDING_STATUS` | `pending` | Status name for "waiting for reply" |
164
- | `CLICKUP_IN_REVIEW_STATUS` | `review` | Status set after implementation |
165
- | `ASSIGNEE_TAG` | | Only process tasks assigned to this user (optional) |
166
- | `THINKING_TAG` | — | Tasks with this tag are analyzed and broken into sub-tasks before execution (optional) |
167
- | `NON_CODE_TAG` | — | Tasks with this tag run without git branching (optional) |
168
- | `NON_CODE_CLICKUP_TEAM_ID` | same as `CLICKUP_TEAM_ID` | Different workspace for non-code tasks (optional) |
169
-
170
- > **Tip:** `CLICKUP_API_KEY` and `CLICKUP_TEAM_ID` are intentionally omitted from `.env.aidev` if you leave them blank during `aidev init` — they will be read from your shell environment instead.
171
-
172
- > **Wildcard tag (`*`):** Set `CLICKUP_TAG=*` (or `JIRA_LABEL=*` / `LINEAR_LABEL=*`) to match **all** tasks regardless of tags/labels. This is useful when the AI dev has its own dedicated user in the task provider and every task assigned to it should be processed.
173
-
174
- ### Git & GitHub
175
-
176
- | Variable | Default | Description |
177
- |---|---|---|
178
- | `GIT_REMOTE` | auto-detected | Remote name — detected via `git remote get-url origin` if unset |
179
- | `GITHUB_BASE_BRANCH` | `main` | Base branch; new task branches are cut from here |
180
- | `GITHUB_REPO` | | `owner/repo` used to generate PR links in comments |
181
-
182
- ### Behaviour
183
-
184
- | Variable | Default | Description |
185
- |---|---|---|
186
- | `AIDEV_ENV_EXTEND` | — | Path to a global env file loaded as the base for this project (see above) |
187
- | `AGENTS` | `claude,cursor` | Comma-separated list of agents in priority order |
188
- | `DEV_NOTES_MODE` | `smart` | When to ask for clarification (`smart` or `always`) |
189
- | `AIDEV_TRIGGER_WORD` | `aidev-continue` | Comment containing this word re-triggers a skipped task |
190
- | `AIDEV_COMMENT_PREFIX` | `[aidev]` | Custom prefix for all aidev comments posted to task providers |
191
-
192
- ---
193
-
194
- ## AI agents
195
-
196
- aidev supports multiple AI agents with automatic fallback. The first available agent in the list is used; if it fails, the next one is tried with the previous agent's output as additional context.
197
-
198
- **Supported agents**
199
-
200
- | Agent | Requires |
201
- |---|---|
202
- | `antigravity` | Google **Antigravity** CLI (`agy` or `antigravity`) in PATH — see [Antigravity](https://antigravity.google/download) |
203
- | `claude` | [Claude CLI](https://github.com/anthropics/claude-code) installed and authenticated |
204
- | `cursor` | Cursor **Agent CLI** (`agent`) in PATH — see [Windows](#windows-cursor-agent-cli) below |
205
- | `windsurf` | [Windsurf](https://windsurf.com) installed with CLI available in PATH |
206
-
207
- ### Windows: Cursor Agent CLI
208
-
209
- On Windows, the Cursor IDE (`cursor.exe`) is separate from the headless Agent CLI. The runner uses the `agent` binary. Install it in PowerShell:
210
-
211
- ```powershell
212
- irm 'https://cursor.com/install?win32=true' | iex
213
- ```
214
-
215
- Then ensure `agent` is on your PATH and run `agent --version` to confirm. Without this, the Cursor runner will report as unavailable.
216
-
217
- **Configure agent order in `.env.aidev`:**
218
-
219
- ```bash
220
- # Claude first, fall back to Cursor
221
- AGENTS=claude,cursor
222
-
223
- # Cursor only
224
- AGENTS=cursor
225
-
226
- # Cursor first (useful when working locally with a monitor)
227
- AGENTS=cursor,claude
228
-
229
- # Claude first, then Windsurf, then Cursor
230
- AGENTS=claude,windsurf,cursor
231
-
232
- # Antigravity first, then Claude
233
- AGENTS=antigravity,claude
234
-
235
- # Windsurf only
236
- AGENTS=windsurf
237
- ```
238
-
239
- ---
240
-
241
- ## Trigger word & re-processing
242
-
243
- aidev prefixes every comment it posts with `[aidev]` (configurable via `AIDEV_COMMENT_PREFIX`). This lets it distinguish its own comments from human replies when deciding whether to re-process a task.
244
-
245
- A task is normally skipped when:
246
- - A remote branch already exists for it, **or**
247
- - It is `pending` and no human has replied yet
248
-
249
- To force aidev to pick the task up again, post a comment containing the **trigger word** (default: `aidev-continue`). aidev will reuse the existing branch and continue implementation from where it left off.
250
-
251
- ```bash
252
- # Customise the trigger word in .env.aidev
253
- AIDEV_TRIGGER_WORD=please-retry
254
- ```
255
-
256
- The trigger word match is case-insensitive, so `aidev-continue`, `AIDEV-CONTINUE`, and `Aidev-Continue` all work.
257
-
258
- For pending tasks, a regular human reply (any comment without the configured prefix) also triggers re-processing — the trigger word is an additional explicit mechanism.
259
-
260
- ```bash
261
- # Customise the comment prefix in .env.aidev
262
- AIDEV_COMMENT_PREFIX=[mybot]
263
- ```
264
-
265
- ---
266
-
267
- ## Non-code tasks
268
-
269
- Tasks tagged with `NON_CODE_TAG` are executed **without git branching** — no checkout, commit, push, or PR creation. The AI agent runs the task directly in the current working directory.
270
-
271
- This is useful for:
272
- - Research or investigation tasks
273
- - Documentation updates that don't go through PR review
274
- - Running scripts or commands
275
- - Any task where you want the AI to act without creating a branch
276
-
277
- ```bash
278
- # In .env.aidev
279
- NON_CODE_TAG=non-code
280
-
281
- # Optionally use a different ClickUp team for non-code tasks
282
- NON_CODE_CLICKUP_TEAM_ID=987654
283
-
284
- # Or a different Jira project
285
- NON_CODE_JIRA_PROJECT=OPS
286
- ```
287
-
288
- Non-code tasks follow the same lifecycle as regular tasks (clarification → implementation → review), except the implementation step skips all git operations. After completion, the task status is moved to your configured "in review" status.
289
-
290
- If `NON_CODE_TAG` is not configured, non-code task processing is disabled entirely.
291
-
292
- ---
293
-
294
- ## Dev notes mode
295
-
296
- Controls when aidev asks ClickUp for clarification before implementing.
297
-
298
- | Mode | Behaviour |
299
- |---|---|
300
- | `smart` | Asks the AI whether the task description is clear enough. Only posts a clarification question if it's ambiguous. |
301
- | `always` | Always posts "any dev notes?" before implementing every task. |
302
-
303
- When a question is posted, the task is moved to `CLICKUP_PENDING_STATUS`. On the next run, aidev checks whether a human has replied and, if so, includes the reply as context for the AI.
304
-
305
- ---
306
-
307
- ## Scheduling
308
-
309
- aidev can run on a cron schedule, one entry per project directory.
310
-
311
- ```bash
312
- # Interactive picker
313
- aidev schedule set
314
-
315
- # Or pass an expression directly
316
- aidev schedule set "*/15 * * * *"
317
-
318
- # Check what's scheduled for the current directory
319
- aidev schedule get
320
- ```
321
-
322
- **Preset options (interactive picker)**
323
-
324
- | Option | Expression |
325
- |---|---|
326
- | Every 15 minutes | `*/15 * * * *` |
327
- | Every 30 minutes | `*/30 * * * *` |
328
- | Every hour | `0 * * * *` |
329
- | Every 5 hours | `0 */5 * * *` |
330
- | Every day at 8am | `0 8 * * *` |
331
-
332
- Each directory gets its own cron entry identified by a `# aidev-cwd:/path` marker running `schedule set` again replaces the existing entry rather than adding a duplicate.
333
-
334
- ### macOS: Full Disk Access required
335
-
336
- On macOS (Ventura and later), cron jobs are silently blocked unless `/usr/sbin/cron` has Full Disk Access:
337
-
338
- 1. Open **System Settings → Privacy & Security → Full Disk Access**
339
- 2. Click **+** and add `/usr/sbin/cron`
340
- 3. Re-run `aidev schedule set` to apply your schedule
341
-
342
- Without this, cron will appear to be configured but jobs will never fire.
343
-
344
- ---
345
-
346
- ## Logging
347
-
348
- Every run appends to `aidev.log` in your project directory:
349
-
350
- ```
351
- ────────────────────────────────────────────────────────────
352
- 2026-03-06T08:00:00.000Z [run] started
353
- ────────────────────────────────────────────────────────────
354
- 2026-03-06T08:00:00.120Z [info] Fetching tasks (filter: all)...
355
- 2026-03-06T08:00:01.340Z [task] [abc123] "Fix login flow" (status: open)
356
- 2026-03-06T08:00:12.780Z [info] Running claude...
357
- 2026-03-06T08:00:45.210Z [success] Task implemented: branch abc123/fix-login-flow pushed
358
- 2026-03-06T08:00:45.890Z [success] Done. Processed: 1, Skipped: 3
359
- ```
360
-
361
- ANSI colour codes are stripped so the file stays readable in any editor or `tail -f`. `aidev.log` is added to `.gitignore` automatically by `aidev init`.
362
-
363
- ---
364
-
365
- ## Providers
366
-
367
- | Provider | Status |
368
- |---|---|
369
- | ClickUp | ✅ Implemented |
370
- | Jira | Implemented |
371
- | Linear | Implemented |
372
- | Monday.com | Implemented |
373
- | Local | ✅ Implemented |
374
- | Notion | Implemented |
375
- | Trello | 🔜 Stub — contributions welcome |
376
-
377
- The `TaskProvider` interface makes it straightforward to add new providers. See [CONTRIBUTING.md](./CONTRIBUTING.md).
378
-
379
- ### Local provider
380
-
381
- Set `PROVIDER=local` in `.env.aidev` to manage tasks entirely via local markdown files — no external API needed.
382
-
383
- ```bash
384
- aidev init # choose "local" when prompted for provider
385
- ```
386
-
387
- Tasks live in `.aidev/tasks/` under status folders:
388
-
389
- ```
390
- .aidev/tasks/
391
- open/ # new tasks ready for implementation
392
- pending/ # waiting for human reply
393
- progress/ # currently being implemented
394
- review/ # implementation complete, awaiting review
395
- done/ # finished
396
- ```
397
-
398
- **Task file format** (e.g. `.aidev/tasks/open/a1b2c3d4-fix-login-bug.md`):
399
-
400
- ```markdown
401
- ---
402
- title: Fix login page bug
403
- priority: 2
404
- assignee: david
405
- estimated: 2h
406
- tags: frontend, auth
407
- created: 2026-03-12T10:00:00.000Z
408
- ---
409
-
410
- The login form should redirect users to the dashboard after successful authentication.
411
- ```
412
-
413
- The filename must start with a short ID (hex characters) followed by a dash and a slug. The YAML frontmatter carries task metadata; everything after `---` is the task description.
414
-
415
- #### Code vs non-code tasks
416
-
417
- By default, local tasks are treated as **code tasks** — aidev creates a git branch, runs the AI agent, commits, pushes, and opens a PR.
418
-
419
- To mark a task as **non-code** (research, docs, investigation — no git branching), add `type: non-code` to the frontmatter:
420
-
421
- ```markdown
422
- ---
423
- title: Compare OAuth2 providers
424
- type: non-code
425
- tags: research
426
- ---
427
-
428
- Evaluate Auth0, Clerk, and Supabase Auth. Write a recommendation.
429
- ```
430
-
431
- Non-code tasks follow the same lifecycle but skip all git operations. The AI response is posted as a session comment instead of a PR.
432
-
433
- **Session file** (comments) — `.aidev/tasks/open/a1b2c3d4-fix-login-bug.session.md`:
434
-
435
- ```markdown
436
- <!-- aidev session log — append your comments below using "## your-name" as header -->
437
-
438
- ---
439
-
440
- ## aidev — 2026-03-12T10:05:00.000Z
441
-
442
- [aidev] Starting implementation on branch `a1b2c3d4/fix-login-bug`
443
-
444
- ---
445
-
446
- ## david — 2026-03-12T10:10:00.000Z
447
-
448
- Please use the new auth API endpoint for this.
449
- ```
450
-
451
- To add a comment, append a `---` separator followed by a `## your-name` header and your message. aidev parses these entries automatically and uses them as conversation context, just like ClickUp/Jira comments.
452
-
453
- Downloaded task attachments are stored in `.aidev/assets/<task-id>/`, and `aidev init` adds `.aidev/assets/` to `.gitignore` automatically.
454
-
455
- ---
456
-
457
- ## Contributing
458
-
459
- Contributions are welcome — new providers, new AI runners, bug fixes, and docs improvements.
460
-
461
- See [CONTRIBUTING.md](./CONTRIBUTING.md) for the full guide.
462
-
463
- ---
464
-
465
- ## License
466
-
467
- [MIT](./LICENSE)
1
+ # @qelos/aidev
2
+
3
+ [![npm version](https://img.shields.io/npm/v/%40qelos%2Faidev.svg?style=flat-square)](https://www.npmjs.com/package/@qelos/aidev)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](./LICENSE)
5
+ [![Node.js](https://img.shields.io/badge/node-%3E%3D18-brightgreen.svg?style=flat-square)](https://nodejs.org)
6
+
7
+ **aidev** turns your tasks into merged code — automatically.
8
+
9
+ It polls your task manager (ClickUp, Jira, Linear, Monday.com, Notion, Trello, or local markdown files), checks whether tasks are clear, runs Claude, Cursor, or Windsurf to implement them, pushes a branch, and moves the task to review. All without touching your keyboard.
10
+
11
+ ```
12
+ Task (ClickUp / Jira / Monday / Notion / Trello / local) → AI implements → git push → "in review"
13
+ ```
14
+
15
+ ---
16
+
17
+ ## Table of Contents
18
+
19
+ - [How it works](#how-it-works)
20
+ - [Quick start](#quick-start)
21
+ - [Commands](#commands)
22
+ - [Concurrency lock](#concurrency-lock)
23
+ - [Configuration](#configuration)
24
+ - [AI agents](#ai-agents)
25
+ - [Dev notes mode](#dev-notes-mode)
26
+ - [Scheduling](#scheduling)
27
+ - [Hooks](#hooks)
28
+ - [Logging](#logging)
29
+ - [Providers](#providers)
30
+ - [Contributing](#contributing)
31
+
32
+ ---
33
+
34
+ ## How it works
35
+
36
+ 1. **Fetch** — pulls all tasks tagged with your configured tag from ClickUp
37
+ 2. **Filter** — skips done/cancelled tasks and tasks that already have a branch
38
+ 3. **Clarify** — in `smart` mode, asks the AI if the task description is clear enough; if not, posts a question as a comment (prefixed with `[aidev]`) and marks the task `pending`
39
+ 4. **Wait** — pending tasks are re-checked on the next run; if a human replied or the trigger word is found, implementation proceeds with the conversation as context
40
+ 5. **Implement** — checks out a fresh branch (or reuses an existing one), runs your configured AI agent(s), falls back to the next agent if one fails
41
+ 6. **Ship** — commits all changes, pushes the branch, posts a comment with the branch name and a PR link, moves the task to your "in review" status
42
+
43
+ ---
44
+
45
+ ## Quick start
46
+
47
+ ```bash
48
+ npm install -g @qelos/aidev
49
+ ```
50
+
51
+ Navigate to your project and run the interactive setup:
52
+
53
+ ```bash
54
+ cd my-project
55
+ aidev init
56
+ ```
57
+
58
+ The wizard will ask for your ClickUp credentials, git settings, and preferred AI agents. Sensitive values (API keys) can be left blank if they are already set as environment variables in your shell.
59
+
60
+ Once configured:
61
+
62
+ ```bash
63
+ aidev run
64
+ ```
65
+
66
+ ---
67
+
68
+ ## Commands
69
+
70
+ | Command | Description |
71
+ |---|---|
72
+ | `aidev init` | Interactive setup creates `.env.aidev` |
73
+ | `aidev run` | Process all open + pending-with-replies tasks |
74
+ | `aidev run open` | Only open (non-pending) tasks |
75
+ | `aidev run pending` | Only pending tasks check for human replies |
76
+ | `aidev stop` | Stop any running aidev process in the current directory |
77
+ | `aidev schedule set` | Interactive cron picker for this directory |
78
+ | `aidev schedule set "<expr>"` | Set a specific cron expression |
79
+ | `aidev schedule get` | Show the current schedule for this directory |
80
+ | `aidev help` | Show command and config reference |
81
+
82
+ ### Global flags
83
+
84
+ | Flag | Description |
85
+ |---|---|
86
+ | `-e, --env <path>` | Load config from a custom env file instead of `.env.aidev` |
87
+ | `-V, --version` | Print version |
88
+
89
+ **Examples**
90
+
91
+ ```bash
92
+ # Use a shared env file for a staging environment
93
+ aidev --env /shared/.env.staging run
94
+
95
+ # Only process tasks that are waiting for a reply
96
+ aidev run pending
97
+
98
+ # Schedule to run every 30 minutes
99
+ aidev schedule set "*/30 * * * *"
100
+ ```
101
+
102
+ ---
103
+
104
+ ## Concurrency lock
105
+
106
+ `aidev run` writes a PID lock file (`.aidev.lock`) in the current directory when it starts and removes it when it finishes. If a second invocation detects a live process already holding the lock, it logs a warning and exits immediately — preventing two agents from committing to the same branch at the same time.
107
+
108
+ ```
109
+ $ aidev run
110
+ [aidev] aidev is already running in this directory (PID 12345). Use "aidev stop" to terminate it.
111
+ ```
112
+
113
+ Use `aidev stop` to send `SIGTERM` to the running process and clean up the lock file:
114
+
115
+ ```bash
116
+ aidev stop
117
+ ```
118
+
119
+ Stale lock files (left behind by a crash) are detected automatically — the next `aidev run` will overwrite them if the stored PID is no longer alive.
120
+
121
+ ---
122
+
123
+ ## Configuration
124
+
125
+ Run `aidev init` for an interactive setup, or create `.env.aidev` manually using `.env.aidev.example` as a template.
126
+
127
+ ### Global env file (`AIDEV_ENV_EXTEND`)
128
+
129
+ If you work across multiple projects, you can keep shared settings (API keys, agent list, etc.) in a single global file and reference it from each project's `.env.aidev`:
130
+
131
+ ```bash
132
+ # ~/.aidev.global
133
+ CLICKUP_API_KEY=pk_...
134
+ CLICKUP_TEAM_ID=123456
135
+ AGENTS=claude,cursor
136
+ ```
137
+
138
+ ```bash
139
+ # my-project/.env.aidev — project-specific values override the global ones
140
+ AIDEV_ENV_EXTEND=~/.aidev.global
141
+ CLICKUP_TAG=my-project
142
+ ```
143
+
144
+ **Priority order (highest → lowest):**
145
+
146
+ 1. Shell environment variables (e.g. set in `~/.zshrc`) — never overwritten
147
+ 2. Local `.env.aidev` values
148
+ 3. `AIDEV_ENV_EXTEND` file values (global base)
149
+
150
+ `AIDEV_ENV_EXTEND` can be set in two ways:
151
+
152
+ - **Per-project** — add `AIDEV_ENV_EXTEND=/path/to/file` inside `.env.aidev`
153
+ - **Shell-wide** — `export AIDEV_ENV_EXTEND=~/.aidev.global` in `~/.zshrc` (applies to every project automatically)
154
+
155
+ `aidev init` will ask for this path and pre-fill it if the variable is already in your shell environment.
156
+
157
+ ### ClickUp
158
+
159
+ | Variable | Default | Description |
160
+ |---|---|---|
161
+ | `CLICKUP_API_KEY` | — | Personal API token — can be set as a shell env var |
162
+ | `CLICKUP_TEAM_ID` | — | Workspace / team ID can be set as a shell env var |
163
+ | `CLICKUP_TAG` | | Tasks with this tag will be picked up (set to `*` to match all tasks) |
164
+ | `CLICKUP_PENDING_STATUS` | `pending` | Status name for "waiting for reply" |
165
+ | `CLICKUP_IN_REVIEW_STATUS` | `review` | Status set after implementation |
166
+ | `ASSIGNEE_TAG` | — | Only process tasks assigned to this user (optional) |
167
+ | `THINKING_TAG` | — | Tasks with this tag are analyzed and broken into sub-tasks before execution (optional) |
168
+ | `NON_CODE_TAG` | | Tasks with this tag run without git branching (optional) |
169
+ | `NON_CODE_CLICKUP_TEAM_ID` | same as `CLICKUP_TEAM_ID` | Different workspace for non-code tasks (optional) |
170
+
171
+ > **Tip:** `CLICKUP_API_KEY` and `CLICKUP_TEAM_ID` are intentionally omitted from `.env.aidev` if you leave them blank during `aidev init` — they will be read from your shell environment instead.
172
+
173
+ > **Wildcard tag (`*`):** Set `CLICKUP_TAG=*` (or `JIRA_LABEL=*` / `LINEAR_LABEL=*`) to match **all** tasks regardless of tags/labels. This is useful when the AI dev has its own dedicated user in the task provider and every task assigned to it should be processed.
174
+
175
+ ### Git & GitHub
176
+
177
+ | Variable | Default | Description |
178
+ |---|---|---|
179
+ | `GIT_REMOTE` | auto-detected | Remote name detected via `git remote get-url origin` if unset |
180
+ | `GITHUB_BASE_BRANCH` | `main` | Base branch; new task branches are cut from here |
181
+ | `GITHUB_REPO` | — | `owner/repo` — used to generate PR links in comments |
182
+
183
+ ### Behaviour
184
+
185
+ | Variable | Default | Description |
186
+ |---|---|---|
187
+ | `AIDEV_ENV_EXTEND` | | Path to a global env file loaded as the base for this project (see above) |
188
+ | `AGENTS` | `claude,cursor` | Comma-separated list of agents in priority order |
189
+ | `DEV_NOTES_MODE` | `smart` | When to ask for clarification (`smart` or `always`) |
190
+ | `AIDEV_TRIGGER_WORD` | `aidev-continue` | Comment containing this word re-triggers a skipped task |
191
+ | `AIDEV_COMMENT_PREFIX` | `[aidev]` | Custom prefix for all aidev comments posted to task providers |
192
+ | `AIDEV_HOOKS_PATH` | — | Path to a `.ts` or `.js` module that exports hook functions (see [Hooks](#hooks)) |
193
+
194
+ ---
195
+
196
+ ## Hooks
197
+
198
+ Set `AIDEV_HOOKS_PATH` in `.env.aidev` to a path relative to the project directory or an absolute path. `aidev init` writes `.aidev/aidev.hooks.ts` and sets `AIDEV_HOOKS_PATH=.aidev/aidev.hooks.ts` by default.
199
+
200
+ The module should export an object (or `export default`) whose properties are optional async functions. Only known hook names are used; anything else is ignored. If a hook throws, the current operation stops (for example the whole run after `beforeRun`, or conflict resolution after `beforeResolveConflicts`). If a hook returns an object, it replaces the context for that step (for example append to `context.prompt` in `beforeEachTask` and return the updated context).
201
+
202
+ **Hook names**
203
+
204
+ | Hook | When | Context notes |
205
+ |---|---|---|
206
+ | `beforeRun` / `afterRun` | Start / end of `aidev run` | `afterRun` includes `processed` and `skipped` counts |
207
+ | `beforeEachTask` / `afterEachTask` | Around each code task implementation | `prompt`, `branchName`, `task`; `afterEachTask` has `success` |
208
+ | `beforeResolveConflicts` / `afterResolveConflicts` | Merge conflict resolution with AI | `conflictFiles`, `prompt`; `afterResolveConflicts` has `resolved` |
209
+ | `beforeNonCodeTask` / `afterNonCodeTask` | Non-code tasks | `afterNonCodeTask` includes agent `output` |
210
+ | `beforeThinkingTask` / `afterThinkingTask` | Thinking-tag tasks (subtask plan) | `beforeThinkingTask` may adjust `subtasks` before steps run |
211
+
212
+ **Second argument: `vm`**
213
+
214
+ Each hook receives `(context, vm)`. The `vm` object exposes:
215
+
216
+ - `runAI(prompt)` — runs the first available configured AI agent
217
+ - `postComment(taskId, text)`, `updateStatus(taskId, status)`, `getComments(taskId)` — same family of operations as the task provider
218
+ - `log.info` / `log.warn` / `log.error` — prefixed hook logging
219
+
220
+ **TypeScript hooks**
221
+
222
+ `.ts` hook files are loaded at runtime via [jiti](https://www.npmjs.com/package/jiti) — no TypeScript compiler or toolchain needed. Just write a plain `.ts` file with the hook functions and aidev handles the rest.
223
+
224
+ ---
225
+
226
+ ## AI agents
227
+
228
+ aidev supports multiple AI agents with automatic fallback. The first available agent in the list is used; if it fails, the next one is tried with the previous agent's output as additional context.
229
+
230
+ **Supported agents**
231
+
232
+ | Agent | Requires |
233
+ |---|---|
234
+ | `antigravity` | Google **Antigravity** CLI (`agy` or `antigravity`) in PATH — see [Antigravity](https://antigravity.google/download) |
235
+ | `claude` | [Claude CLI](https://github.com/anthropics/claude-code) installed and authenticated |
236
+ | `cursor` | Cursor **Agent CLI** (`agent`) in PATH — see [Windows](#windows-cursor-agent-cli) below |
237
+ | `windsurf` | [Windsurf](https://windsurf.com) installed with CLI available in PATH |
238
+
239
+ ### Windows: Cursor Agent CLI
240
+
241
+ On Windows, the Cursor IDE (`cursor.exe`) is separate from the headless Agent CLI. The runner uses the `agent` binary. Install it in PowerShell:
242
+
243
+ ```powershell
244
+ irm 'https://cursor.com/install?win32=true' | iex
245
+ ```
246
+
247
+ Then ensure `agent` is on your PATH and run `agent --version` to confirm. Without this, the Cursor runner will report as unavailable.
248
+
249
+ **Configure agent order in `.env.aidev`:**
250
+
251
+ ```bash
252
+ # Claude first, fall back to Cursor
253
+ AGENTS=claude,cursor
254
+
255
+ # Cursor only
256
+ AGENTS=cursor
257
+
258
+ # Cursor first (useful when working locally with a monitor)
259
+ AGENTS=cursor,claude
260
+
261
+ # Claude first, then Windsurf, then Cursor
262
+ AGENTS=claude,windsurf,cursor
263
+
264
+ # Antigravity first, then Claude
265
+ AGENTS=antigravity,claude
266
+
267
+ # Windsurf only
268
+ AGENTS=windsurf
269
+ ```
270
+
271
+ ---
272
+
273
+ ## Trigger word & re-processing
274
+
275
+ aidev prefixes every comment it posts with `[aidev]` (configurable via `AIDEV_COMMENT_PREFIX`). This lets it distinguish its own comments from human replies when deciding whether to re-process a task.
276
+
277
+ A task is normally skipped when:
278
+ - A remote branch already exists for it, **or**
279
+ - It is `pending` and no human has replied yet
280
+
281
+ To force aidev to pick the task up again, post a comment containing the **trigger word** (default: `aidev-continue`). aidev will reuse the existing branch and continue implementation from where it left off.
282
+
283
+ ```bash
284
+ # Customise the trigger word in .env.aidev
285
+ AIDEV_TRIGGER_WORD=please-retry
286
+ ```
287
+
288
+ The trigger word match is case-insensitive, so `aidev-continue`, `AIDEV-CONTINUE`, and `Aidev-Continue` all work.
289
+
290
+ For pending tasks, a regular human reply (any comment without the configured prefix) also triggers re-processing — the trigger word is an additional explicit mechanism.
291
+
292
+ ```bash
293
+ # Customise the comment prefix in .env.aidev
294
+ AIDEV_COMMENT_PREFIX=[mybot]
295
+ ```
296
+
297
+ ---
298
+
299
+ ## Non-code tasks
300
+
301
+ Tasks tagged with `NON_CODE_TAG` are executed **without git branching** no checkout, commit, push, or PR creation. The AI agent runs the task directly in the current working directory.
302
+
303
+ This is useful for:
304
+ - Research or investigation tasks
305
+ - Documentation updates that don't go through PR review
306
+ - Running scripts or commands
307
+ - Any task where you want the AI to act without creating a branch
308
+
309
+ ```bash
310
+ # In .env.aidev
311
+ NON_CODE_TAG=non-code
312
+
313
+ # Optionally use a different ClickUp team for non-code tasks
314
+ NON_CODE_CLICKUP_TEAM_ID=987654
315
+
316
+ # Or a different Jira project
317
+ NON_CODE_JIRA_PROJECT=OPS
318
+ ```
319
+
320
+ Non-code tasks follow the same lifecycle as regular tasks (clarification → implementation → review), except the implementation step skips all git operations. After completion, the task status is moved to your configured "in review" status.
321
+
322
+ If `NON_CODE_TAG` is not configured, non-code task processing is disabled entirely.
323
+
324
+ ---
325
+
326
+ ## Dev notes mode
327
+
328
+ Controls when aidev asks ClickUp for clarification before implementing.
329
+
330
+ | Mode | Behaviour |
331
+ |---|---|
332
+ | `smart` | Asks the AI whether the task description is clear enough. Only posts a clarification question if it's ambiguous. |
333
+ | `always` | Always posts "any dev notes?" before implementing every task. |
334
+
335
+ When a question is posted, the task is moved to `CLICKUP_PENDING_STATUS`. On the next run, aidev checks whether a human has replied and, if so, includes the reply as context for the AI.
336
+
337
+ ---
338
+
339
+ ## Scheduling
340
+
341
+ aidev can run on a cron schedule, one entry per project directory.
342
+
343
+ ```bash
344
+ # Interactive picker
345
+ aidev schedule set
346
+
347
+ # Or pass an expression directly
348
+ aidev schedule set "*/15 * * * *"
349
+
350
+ # Check what's scheduled for the current directory
351
+ aidev schedule get
352
+ ```
353
+
354
+ **Preset options (interactive picker)**
355
+
356
+ | Option | Expression |
357
+ |---|---|
358
+ | Every 15 minutes | `*/15 * * * *` |
359
+ | Every 30 minutes | `*/30 * * * *` |
360
+ | Every hour | `0 * * * *` |
361
+ | Every 5 hours | `0 */5 * * *` |
362
+ | Every day at 8am | `0 8 * * *` |
363
+
364
+ Each directory gets its own cron entry identified by a `# aidev-cwd:/path` marker — running `schedule set` again replaces the existing entry rather than adding a duplicate.
365
+
366
+ ### macOS: Full Disk Access required
367
+
368
+ On macOS (Ventura and later), cron jobs are silently blocked unless `/usr/sbin/cron` has Full Disk Access:
369
+
370
+ 1. Open **System Settings Privacy & Security → Full Disk Access**
371
+ 2. Click **+** and add `/usr/sbin/cron`
372
+ 3. Re-run `aidev schedule set` to apply your schedule
373
+
374
+ Without this, cron will appear to be configured but jobs will never fire.
375
+
376
+ ---
377
+
378
+ ## Logging
379
+
380
+ Every run appends to `aidev.log` in your project directory:
381
+
382
+ ```
383
+ ────────────────────────────────────────────────────────────
384
+ 2026-03-06T08:00:00.000Z [run] started
385
+ ────────────────────────────────────────────────────────────
386
+ 2026-03-06T08:00:00.120Z [info] Fetching tasks (filter: all)...
387
+ 2026-03-06T08:00:01.340Z [task] [abc123] "Fix login flow" (status: open)
388
+ 2026-03-06T08:00:12.780Z [info] Running claude...
389
+ 2026-03-06T08:00:45.210Z [success] Task implemented: branch abc123/fix-login-flow pushed
390
+ 2026-03-06T08:00:45.890Z [success] Done. Processed: 1, Skipped: 3
391
+ ```
392
+
393
+ ANSI colour codes are stripped so the file stays readable in any editor or `tail -f`. `aidev.log` is added to `.gitignore` automatically by `aidev init`.
394
+
395
+ ---
396
+
397
+ ## Providers
398
+
399
+ | Provider | Status |
400
+ |---|---|
401
+ | ClickUp | ✅ Implemented |
402
+ | Jira | Implemented |
403
+ | Linear | ✅ Implemented |
404
+ | Monday.com | ✅ Implemented |
405
+ | Local | ✅ Implemented |
406
+ | Notion | ✅ Implemented |
407
+ | Trello | 🔜 Stub — contributions welcome |
408
+
409
+ The `TaskProvider` interface makes it straightforward to add new providers. See [CONTRIBUTING.md](./CONTRIBUTING.md).
410
+
411
+ ### Local provider
412
+
413
+ Set `PROVIDER=local` in `.env.aidev` to manage tasks entirely via local markdown files no external API needed.
414
+
415
+ ```bash
416
+ aidev init # choose "local" when prompted for provider
417
+ ```
418
+
419
+ Tasks live in `.aidev/tasks/` under status folders:
420
+
421
+ ```
422
+ .aidev/tasks/
423
+ open/ # new tasks ready for implementation
424
+ pending/ # waiting for human reply
425
+ progress/ # currently being implemented
426
+ review/ # implementation complete, awaiting review
427
+ done/ # finished
428
+ ```
429
+
430
+ **Task file format** (e.g. `.aidev/tasks/open/a1b2c3d4-fix-login-bug.md`):
431
+
432
+ ```markdown
433
+ ---
434
+ title: Fix login page bug
435
+ priority: 2
436
+ assignee: david
437
+ estimated: 2h
438
+ tags: frontend, auth
439
+ created: 2026-03-12T10:00:00.000Z
440
+ ---
441
+
442
+ The login form should redirect users to the dashboard after successful authentication.
443
+ ```
444
+
445
+ The filename must start with a short ID (hex characters) followed by a dash and a slug. The YAML frontmatter carries task metadata; everything after `---` is the task description.
446
+
447
+ #### Code vs non-code tasks
448
+
449
+ By default, local tasks are treated as **code tasks** — aidev creates a git branch, runs the AI agent, commits, pushes, and opens a PR.
450
+
451
+ To mark a task as **non-code** (research, docs, investigation no git branching), add `type: non-code` to the frontmatter:
452
+
453
+ ```markdown
454
+ ---
455
+ title: Compare OAuth2 providers
456
+ type: non-code
457
+ tags: research
458
+ ---
459
+
460
+ Evaluate Auth0, Clerk, and Supabase Auth. Write a recommendation.
461
+ ```
462
+
463
+ Non-code tasks follow the same lifecycle but skip all git operations. The AI response is posted as a session comment instead of a PR.
464
+
465
+ **Session file** (comments) — `.aidev/tasks/open/a1b2c3d4-fix-login-bug.session.md`:
466
+
467
+ ```markdown
468
+ <!-- aidev session log — append your comments below using "## your-name" as header -->
469
+
470
+ ---
471
+
472
+ ## aidev — 2026-03-12T10:05:00.000Z
473
+
474
+ [aidev] Starting implementation on branch `a1b2c3d4/fix-login-bug`
475
+
476
+ ---
477
+
478
+ ## david — 2026-03-12T10:10:00.000Z
479
+
480
+ Please use the new auth API endpoint for this.
481
+ ```
482
+
483
+ To add a comment, append a `---` separator followed by a `## your-name` header and your message. aidev parses these entries automatically and uses them as conversation context, just like ClickUp/Jira comments.
484
+
485
+ Downloaded task attachments are stored in `.aidev/assets/<task-id>/`, and `aidev init` adds `.aidev/assets/` to `.gitignore` automatically.
486
+
487
+ ---
488
+
489
+ ## Contributing
490
+
491
+ Contributions are welcome — new providers, new AI runners, bug fixes, and docs improvements.
492
+
493
+ See [CONTRIBUTING.md](./CONTRIBUTING.md) for the full guide.
494
+
495
+ ---
496
+
497
+ ## License
498
+
499
+ [MIT](./LICENSE)