taskgraph-ai 0.49.1 → 0.52.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +76 -32
  2. package/dist/ai-services-unified-BbSRBK0N.js +3 -0
  3. package/dist/ai-services-unified-CQMZv2X-.js +1 -0
  4. package/dist/assets/AGENTS.md +12 -31
  5. package/dist/assets/example_prd_rpg.txt +1 -4
  6. package/dist/assets/scripts_README.md +12 -14
  7. package/dist/commands-DOZyxFfM.js +231 -0
  8. package/dist/config-manager-BsUS_HoV.js +1 -0
  9. package/dist/config-manager-CKzRb4tZ.js +1 -0
  10. package/dist/dependency-manager-BcQJdp1Y.js +971 -0
  11. package/dist/git-utils--i2q96hv.js +1 -0
  12. package/dist/git-utils-BezpEZd4.js +1 -0
  13. package/dist/{init-wtXaFE45.js → init-S96FNSm7.js} +65 -389
  14. package/dist/mcp-server.js +6 -6
  15. package/dist/research-cdWIHSpn.js +1 -0
  16. package/dist/response-language-Bjbf2_9z.js +1 -0
  17. package/dist/{response-language-BHhde6n_.js → response-language-Ln6H6G2z.js} +1 -1
  18. package/dist/src-Cio2Sps9.js +207 -0
  19. package/dist/tag-management-BzAE-dVv.js +1 -0
  20. package/dist/task-manager-Utma-ZPy.js +1 -0
  21. package/dist/taskgraph.js +1 -1
  22. package/dist/update-subtask-by-id-UcjCRJbf.js +1 -0
  23. package/dist/update-task-by-id-98Q5zy74.js +1 -0
  24. package/dist/utils-BzS6gmZZ.js +1 -0
  25. package/package.json +16 -30
  26. package/dist/ai-services-unified--6CT6QUI.js +0 -1
  27. package/dist/ai-services-unified-D8PahWkz.js +0 -3
  28. package/dist/commands-CceFmRJA.js +0 -230
  29. package/dist/config-manager-CvDCaURh.js +0 -1
  30. package/dist/config-manager-DD5sEcpv.js +0 -270
  31. package/dist/dependency-manager-B7SaMC6u.js +0 -966
  32. package/dist/git-utils-DllbRE35.js +0 -1
  33. package/dist/git-utils-PBP1PRVP.js +0 -1
  34. package/dist/research-BRpAIbWg.js +0 -1
  35. package/dist/response-language-Dz-rFnaJ.js +0 -1
  36. package/dist/sentry-DNoFrfjb.js +0 -1
  37. package/dist/tag-management-BEKnBGXA.js +0 -1
  38. package/dist/task-manager-BQkOlw_W.js +0 -1
  39. package/dist/update-subtask-by-id-BOFRADbR.js +0 -1
  40. package/dist/update-task-by-id-DTHqRii_.js +0 -1
  41. package/dist/utils-DYpucGVy.js +0 -1
package/README.md CHANGED
@@ -18,55 +18,81 @@
18
18
 
19
19
  TaskGraph turns a product requirements document (PRD) into a dependency-aware task list, then walks Claude Code through it one task at a time. You describe what to build, TaskGraph plans the work, and Claude Code implements it, with the plan and progress stored in your repo.
20
20
 
21
+ <p align="center">
22
+ <img src="images/taskgraph-flow.svg" alt="Eight tasks from scaffold to launch. Each unlocks when its dependencies are done, and taskgraph next always points at the next unblocked task." width="720">
23
+ </p>
24
+
21
25
  - **Plan from a PRD:** generate tasks and subtasks, with dependencies, priorities and test strategies.
22
26
  - **Always know what's next:** `next` picks the first unblocked task.
23
27
  - **Stay in Claude Code:** use slash commands (`/tm:next-task`) or the `taskgraph` CLI. An MCP server is available if you want plain-language control, but it is optional.
24
28
  - **No API keys:** every AI call runs through your signed-in Claude Code.
25
29
 
26
- > **Attribution:** TaskGraph is based on [Task Master](https://github.com/eyaltoledano/claude-task-master) by Eyal Toledano ([@eyaltoledano](https://x.com/eyaltoledano)) and Ralph Khreish ([@RalphEcom](https://x.com/RalphEcom)). It is named `taskgraph-ai` with `taskgraph` and `taskgraph-mcp` binaries, so it can sit next to the original, and it keeps the original license and copyright notices (see [Licensing](#licensing)). Existing `.taskmaster/` project folders work unchanged.
30
+ <p align="center">
31
+ <a href="images/demo/03-pick-up-where-you-left-off.mp4"><img src="images/demo/03-pick-up-where-you-left-off.svg" alt="A new Claude Code session running /tm:next-task and resuming from the notes logged last time" width="820"></a>
32
+ <br>
33
+ <sub>3. Pick up where you left off · <a href="images/demo/03-pick-up-where-you-left-off.mp4">MP4</a></sub>
34
+ </p>
35
+
36
+ <details>
37
+ <summary><b>See the full workflow</b> (4 short clips)</summary>
38
+
39
+ <p align="center">
40
+ <a href="images/demo/01-setup.mp4"><img src="images/demo/01-setup.svg" alt="Running taskgraph init --rules claude in a project" width="820"></a>
41
+ <br>
42
+ <sub>1. Set it up in your project · <a href="images/demo/01-setup.mp4">MP4</a></sub>
43
+ </p>
44
+
45
+ <p align="center">
46
+ <a href="images/demo/02-prd-to-tasks.mp4"><img src="images/demo/02-prd-to-tasks.svg" alt="Claude Code running /tm:parse-prd to turn a PRD into 8 dependent tasks" width="820"></a>
47
+ <br>
48
+ <sub>2. Turn your PRD into a plan · <a href="images/demo/02-prd-to-tasks.mp4">MP4</a></sub>
49
+ </p>
50
+
51
+ <p align="center">
52
+ <a href="images/demo/03-pick-up-where-you-left-off.mp4"><img src="images/demo/03-pick-up-where-you-left-off.svg" alt="A new Claude Code session running /tm:next-task and resuming from the notes logged last time" width="820"></a>
53
+ <br>
54
+ <sub>3. Pick up where you left off · <a href="images/demo/03-pick-up-where-you-left-off.mp4">MP4</a></sub>
55
+ </p>
56
+
57
+ <p align="center">
58
+ <a href="images/demo/04-terminal.mp4"><img src="images/demo/04-terminal.svg" alt="The taskgraph list dashboard and task table in a terminal" width="820"></a>
59
+ <br>
60
+ <sub>4. Or drive it from your terminal · <a href="images/demo/04-terminal.mp4">MP4</a></sub>
61
+ </p>
62
+
63
+ </details>
64
+
65
+ > **Attribution:** TaskGraph is based on [Task Master](https://github.com/eyaltoledano/claude-task-master) by Eyal Toledano ([@eyaltoledano](https://x.com/eyaltoledano)) and Ralph Khreish ([@RalphEcom](https://x.com/RalphEcom)). It is named `taskgraph-ai` with `taskgraph` and `taskgraph-mcp` binaries, so it can sit next to the original, and it keeps the original license and copyright notices (see [Licensing](#licensing)). Coming from Task Master or a release before 0.47? See [Upgrading](#upgrading).
27
66
 
28
67
  ## Contents
29
68
 
30
- [Set up in Claude Code](#set-up-in-claude-code) · [How to use it](#how-to-use-it) · [Commands](#commands) · [MCP tool tiers](#mcp-tool-tiers) · [Models](#models) · [Troubleshooting](#troubleshooting) · [Docs](#documentation) · [Licensing](#licensing)
69
+ [Set up in Claude Code](#set-up-in-claude-code) · [How to use it](#how-to-use-it) · [Commands](#commands) · [MCP tool tiers](#mcp-tool-tiers) · [Models](#models) · [Upgrading](#upgrading) · [Troubleshooting](#troubleshooting) · [Docs](#documentation) · [Licensing](#licensing)
31
70
 
32
71
  ## Set up in Claude Code
33
72
 
34
- > **Install from source for now.** `taskgraph-ai` isn't published to npm yet, so `npx -y taskgraph-ai` and `npm install -g taskgraph-ai` don't work. Build it once from this repository (step 1). When the package is published, `npx -y taskgraph-ai` replaces `node /path/to/taskgraph-ai/dist/mcp-server.js` everywhere below.
35
-
36
73
  You need [Claude Code](https://docs.claude.com/en/docs/claude-code) installed and signed in (run `claude` once) and Node.js 22 or later.
37
74
 
38
- ### 1. Build from source
75
+ ### 1. Install
39
76
 
40
77
  ```bash
41
- git clone https://github.com/stephennmiller/taskgraph-ai.git
42
- cd taskgraph-ai
43
- npm install
44
- npm run build
78
+ npm install -g taskgraph-ai
45
79
  ```
46
80
 
47
- This creates `dist/taskgraph.js` (the CLI) and `dist/mcp-server.js` (the optional MCP server). The steps below call the folder `/path/to/taskgraph-ai`; use your real path. After pulling new changes, run `npm run build` again.
81
+ This gives you the `taskgraph` command (the CLI) and `taskgraph-mcp`, the optional MCP server. To skip the install, run any command through npx, for example `npx -y -p taskgraph-ai taskgraph list`. To build from source instead, see [Working on TaskGraph itself](#troubleshooting).
48
82
 
49
83
  ### 2. Initialize your project
50
84
 
51
85
  From your own project folder:
52
86
 
53
87
  ```bash
54
- node /path/to/taskgraph-ai/dist/taskgraph.js init --rules claude
88
+ taskgraph init --rules claude
55
89
  ```
56
90
 
57
91
  This creates `.taskgraph/` (tasks, docs, config), a `CLAUDE.md` import with TaskGraph's workflow guide, and 46 slash commands in `.claude/commands/tm/`. Don't run it twice; it only re-adds the same files.
58
92
 
59
- `init` also writes a `.mcp.json` that starts the server with `npx -y taskgraph-ai`, which won't work until the package is published. Delete that file, or if you add the MCP server (step 5), change it to the `node` command shown there.
93
+ `init` also writes a `.mcp.json` that registers the MCP server with the 7 `core` tools. Delete that file if you only want the slash commands and CLI; see step 4 to keep and configure the server.
60
94
 
61
- ### 3. Add a shell alias
62
-
63
- A shell alias keeps the commands in the rest of this README short:
64
-
65
- ```bash
66
- alias taskgraph="node /path/to/taskgraph-ai/dist/taskgraph.js"
67
- ```
68
-
69
- ### 4. (Optional) Install the plugin
95
+ ### 3. (Optional) Install the plugin
70
96
 
71
97
  The plugin adds a nearly identical set of 46 slash commands (as `/taskgraph:<name>`) and three agents (`task-orchestrator`, `task-executor`, `task-checker`).
72
98
 
@@ -75,16 +101,16 @@ The plugin adds a nearly identical set of 46 slash commands (as `/taskgraph:<nam
75
101
  /plugin install taskgraph@taskgraph
76
102
  ```
77
103
 
78
- The plugin does not register an MCP server. The `task-checker` agent uses the `taskgraph show` CLI, and uses the MCP tool instead if you registered the server as `taskgraph-ai` (step 5). Its slash commands overlap with the ones from step 2, so install the plugin only if you want the agents.
104
+ The plugin does not register an MCP server. The `task-checker` agent uses the `taskgraph show` CLI, and uses the MCP tool instead if you registered the server as `taskgraph-ai` (step 4). Its slash commands overlap with the ones from step 2, so install the plugin only if you want the agents.
79
105
 
80
- ### 5. (Optional) Add the MCP server
106
+ ### 4. (Optional) Add the MCP server
81
107
 
82
108
  Skip this unless you want to drive TaskGraph in plain language. Slash commands and the CLI do everything without it.
83
109
 
84
110
  ```bash
85
111
  claude mcp add taskgraph-ai --scope user \
86
112
  --env TASKGRAPH_TOOLS=standard \
87
- -- node /path/to/taskgraph-ai/dist/mcp-server.js
113
+ -- npx -y taskgraph-ai
88
114
  ```
89
115
 
90
116
  Restart Claude Code and run `/mcp`; `taskgraph-ai` should show as connected. `standard` loads 14 tools, enough for everything in [How to use it](#how-to-use-it). See [MCP tool tiers](#mcp-tool-tiers) for the others.
@@ -95,8 +121,8 @@ To share the setup with your team instead, put it in the project's `.mcp.json`:
95
121
  {
96
122
  "mcpServers": {
97
123
  "taskgraph-ai": {
98
- "command": "node",
99
- "args": ["/path/to/taskgraph-ai/dist/mcp-server.js"],
124
+ "command": "npx",
125
+ "args": ["-y", "taskgraph-ai"],
100
126
  "env": { "TASKGRAPH_TOOLS": "standard" }
101
127
  }
102
128
  }
@@ -105,6 +131,13 @@ To share the setup with your team instead, put it in the project's `.mcp.json`:
105
131
 
106
132
  ## How to use it
107
133
 
134
+ <p align="center">
135
+ <picture>
136
+ <source media="(prefers-color-scheme: dark)" srcset="images/how-it-works-dark.svg">
137
+ <img src="images/how-it-works.svg" alt="parse-prd turns your PRD into a task graph stored in .taskgraph/tasks/tasks.json in your repo. Each Claude Code session reads and updates that file, so a new session picks up the next task and the notes from the last one." width="820">
138
+ </picture>
139
+ </p>
140
+
108
141
  The examples below use slash commands (`/tm:...`), with the CLI equivalent in each table. If you added the optional MCP server, you can say the same things in plain language instead.
109
142
 
110
143
  ### 1. Write a PRD
@@ -189,7 +222,7 @@ taskgraph research "latest JWT best practices"
189
222
  taskgraph models --setup # choose models
190
223
  ```
191
224
 
192
- Every command, flag and example is in the [command reference](docs/command-reference.md).
225
+ Every command, flag and example is in the [command reference](apps/docs/capabilities/cli-root-commands.mdx).
193
226
 
194
227
  ## MCP tool tiers
195
228
 
@@ -207,7 +240,7 @@ Set it when you add the server:
207
240
  ```bash
208
241
  claude mcp add taskgraph-ai --scope user \
209
242
  --env TASKGRAPH_TOOLS=all \
210
- -- node /path/to/taskgraph-ai/dist/mcp-server.js
243
+ -- npx -y taskgraph-ai
211
244
  ```
212
245
 
213
246
  Or edit the `env` block in `.mcp.json`, then restart Claude Code.
@@ -216,12 +249,23 @@ Or edit the `env` block in `.mcp.json`, then restart Claude Code.
216
249
 
217
250
  TaskGraph uses three roles: **main**, **research** and **fallback** (used if either of the others fails). The choices are `opus`, `sonnet` and `haiku`. The research role gets web search and fetch only. It cannot read or change your files and has no shell.
218
251
 
219
- In Claude Code, say `Change the main model to opus`, or run `taskgraph models --setup`. Details are in [Models](docs/models.md) and the [Claude Code guide](docs/examples/claude-code-usage.md).
252
+ In Claude Code, say `Change the main model to opus`, or run `taskgraph models --setup`. Details are in [Models](docs/models.md) and the [Claude Code guide](apps/docs/capabilities/claude-code.mdx).
253
+
254
+ ## Upgrading
255
+
256
+ Projects created with Task Master, or with a TaskGraph release before 0.47, need a few manual changes:
257
+
258
+ - **Rename `.taskmaster/` to `.taskgraph/`** by hand. TaskGraph no longer detects the old folder.
259
+ - **Rename environment variables:** `TASK_MASTER_*` and `TASKMASTER_*` are now `TASKGRAPH_*`. The old names are ignored.
260
+ - **Removed:** the `taskgraph migrate` command and `.taskmasterconfig`. Configuration lives in `.taskgraph/config.json`; run `taskgraph models --setup` to recreate it.
261
+ - **Claude Code only:** other providers and their flags are gone, models are `opus`, `sonnet` and `haiku`, and the only API key still read is the optional `CLAUDE_CODE_API_KEY`.
262
+
263
+ Full details are in the [upgrade guide](apps/docs/upgrading.mdx).
220
264
 
221
265
  ## Troubleshooting
222
266
 
223
- - **`0 tools enabled` or the server won't connect:** restart Claude Code, run `/mcp`, and confirm `node /path/to/taskgraph-ai/dist/mcp-server.js` starts on its own in a terminal (it waits for input; press Ctrl+C to stop). If `dist/` is missing or stale, run `npm run build`.
224
- - **Working on TaskGraph itself:** this repository's `.mcp.json` starts `dist/mcp-server.js` relative to the repo, so run `npm run build` first or the server won't connect.
267
+ - **`0 tools enabled` or the server won't connect:** restart Claude Code, run `/mcp`, and confirm `npx -y taskgraph-ai` starts on its own in a terminal (it waits for input; press Ctrl+C to stop).
268
+ - **Working on TaskGraph itself:** build from source with `git clone https://github.com/stephennmiller/taskgraph-ai.git && cd taskgraph-ai && npm install && npm run build`, then run `node dist/taskgraph.js` for the CLI. This repository's own `.mcp.json` starts `dist/mcp-server.js` relative to the repo, so run `npm run build` first or the server won't connect.
225
269
  - **AI commands fail:** run `claude` once and make sure you're signed in.
226
270
  - **Fewer tools than expected:** `TASKGRAPH_TOOLS` defaults to `core`. Set `standard` or `all`.
227
271
  - **Commands behave oddly after `git pull`:** run `npm run build` again; the CLI and server run from `dist/`.
@@ -230,7 +274,7 @@ In Claude Code, say `Change the main model to opus`, or run `taskgraph models --
230
274
 
231
275
  ## Documentation
232
276
 
233
- [Tutorial](docs/tutorial.md) · [Command reference](docs/command-reference.md) · [Configuration](docs/configuration.md) · [Task structure](docs/task-structure.md) · [Examples](docs/examples.md) · [Models](docs/models.md) · [Plugin](CLAUDE_CODE_PLUGIN.md) · [Contributing](CONTRIBUTING.md) · [Changelog](CHANGELOG.md)
277
+ [Tutorial](apps/docs/tutorial.mdx) · [Command reference](apps/docs/capabilities/cli-root-commands.mdx) · [Configuration](apps/docs/configuration.mdx) · [Task structure](apps/docs/capabilities/task-structure.mdx) · [Examples](apps/docs/examples.mdx) · [Models](docs/models.md) · [Upgrading](apps/docs/upgrading.mdx) · [Plugin](CLAUDE_CODE_PLUGIN.md) · [Contributing](CONTRIBUTING.md) · [Changelog](CHANGELOG.md)
234
278
 
235
279
  ## Contributors
236
280
 
@@ -0,0 +1,3 @@
1
+ import{D as e,Q as t,S as n,b as r,d as i,h as a,i as o,j as s,lt as c,m as l,nt as u,o as d,p as f,q as p,u as m,v as h,x as g,y as _}from"./config-manager-CKzRb4tZ.js";import{createRequire as v}from"node:module";import{execSync as y}from"child_process";import{createClaudeCode as b}from"ai-sdk-provider-claude-code";import*as x from"ai";import{jsonrepair as S}from"jsonrepair";import{EnvHttpProxyAgent as C}from"undici";var w=Object.defineProperty,T=(e,t)=>{let n={};for(var r in e)w(n,r,{get:e[r],enumerable:!0});return t||w(n,Symbol.toStringTag,{value:`Module`}),n},E=/* @__PURE__ */ v(import.meta.url);const{JSONParseError:D,NoObjectGeneratedError:O,generateObject:k,generateText:A,streamObject:j,streamText:ee,zodSchema:te}=x,M=x.jsonSchema,N=/* @__PURE__ */ new Set([`minimum`,`maximum`,`exclusiveMinimum`,`exclusiveMaximum`]),P=[`additionalProperties`,`contains`,`if`,`then`,`else`,`not`,`propertyNames`],F=[`allOf`,`anyOf`,`oneOf`,`prefixItems`],I=[`definitions`,`$defs`,`dependentSchemas`,`patternProperties`,`properties`],ne=e=>e?Array.isArray(e)?e.includes(`integer`):e===`integer`:!1,L=e=>{if(!e||typeof e!=`object`)return e;if(Array.isArray(e))return e.map(L);let t={...e};if(ne(t.type))for(let e of N)e in t&&delete t[e];for(let e of P)t[e]&&(t[e]=L(t[e]));for(let e of F)Array.isArray(t[e])&&(t[e]=t[e].map(L));for(let e of I)if(t[e]&&typeof t[e]==`object`){let n={};for(let[r,i]of Object.entries(t[e]))n[r]=L(i);t[e]=n}return t.items&&=L(t.items),t},R=e=>{let t=te(e);if(!t||typeof t!=`object`||!t.jsonSchema)return t;let n=L(t.jsonSchema);return typeof M==`function`?M(n,{validate:t.validate}):{...t,jsonSchema:n}};var z=class t{constructor(){if(this.constructor===t)throw Error(`BaseAIProvider cannot be instantiated directly`);this.name=this.constructor.name,this._proxyAgent=null,this.needsExplicitJsonSchema=!1,this.supportsTemperature=!0}validateAuth(e){if(!e.apiKey)throw Error(`${this.name} API key is required`)}createProxyFetch(){this._projectRoot||=p();let t=this._projectRoot;if(e(null,t))return this._proxyAgent||=new C,(e,t={})=>fetch(e,{...t,dispatcher:this._proxyAgent})}validateParams(e){if(this.validateAuth(e),!e.modelId)throw Error(`${this.name} Model ID is required`);this.validateOptionalParams(e)}validateOptionalParams(e){if(e.temperature!==void 0&&(e.temperature<0||e.temperature>1))throw Error(`Temperature must be between 0 and 1`);if(e.maxTokens!==void 0){let t=Number(e.maxTokens);if(!Number.isFinite(t)||t<=0)throw Error(`maxTokens must be a finite number greater than 0`)}}validateMessages(e){if(!e||!Array.isArray(e)||e.length===0)throw Error(`Invalid or empty messages array provided`);for(let t of e)if(!t.role||!t.content)throw Error(`Invalid message format. Each message must have role and content`)}handleError(e,t){let n=t.message||`Unknown error occurred`;throw u(`error`,`${this.name} ${e} failed: ${n}`,{error:t}),Error(`${this.name} API error during ${e}: ${n}`)}getClient(e){throw Error(`getClient must be implemented by provider`)}isRequiredApiKey(){return!0}getRequiredApiKeyName(){throw Error(`getRequiredApiKeyName must be implemented by provider`)}prepareTokenParam(e,t){return t===void 0?{}:{maxOutputTokens:Math.floor(Number(t))}}prepareMessages(e){let t=e.filter(e=>e.role===`system`);return t.length===0?{messages:e}:{instructions:t.map(e=>typeof e.content==`string`?e.content:e.content.map(e=>e.text??``).join(``)).join(`
2
+
3
+ `),messages:e.filter(e=>e.role!==`system`)}}async generateText(e){try{this.validateParams(e),this.validateMessages(e.messages),u(`debug`,`Generating ${this.name} text with model: ${e.modelId}`);let t=await this.getClient(e),n=await A({model:t(e.modelId),...this.prepareMessages(e.messages),...this.prepareTokenParam(e.modelId,e.maxTokens),...this.supportsTemperature&&e.temperature!==void 0?{temperature:e.temperature}:{}});u(`debug`,`${this.name} generateText completed successfully for model: ${e.modelId}`);let r=n.usage?.inputTokens??n.usage?.promptTokens??0,i=n.usage?.outputTokens??n.usage?.completionTokens??0,a=n.usage?.totalTokens??r+i;return{text:n.text,usage:{inputTokens:r,outputTokens:i,totalTokens:a}}}catch(e){this.handleError(`text generation`,e)}}async streamText(e){try{this.validateParams(e),this.validateMessages(e.messages),u(`debug`,`Streaming ${this.name} text with model: ${e.modelId}`);let t=await this.getClient(e),n=await ee({model:t(e.modelId),...this.prepareMessages(e.messages),...this.prepareTokenParam(e.modelId,e.maxTokens),...this.supportsTemperature&&e.temperature!==void 0?{temperature:e.temperature}:{},...e.experimental_transform&&{experimental_transform:e.experimental_transform}});return u(`debug`,`${this.name} streamText initiated successfully for model: ${e.modelId}`),n}catch(e){this.handleError(`text streaming`,e)}}async streamObject(e){try{if(this.validateParams(e),this.validateMessages(e.messages),!e.schema)throw Error(`Schema is required for object streaming`);u(`debug`,`Streaming ${this.name} object with model: ${e.modelId}`);let t=await this.getClient(e),n=R(e.schema),r=await j({model:t(e.modelId),...this.prepareMessages(e.messages),schema:n,mode:e.mode||`auto`,maxOutputTokens:e.maxTokens,...this.supportsTemperature&&e.temperature!==void 0?{temperature:e.temperature}:{}});return u(`debug`,`${this.name} streamObject initiated successfully for model: ${e.modelId}`),r}catch(e){this.handleError(`object streaming`,e)}}async generateObject(e){try{if(this.validateParams(e),this.validateMessages(e.messages),!e.schema)throw Error(`Schema is required for object generation`);if(!e.objectName)throw Error(`Object name is required for object generation`);u(`debug`,`Generating ${this.name} object ('${e.objectName}') with model: ${e.modelId}`);let t=await this.getClient(e),n=R(e.schema),r=await k({model:t(e.modelId),...this.prepareMessages(e.messages),schema:n,mode:this.needsExplicitJsonSchema?`json`:`auto`,schemaName:e.objectName,schemaDescription:`Generate a valid JSON object for ${e.objectName}`,maxTokens:e.maxTokens,...this.supportsTemperature&&e.temperature!==void 0?{temperature:e.temperature}:{}});u(`debug`,`${this.name} generateObject completed successfully for model: ${e.modelId}`);let i=r.usage?.inputTokens??r.usage?.promptTokens??0,a=r.usage?.outputTokens??r.usage?.completionTokens??0,o=r.usage?.totalTokens??i+a;return{object:r.object,usage:{inputTokens:i,outputTokens:a,totalTokens:o}}}catch(e){if(O.isInstance(e)&&e.cause instanceof D&&e.cause.text){u(`warn`,`${this.name} generated malformed JSON, attempting to repair...`);try{let t=S(e.cause.text),n=JSON.parse(t);return u(`info`,`Successfully repaired ${this.name} JSON output`),{object:n,usage:{inputTokens:e.usage?.promptTokens||e.usage?.inputTokens||0,outputTokens:e.usage?.completionTokens||e.usage?.outputTokens||0,totalTokens:e.usage?.totalTokens||0}}}catch(e){u(`error`,`Failed to repair ${this.name} JSON: ${e.message}`)}}this.handleError(`object generation`,e)}}};let B=!1;const V=[`WebSearch`,`WebFetch`],H=[`Read`,`Grep`,`Glob`];function U(e,t){let n=e===`research`,r=n?V:H;return{tools:[...r],allowedTools:[...r],permissionMode:`dontAsk`,permissionPrompts:`none`,strictMcpConfig:!0,mcpServers:{},...n&&{settingSources:[],maxTurns:t.maxTurns??8}}}var W=class extends z{constructor(){super(),this.name=`Claude Code`,this.supportedModels=g(`claude-code`),this.supportedModels.length===0&&u(`warn`,`No supported models found for claude-code provider. Check supported-models.json configuration.`),this.needsExplicitJsonSchema=!0,this.supportsTemperature=!1}getRequiredApiKeyName(){return`CLAUDE_CODE_API_KEY`}isRequiredApiKey(){return!1}validateAuth(e){if(process.env.NODE_ENV!==`test`&&!B&&!process.env.CLAUDE_CODE_OAUTH_TOKEN)try{y(`claude --version`,{stdio:`pipe`,timeout:1e3})}catch{u(`warn`,`Claude Code CLI not detected. Install it with: npm install -g @anthropic-ai/claude-code`)}finally{B=!0}}getClient(e={}){try{let t=o(e.commandName)||{},n={...process.env};return process.env.CLAUDE_CODE_API_KEY?n.ANTHROPIC_API_KEY=process.env.CLAUDE_CODE_API_KEY:delete n.ANTHROPIC_API_KEY,b({defaultSettings:{systemPrompt:{type:`preset`,preset:`claude_code`},settingSources:[`user`,`project`,`local`],env:n,...t,...U(e.role,t)}})}catch(e){let t=String(e?.message||``);if(e?.code===`ENOENT`||/claude/i.test(t)){let t=/* @__PURE__ */ Error(`Claude Code CLI not available. Please install Claude Code CLI first. Original error: ${e.message}`);t.cause=e,this.handleError(`Claude Code CLI initialization`,t)}else this.handleError(`client initialization`,e)}}getSupportedModels(){return this.supportedModels}isModelSupported(e){return e?this.supportedModels.includes(String(e).toLowerCase()):!1}};let G=null;var K=class e{constructor(){this._providers=/* @__PURE__ */ new Map,this._initialized=!1}static getInstance(){return G||=new e,G}initialize(){return this._initialized||=!0,this}registerProvider(e,t,n={}){if(!e||typeof e!=`string`)throw Error(`Provider name must be a non-empty string`);if(!t)throw Error(`Provider instance is required`);if(typeof t.generateText!=`function`||typeof t.streamText!=`function`||typeof t.generateObject!=`function`)throw Error(`Provider must implement BaseAIProvider interface`);return this._providers.set(e,{instance:t,options:n,registeredAt:/* @__PURE__ */ new Date}),this}hasProvider(e){return this._providers.has(e)}getProvider(e){let t=this._providers.get(e);return t?t.instance:null}getAllProviders(){return new Map(this._providers)}unregisterProvider(e){return this._providers.has(e)?(this._providers.delete(e),!0):!1}reset(){this._providers.clear(),this._initialized=!1}};K.getInstance().initialize();const q={"claude-code":new W};function J(e){if(q[e])return q[e];let t=K.getInstance();return t.hasProvider(e)?(u(`debug`,`Provider "${e}" found in dynamic registry`),t.getProvider(e)):null}function Y(e,t){let n={inputCost:0,outputCost:0,currency:`USD`,isUnknown:!1};if(!s||!s[e])return u(`warn`,`Provider "${e}" not found in MODEL_MAP. Cannot determine cost for model ${t}.`),{...n,isUnknown:!0};let r=s[e].find(e=>e.id===t);if(!r)return u(`debug`,`Model "${t}" not found under provider "${e}". Assuming unknown cost.`),{...n,isUnknown:!0};if(r.cost_per_1m_tokens===null)return u(`debug`,`Cost data is null for model "${t}" under provider "${e}". Pricing unknown.`),{...n,isUnknown:!0};if(r.cost_per_1m_tokens===void 0)return u(`debug`,`Cost data not found for model "${t}" under provider "${e}". Pricing unknown.`),{...n,isUnknown:!0};let i=r.cost_per_1m_tokens;return{inputCost:i.input||0,outputCost:i.output||0,currency:i.currency||`USD`,isUnknown:!1}}function X(e,t,n,r){let i=(e||0)/1e6*n+(t||0)/1e6*r;return parseFloat(i.toFixed(6))}function re(e){let n={currentTag:`master`,availableTags:[`master`]};try{return e?{currentTag:t(e)||`master`,availableTags:ie(e)}:n}catch(e){return d()&&u(`debug`,`Error getting tag information: ${e.message}`),n}}function ie(e){let t=[`master`];try{let n=E(`path`),r=E(`fs`),i=n.join(e,`.taskgraph`,`tasks`,`tasks.json`);if(!r.existsSync(i))return t;let a=JSON.parse(r.readFileSync(i,`utf8`));if(!a||typeof a!=`object`)return t;let o=Object.keys(a).filter(e=>ae(a[e]));return o.length>0?o:t}catch(e){return d()&&u(`debug`,`Could not read tasks file for available tags: ${e.message}`),t}}function ae(e){return e&&typeof e==`object`&&Array.isArray(e.tasks)}function oe(e){let t=e.message?.toLowerCase()||``;return t.includes(`rate limit`)||t.includes(`overloaded`)||t.includes(`service temporarily unavailable`)||t.includes(`timeout`)||t.includes(`network error`)||e.status===429||e.status>=500}function se(e){try{if(e?.data?.error?.message)return e.data.error.message;if(e?.error?.message)return e.error.message;if(typeof e?.responseBody==`string`)try{let t=JSON.parse(e.responseBody);if(t?.error?.message)return t.error.message}catch{}return typeof e?.message==`string`&&e.message?e.message:typeof e==`string`?e:`An unknown AI service error occurred.`}catch{return`Failed to extract error message.`}}function ce(e,t){return{main:{provider:l(t),modelId:f(t)},research:{provider:_(t),modelId:h(t)},fallback:{provider:i(t),modelId:m(t)}}[e]||null}function Z(e,t,n=null){let r=J(e);if(!r)throw Error(`Unknown provider '${e}' for API key resolution.`);let i=r.getRequiredApiKeyName();if(i===null)return null;let a=c(i,t,n);if(!r.isRequiredApiKey())return a||null;if(!a)throw Error(`Required API key ${i} for provider '${e}' is not set in environment, session, or .env file.`);return a}async function le(e,t,n,r,i,a){let o=0,s=t;for(;o<=2;)try{d()&&u(`info`,`Attempt ${o+1}/3 calling ${s} (Provider: ${r}, Model: ${i}, Role: ${a})`);let c=await e[t](n);return d()&&u(`info`,`${s} succeeded for role ${a} (Provider: ${r}) on attempt ${o+1}`),c}catch(e){if(u(`warn`,`Attempt ${o+1} failed for role ${a} (${s} / ${r}): ${e.message}`),oe(e)&&o<2){o++;let e=1e3*2**(o-1);u(`info`,`Something went wrong on the provider side. Retrying in ${e/1e3}s...`),await new Promise(t=>setTimeout(t,e))}else throw u(`error`,`Something went wrong on the provider side. Max retries reached for role ${a} (${s} / ${r}).`),e}throw Error(`Exhausted all retries for role ${a} (${s} / ${r})`)}async function Q(e,t){let{role:i,session:o,projectRoot:s,systemPrompt:c,prompt:l,schema:f,objectName:m,commandName:h,outputType:g,experimental_transform:_,...v}=t;d()&&u(`info`,`${e}Service called`,{role:i,commandName:h,outputType:g,projectRoot:s});let y=s||p(),b=n(y),x;i===`main`?x=[`main`,`fallback`,`research`]:i===`research`?x=[`research`,`fallback`,`main`]:i===`fallback`?x=[`fallback`,`main`,`research`]:(u(`warn`,`Unknown initial role: ${i}. Defaulting to main -> fallback -> research sequence.`),x=[`main`,`fallback`,`research`]);let S=/* @__PURE__ */ new Set,C=null,w=`AI service call failed for all configured roles.`;for(let t of x){let n,i,s,d,p,x,T=null;try{u(`debug`,`New AI service call with role: ${t}`);let w=ce(t,y);if(!w){u(`error`,`Unknown role encountered in _unifiedServiceRunner: ${t}`),C||=/* @__PURE__ */ Error(`Unknown AI role specified: ${t}`);continue}if(n=w.provider,i=w.modelId,!n||!i){u(`warn`,`Skipping role '${t}': Provider or Model ID not configured.`),C||=/* @__PURE__ */ Error(`Configuration missing for role '${t}'. Provider: ${n}, Model: ${i}`);continue}if(S.has(`${n}/${i}`)){u(`debug`,`Skipping role '${t}': ${n}/${i} already failed for this request.`);continue}if(p=J(n?.toLowerCase()),!p){u(`warn`,`Skipping role '${t}': Provider '${n}' not supported.`),C||=/* @__PURE__ */ Error(`Unsupported provider configured: ${n}`);continue}d=a(t,y),s=Z(n?.toLowerCase(),o,y);let E=[],D=`${c} \n\n Always respond in ${r(y)}.`;if(E.push({role:`system`,content:D.trim()}),l)E.push({role:`user`,content:l});else throw Error(`User prompt content is missing.`);let O={apiKey:s,modelId:i,maxTokens:d.maxTokens,temperature:d.temperature,messages:E,...(e===`generateObject`||e===`streamObject`)&&{schema:f,objectName:m},role:t,...h&&{commandName:h},..._&&{experimental_transform:_},...v};if(x=await le(p,e,O,n,i,t),b&&x&&x.usage)try{T=await $({userId:b,commandName:h,providerName:n,modelId:i,inputTokens:x.usage.inputTokens,outputTokens:x.usage.outputTokens,outputType:g})}catch{}else b&&x&&!x.usage&&u(`warn`,`Cannot log telemetry for ${h} (${n}/${i}): AI result missing 'usage' data. (May be expected for streams)`);let k;e===`generateText`?k=x.text:e===`generateObject`?k=x.object:(e===`streamText`||e===`streamObject`||u(`error`,`Unknown serviceType in _unifiedServiceRunner: ${e}`),k=x);let A=re(y);return{mainResult:k,telemetryData:T,tagInfo:A,providerName:n,modelId:i}}catch(r){let a=se(r);if(u(`error`,`Service call failed for role ${t} (Provider: ${n||`unknown`}, Model: ${i||`unknown`}): ${a}`),C=r,w=a,n&&i&&S.add(`${n}/${i}`),e===`generateObject`){let e=a.toLowerCase();if(e.includes(`no endpoints found that support tool use`)||e.includes(`does not support tool_use`)||e.includes(`tool use is not supported`)||e.includes(`tools are not supported`)||e.includes(`function calling is not supported`)||e.includes(`tool use is not supported`)){let e=`Model '${i||`unknown`}' via provider '${n||`unknown`}' does not support the 'tool use' required by generateObjectService. Please configure a model that supports tool/function calling for the '${t}' role, or use generateTextService if structured output is not strictly required.`;throw u(`error`,`[Tool Support Error] ${e}`),Error(e)}}}}throw u(`error`,`All roles in the sequence [${x.join(`, `)}] failed.`),Error(w)}async function ue(e){return Q(`generateText`,{outputType:`cli`,...e})}async function de(e){return Q(`streamText`,{outputType:`cli`,...e})}async function fe(e){let t={outputType:`cli`,...e};if(!t.schema)throw Error(`streamObjectService requires a schema parameter`);return Q(`streamObject`,t)}async function pe(e){return Q(`generateObject`,{objectName:`generated_object`,maxRetries:3,outputType:`cli`,...e})}async function $({userId:e,commandName:t,providerName:n,modelId:r,inputTokens:i,outputTokens:a,outputType:o}){try{let o=(/* @__PURE__ */ new Date()).toISOString(),s=(i||0)+(a||0),{inputCost:c,outputCost:l,currency:f,isUnknown:p}=Y(n,r),m=X(i,a,c,l),h={timestamp:o,userId:e,commandName:t,modelUsed:r,providerName:n,inputTokens:i||0,outputTokens:a||0,totalTokens:s,totalCost:m,currency:f,isUnknownCost:p};return d()&&u(`info`,`AI Usage Telemetry:`,h),h}catch(e){return u(`error`,`Failed to log AI usage telemetry: ${e.message}`,{error:e}),null}}export{de as a,fe as i,ue as n,T as o,$ as r,pe as t};
@@ -0,0 +1 @@
1
+ export{r as logAiUsage}from"./ai-services-unified-BbSRBK0N.js";
@@ -43,7 +43,7 @@ taskgraph generate # Update task markdow
43
43
  - `.taskgraph/config.json` - AI model configuration (use `taskgraph models` to modify)
44
44
  - `.taskgraph/docs/prd.md` - Product Requirements Document for parsing (`.md` extension recommended for better editor support)
45
45
  - `.taskgraph/tasks/*.txt` - Individual task files (auto-generated from tasks.json)
46
- - `.env` - API keys for CLI usage
46
+ - `.env` - Optional environment variables (for example `CLAUDE_CODE_API_KEY`)
47
47
 
48
48
  **PRD File Format:** While both `.txt` and `.md` extensions work, **`.md` is recommended** because:
49
49
  - Markdown syntax highlighting in editors improves readability
@@ -76,7 +76,7 @@ project/
76
76
  ├── .claude/
77
77
  │ ├── settings.json # Claude Code configuration
78
78
  │ └── commands/ # Custom slash commands
79
- ├── .env # API keys
79
+ ├── .env # Optional env vars
80
80
  ├── .mcp.json # MCP configuration
81
81
  └── CLAUDE.md # This file - auto-loaded by Claude Code
82
82
  ```
@@ -110,16 +110,7 @@ TaskGraph also provides an MCP server that Claude Code can connect to. It is opt
110
110
  "command": "npx",
111
111
  "args": ["-y", "taskgraph-ai"],
112
112
  "env": {
113
- "TASKGRAPH_TOOLS": "core",
114
- "ANTHROPIC_API_KEY": "your_key_here",
115
- "PERPLEXITY_API_KEY": "your_key_here",
116
- "OPENAI_API_KEY": "OPENAI_API_KEY_HERE",
117
- "GOOGLE_API_KEY": "GOOGLE_API_KEY_HERE",
118
- "XAI_API_KEY": "XAI_API_KEY_HERE",
119
- "OPENROUTER_API_KEY": "OPENROUTER_API_KEY_HERE",
120
- "MISTRAL_API_KEY": "MISTRAL_API_KEY_HERE",
121
- "AZURE_OPENAI_API_KEY": "AZURE_OPENAI_API_KEY_HERE",
122
- "OLLAMA_API_KEY": "OLLAMA_API_KEY_HERE"
113
+ "TASKGRAPH_TOOLS": "core"
123
114
  }
124
115
  }
125
116
  }
@@ -261,19 +252,9 @@ Add to `.claude/settings.json`:
261
252
 
262
253
  ## Configuration & Setup
263
254
 
264
- ### API Keys Required
255
+ ### Authentication
265
256
 
266
- At least **one** of these API keys must be configured:
267
-
268
- - `ANTHROPIC_API_KEY` (Claude models) - **Recommended**
269
- - `PERPLEXITY_API_KEY` (Research features) - **Highly recommended**
270
- - `OPENAI_API_KEY` (GPT models)
271
- - `GOOGLE_API_KEY` (Gemini models)
272
- - `MISTRAL_API_KEY` (Mistral models)
273
- - `OPENROUTER_API_KEY` (Multiple models)
274
- - `XAI_API_KEY` (Grok models)
275
-
276
- An API key is required for any provider used across any of the 3 roles defined in the `models` command.
257
+ TaskGraph runs every AI call through your signed-in Claude Code, so no provider API keys are needed. Run `claude` once to sign in. Optionally set `CLAUDE_CODE_API_KEY` to bill calls to a specific Anthropic API key.
277
258
 
278
259
  ### Model Configuration
279
260
 
@@ -282,9 +263,9 @@ An API key is required for any provider used across any of the 3 roles defined i
282
263
  taskgraph models --setup
283
264
 
284
265
  # Set specific models
285
- taskgraph models --set-main claude-sonnet-5-5
286
- taskgraph models --set-research perplexity-llama-3.1-sonar-large-128k-online
287
- taskgraph models --set-fallback gpt-4o-mini
266
+ taskgraph models --set-main sonnet
267
+ taskgraph models --set-research opus
268
+ taskgraph models --set-fallback haiku
288
269
  ```
289
270
 
290
271
  ## Task Structure & IDs
@@ -377,14 +358,14 @@ cd ../project-api && claude # Terminal 2: API work
377
358
  ### AI Commands Failing
378
359
 
379
360
  ```bash
380
- # Check API keys are configured
381
- cat .env # For CLI usage
361
+ # Make sure Claude Code is installed and signed in
362
+ claude --version
382
363
 
383
364
  # Verify model configuration
384
365
  taskgraph models
385
366
 
386
367
  # Test with different model
387
- taskgraph models --set-fallback gpt-4o-mini
368
+ taskgraph models --set-fallback haiku
388
369
  ```
389
370
 
390
371
  ### MCP Connection Issues (only if you use MCP)
@@ -444,7 +425,7 @@ These commands make AI calls and may take up to a minute:
444
425
  ### Research Mode
445
426
 
446
427
  - Add `--research` flag for research-based AI enhancement
447
- - Requires a research model API key like Perplexity (`PERPLEXITY_API_KEY`) in environment
428
+ - The research role has web search and fetch only; it cannot read or change your files
448
429
  - Provides more informed task creation and updates
449
430
  - Recommended for complex technical tasks
450
431
 
@@ -26,11 +26,8 @@ When using this template to **create** a PRD (not parse it), use **code-context-
26
26
 
27
27
  **Recommended tools:**
28
28
  - **Claude Code** (claude-code CLI) - Best for structured reasoning and large contexts
29
- - **Cursor/Windsurf** - IDE integration with full codebase context
30
- - **Gemini CLI** (gemini-cli) - Massive context window for large codebases
31
- - **Codex/Grok CLI** - Strong code generation with context awareness
32
29
 
33
- **Note:** Once your PRD is created, `taskgraph parse-prd` works with any configured AI model - it just needs to read the PRD text itself, not your codebase.
30
+ **Note:** Once your PRD is created, `taskgraph parse-prd` works with Claude Code - it just needs to read the PRD text itself, not your codebase.
34
31
  </rpg-method>
35
32
 
36
33
  ---
@@ -12,7 +12,7 @@ In an AI-driven development process—particularly with tools like [Cursor](http
12
12
  4. **Generate** individual task files (e.g., `task_001.txt`) for easy reference or to feed into an AI coding workflow.
13
13
  5. **Set task status**—mark tasks as `done`, `pending`, or `deferred` based on progress.
14
14
  6. **Expand** tasks with subtasks—break down complex tasks into smaller, more manageable subtasks.
15
- 7. **Research-backed subtask generation**—use Perplexity AI to generate more informed and contextually relevant subtasks.
15
+ 7. **Research-backed subtask generation**—use the research model to generate more informed and contextually relevant subtasks.
16
16
  8. **Clear subtasks**—remove subtasks from specified tasks to allow regeneration or restructuring.
17
17
  9. **Show task details**—display detailed information about a specific task and its subtasks.
18
18
 
@@ -26,10 +26,10 @@ TaskGraph configuration is now managed through two primary methods:
26
26
  - Managed using the `taskgraph models --setup` command or the `models` MCP tool.
27
27
  - This is the main configuration file for most settings.
28
28
 
29
- 2. **Environment Variables (`.env` File - API Keys Only)**
30
- - Used **only** for sensitive **API Keys** (e.g., `ANTHROPIC_API_KEY`, `PERPLEXITY_API_KEY`).
31
- - Create a `.env` file in your project root for CLI usage.
32
- - See `assets/env.example` for required key names.
29
+ 2. **Environment Variables (optional)**
30
+ - TaskGraph needs no provider API keys; AI calls run through your signed-in Claude Code.
31
+ - `CLAUDE_CODE_API_KEY` optionally bills calls to a specific Anthropic API key.
32
+ - See the Configuration page in the TaskGraph docs for the `TASKGRAPH_*` variables.
33
33
 
34
34
  **Important:** Settings like `MODEL`, `MAX_TOKENS`, `TEMPERATURE`, `TASKGRAPH_LOG_LEVEL`, etc., are **no longer set via `.env`**. Use `taskgraph models --setup` instead.
35
35
 
@@ -160,10 +160,10 @@ taskgraph expand --all
160
160
  # Force regeneration of subtasks for all pending tasks
161
161
  taskgraph expand --all --force
162
162
 
163
- # Use Perplexity AI for research-backed subtask generation
163
+ # Use the research model for research-backed subtask generation
164
164
  taskgraph expand --id=3 --research
165
165
 
166
- # Use Perplexity AI for research-backed generation on all pending tasks
166
+ # Use the research model for research-backed generation on all pending tasks
167
167
  taskgraph expand --all --research
168
168
  ```
169
169
 
@@ -192,11 +192,9 @@ Notes:
192
192
  ## AI Integration (Updated)
193
193
 
194
194
  - The script now uses a unified AI service layer (`ai-services-unified.js`).
195
- - Model selection (e.g., Claude vs. Perplexity for `--research`) is determined by the configuration in `.taskgraph/config.json` based on the requested `role` (`main` or `research`).
196
- - API keys are automatically resolved from your `.env` file (for CLI) or MCP session environment.
197
- - To use the research capabilities (e.g., `expand --research`), ensure you have:
198
- 1. Configured a model for the `research` role using `taskgraph models --setup` (Perplexity models are recommended).
199
- 2. Added the corresponding API key (e.g., `PERPLEXITY_API_KEY`) to your `.env` file.
195
+ - Model selection (for example `opus`, `sonnet` or `haiku`) is determined by the configuration in `.taskgraph/config.json` based on the requested `role` (`main` or `research`).
196
+ - No provider API keys are needed; calls run through your signed-in Claude Code.
197
+ - To use the research capabilities (for example `expand --research`), configure a model for the `research` role with `taskgraph models --setup`.
200
198
 
201
199
  ## Logging
202
200
 
@@ -317,13 +315,13 @@ taskgraph analyze-complexity --model=claude-3-opus-20240229
317
315
  # Set a custom complexity threshold (1-10)
318
316
  taskgraph analyze-complexity --threshold=6
319
317
 
320
- # Use Perplexity AI for research-backed complexity analysis
318
+ # Use the research model for research-backed complexity analysis
321
319
  taskgraph analyze-complexity --research
322
320
  ```
323
321
 
324
322
  Notes:
325
323
 
326
- - The command uses Claude to analyze each task's complexity (or Perplexity with --research flag)
324
+ - The command uses Claude to analyze each task's complexity (or the research model with the --research flag)
327
325
  - Tasks are scored on a scale of 1-10
328
326
  - Each task receives a recommended number of subtasks based on DEFAULT_SUBTASKS configuration
329
327
  - The default output path is `scripts/task-complexity-report.json`