ai-projects 1.6.0 → 1.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -12,18 +12,19 @@ AIP has a comprehensive built-in help system for every level:
12
12
  # 🚀 New here? Start with the quick guide
13
13
  aip help quickstart
14
14
 
15
- # 📋 Browse all commands by noun
16
- aip help usage
15
+ # 📋 Read list of verbs by all nouns
16
+ aip --help # Same as `aip help usage`
17
17
 
18
- # 🎯 Need commands for a specific noun?
19
- aip help usage task # All task commands
20
- aip help usage project # All project commands
21
- aip help usage log # All logging commands
18
+ # 🎯 List of verbs by noun
19
+ aip task --help # Same as `aip help usage task`
20
+
21
+ # 📋 Get all parameters and --options for a command
22
+ aip task create --help
22
23
 
23
24
  # 📖 Complete API reference (comprehensive!)
24
25
  aip help api
25
26
 
26
- # 🛠️ Project management skill documentation
27
+ # 🛠️ Project management skill documentation (can be piped to a SKILL.md)
27
28
  aip help skill
28
29
 
29
30
  # 🔗 Hook system documentation
@@ -41,17 +42,13 @@ aip help hooks
41
42
  ## 🚀 Quick Start
42
43
 
43
44
  ```bash
44
- # Create a project with multi-line body
45
- aip project create "my-project" --description "..." --body "$(cat <<'EOF'
46
- # Goals
47
- - Build something amazing
48
- - Solve real problems
49
-
50
- ## Success Criteria
51
- - Tests passing
52
- - Documentation complete
53
- EOF
54
- )"
45
+ # Create project with body (inline - cleanest)
46
+ aip project create "my-project" --description "..." --body $'# Goals\n- Build X\n- Solve Y'
47
+
48
+ # Create project with body (here-string for multi-line)
49
+ aip project create "my-project" --description "..." --body "$(cat <<< '# Goals
50
+ - Build X
51
+ - Solve Y')"
55
52
 
56
53
  # Create a task in the project
57
54
  aip task create my-project "first-task" --description "Get started"
@@ -59,6 +56,9 @@ aip task create my-project "first-task" --description "Get started"
59
56
  # Navigate and work
60
57
  cd $(aip task path first-task)
61
58
 
59
+ # Start working (and read in all context to stdout)
60
+ aip task start
61
+
62
62
  # Log your progress
63
63
  aip log append "API integration complete"
64
64
 
@@ -66,8 +66,28 @@ aip log append "API integration complete"
66
66
  aip log read
67
67
  ```
68
68
 
69
+ ## 🏠 AIP_HOME - Project Root Directory
70
+
71
+ AIP stores all projects, tasks, and agents under `$AIP_HOME`.
72
+
73
+ **Set it in your `~/.bashrc` (or `~/.zshrc`):**
74
+ ```bash
75
+ export AIP_HOME=/path/to/your/aip-root
76
+ ```
77
+
78
+ **Auto-detection (if `AIP_HOME` is not set):**
79
+ AIP automatically detects the root by traversing up from your current directory looking for standard folders (`projects/`, `skills/`, `agents/`). This means you can `cd` anywhere in your project structure and AIP will find the root.
80
+
81
+ ```bash
82
+ # No setup needed - just run from anywhere in your project
83
+ cd /path/to/aip-root/projects/my-project/tasks/some-task
84
+ aip task list # Works! AIP detected the root
85
+ ```
86
+
69
87
  ## 📁 Project Structure
70
88
 
89
+ Once AIP_HOME is determined, the structure is:
90
+
71
91
  ```
72
92
  $AIP_HOME/projects/{project}/
73
93
  ├── main.md # Goals + body (YAML frontmatter + markdown)
@@ -98,6 +118,7 @@ aip task create my-project "task-name" --description "..."
98
118
  aip task update --status in-progress
99
119
  aip task list
100
120
  aip task path task-name # Get absolute path
121
+ aip task start # Start working (and read in all context to stdout)
101
122
  ```
102
123
 
103
124
  ### Logging
@@ -109,34 +130,21 @@ aip log read # View status history
109
130
 
110
131
  ### Utilities
111
132
  ```bash
112
- aip task ingest # Output full context for AI agents
113
- aip task start # Mark as in-progress
114
133
  aip help quickstart # Get started guide
134
+ aip help skill --mode claude > ~/.claude/skills/aip/SKILL.md
135
+ aip help skill --mode hermes > ~/.hermes/skills/some_toolset/aip/SKILL.md
115
136
  ```
116
137
 
117
- ## 🤖 For AI Agents
118
-
119
- If you're an AI agent working with AIP:
120
-
121
- 1. **Read** `$AIP_HOME/AGENTS.md` first
122
- 2. **Review** `main.md` for goals and context
123
- 3. **Check** `log.tsv` for activity history
124
- 4. **Work** and save outputs to `outputs/`
125
- 5. **Log** progress: `aip log append "message"`
126
- 6. **Complete**: Set status=done, summarize in project status
127
-
128
138
  ## 💡 Pro Tips
129
139
 
130
140
  ```bash
131
141
  # Chain commands
132
142
  cd $(aip task path my-task) && aip task start
133
143
 
134
- # Use heredocs for complex body content
135
- aip project update --body "$(cat <<'EOF'
136
- # Updated Goals
137
- ...
138
- EOF
139
- )"
144
+ # Use here-string for complex body content
145
+ aip project update --body "$(cat <<< '# Updated Goals
146
+ - New goal 1
147
+ - New goal 2')"
140
148
 
141
149
  # Quick status check
142
150
  aip log read | tail -5
package/dist/index.d.ts CHANGED
@@ -357,16 +357,6 @@ declare const commands: {
357
357
  }>>;
358
358
  };
359
359
  readonly util: {
360
- readonly postmortem: CommandDef<zod.ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, zod.ZodObject<{
361
- project: zod.ZodString;
362
- task: zod.ZodString;
363
- }, "strip", zod.ZodTypeAny, {
364
- project: string;
365
- task: string;
366
- }, {
367
- project: string;
368
- task: string;
369
- }>>;
370
360
  readonly read: CommandDef<zod.ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, zod.ZodObject<{
371
361
  paths: zod.ZodArray<zod.ZodString, "many">;
372
362
  }, "strip", zod.ZodTypeAny, {
package/dist/index.js CHANGED
@@ -1,26 +1,26 @@
1
1
  #!/usr/bin/env node
2
- import {z as z$1}from'zod';import {parser}from'zod-opts';import Ve from'dotenv';import We from'fs';import G from'path';import {fileURLToPath}from'url';import {spawn,exec}from'child_process';import z from'fs/promises';import w from'lodash';import Z from'moment';import {inspect}from'util';import vt from'yaml';var Ge=Object.defineProperty;var g=(t,e)=>()=>(t&&(e=t(t=0)),e);var Me=(t,e)=>{for(var o in e)Ge(t,o,{get:e[o],enumerable:true});};var S,W=g(()=>{S={name:"ai-projects",version:"1.6.0",type:"module",description:"Useful CLI for AI agents to create and manage projects, tasks, skills and agents",main:"dist/index.js",types:"dist/index.d.ts",bin:{aip:"dist/index.js"},files:["dist/**/*","README.md","LICENSE"],scripts:{build:"npm run build:map && npm run build:code","build:map":"tsx bin/map-commands.ts","build:code":"tsup --no-dts","build:all":"npm run build:map && tsup","build:check":"tsc --noEmit","build:watch":"npm run build:code -- --watch","build:clean":"rimraf dist/*","build:incr":"tsup --no-dts",start:"dist/index.js",dev:'npm run build:watch -- --onSuccess "dist/index.js"',cli:"npm run build && npm start --",ts:"tsx",vitest:"VITE_CJS_IGNORE_WARNING=true vitest",test:"npm run test:types && npm run test:unit","test:unit":"npm run vitest -- run","test:types:test":"tsc -p tsconfig.test.json --incremental --tsBuildInfoFile dist/test.tsbuildinfo","test:types:bin":"tsc -p bin/tsconfig.json --incremental --tsBuildInfoFile dist/bin.tsbuildinfo","test:types":"npm run test:types:test && npm run test:types:bin","test:full":"npm run lint:full && npm run test",eslint:"eslint --cache",lint:"npm run eslint -- '{src,bin}/**/*.ts'","lint:fix":"npm run lint -- --fix","lint:full":"npm run build:incr && npm run test:types:bin && npm run lint:fix","lint:full:silent":"npm run -s lint:full && echo LINT OK",map:"npm run build:map",link:"npm link",unlink:"npm unlink",prepare:'[ "$CI" != "true" ] && [ -d node_modules/husky ] && husky || true',prepack:"npm run test:full && npm run build:all","publish:dry":"npm pack --dry-run","version:patch":"npm version patch","version:minor":"npm version minor","version:major":"npm version major","agent:stop":"npm run -s lint:full:silent"},keywords:["ai","aip","project","task","kanban","cli","agent","automation"],author:"Ariel Flesler <aflesler@gmail.com>",license:"MIT",repository:{type:"git",url:"git+https://github.com/flesler/ai-projects.git"},homepage:"https://github.com/flesler/ai-projects#readme",bugs:{url:"https://github.com/flesler/ai-projects/issues"},engines:{node:">=20.0.0"},dependencies:{dotenv:"^17.3.1",lodash:"^4.17.21",moment:"^2.30.1",tslib:"^2.8.1",yaml:"^2.8.0",zod:"^3.25.76","zod-opts":"^1.0.0"},devDependencies:{"@eslint/js":"^10.0.1","@stylistic/eslint-plugin":"^5.7.0","@types/dotenv":"^8.2.3","@types/eslint":"^9.6.1","@types/lodash":"^4.17.23","@types/moment":"^2.13.0","@types/node":"^25.0.9","@types/source-map-support":"^0.5.10","@typescript-eslint/eslint-plugin":"^8.53.0","@typescript-eslint/parser":"^8.53.0",eslint:"^10.0.3","eslint-plugin-import-x":"^4.16.2","eslint-plugin-unused-imports":"^4.4.1","fast-glob":"^3.3.3",husky:"^9.1.7",rimraf:"^6.0.1","source-map-support":"^0.5.21",tsup:"^8.5.1",tsx:"^4.20.3","types-package-json":"^2.0.39",typescript:"^5.8.3",vitest:"^4.0.17"}};});function p(t){let{description:e,options:o=z$1.object({}),args:r,handler:n}=t,i=o.shape,a={};for(let[m,d]of Object.entries(i))a[m]={type:d};let l=parser().options(a);if(r){let m=r.shape,d=Object.entries(m).map(([f,b])=>({name:f,type:b}));d.length>0&&(l=l.args(d));}return e&&(l=l.description(e)),{description:e,options:o,args:r,parser:l,handler:n,cli:m=>n(l.parse(m))}}var k=g(()=>{});var c,P=g(()=>{c={dirs:{PROJECTS:"projects",SKILLS:"skills",AGENTS:"agents",TASKS:"tasks",INPUTS:"inputs",OUTPUTS:"outputs",HOOKS:"hooks",SCRIPTS:"scripts"},files:{MAIN:"main.md",LOG:"log.tsv",SKILL:"SKILL.md"},hookTypes:["pre-create","post-create","pre-complete","post-complete","pre-start","post-start","pre-update","post-update"],languages:["ts","js","sh","py"],targets:["project","task"]};});var qe,$t,U,Ye,A,M=g(()=>{P();qe=()=>{let t=fileURLToPath(import.meta.url),e=G.dirname(t),o=10;for(let r=0;r<o;r++)try{if(We.existsSync(G.join(e,"package.json")))return e;let n=G.dirname(e);if(n===e)break;e=n;}catch{break}return process.cwd()},$t=qe(),U=process.env.AIP_HOME;U||(Ve.config({path:G.join($t,".env"),quiet:true}),U=process.env.AIP_HOME);if(!U){U=process.cwd();let t=U.split(G.sep);for(let e of [c.dirs.PROJECTS,c.dirs.SKILLS,c.dirs.AGENTS]){let o=t.indexOf(e);if(o!==-1){U=t.slice(0,o).join(G.sep);break}}}Ye={ROOT:$t,AIP_HOME:U},A=Ye;});var y,s,j=g(()=>{M();y={REPO:fileURLToPath(import.meta.url.replace(/\/(dist|src)\/.*/,"/")),join:(...t)=>G.join(...t),onRepo:(...t)=>y.join(y.REPO,...t),joinHome:(...t)=>y.join(A.AIP_HOME,...t),async ensureDir(t){await z.mkdir(t,{recursive:true});},async write(t,e){await y.ensureDir(G.dirname(t)),await z.writeFile(t,e,"utf8");},async append(t,e){await y.ensureDir(G.dirname(t)),await z.appendFile(t,e,"utf8");},async read(t){return z.readFile(t,"utf8")},async readRepo(...t){return y.read(y.onRepo(...t))},async readMany(...t){return (await Promise.all(t.map(async o=>{if(await y.fileExists(o)){let r=await y.read(o);return `# ${o}
2
+ import {z as z$1}from'zod';import {parser}from'zod-opts';import rt from'path';import {spawn,exec}from'child_process';import K from'fs/promises';import T from'lodash';import V from'moment';import {fileURLToPath}from'url';import {inspect}from'util';import xt from'yaml';var Le=Object.defineProperty;var f=(t,e)=>()=>(t&&(e=t(t=0)),e);var _e=(t,e)=>{for(var o in e)Le(t,o,{get:e[o],enumerable:true});};var S,B=f(()=>{S={name:"ai-projects",version:"1.6.2",type:"module",description:"Useful CLI for AI agents to create and manage projects, tasks, skills and agents",main:"dist/index.js",types:"dist/index.d.ts",bin:{aip:"dist/index.js"},files:["dist/**/*","README.md","LICENSE"],scripts:{build:"npm run build:map && npm run build:code","build:map":"tsx bin/map-commands.ts","build:code":"tsup --no-dts","build:full":"npm run build:map && tsup","build:check":"tsc --noEmit","build:watch":"npm run build:code -- --watch","build:clean":"rimraf dist/*",start:"dist/index.js",dev:'npm run build:watch -- --onSuccess "dist/index.js"',cli:"npm run build && npm start --",ts:"tsx",vitest:"VITE_CJS_IGNORE_WARNING=true vitest",test:"npm run test:types && npm run test:unit","test:unit":"npm run vitest -- run","test:types:test":"tsc -p tsconfig.test.json --incremental --tsBuildInfoFile test.tsbuildinfo","test:types:bin":"tsc -p bin/tsconfig.json --incremental --tsBuildInfoFile bin.tsbuildinfo","test:types":"npm run test:types:test && npm run test:types:bin","test:full":"npm run lint:full && npm run test",eslint:"eslint --cache",lint:"npm run eslint -- '{src,bin}/**/*.ts'","lint:fix":"npm run lint -- --fix","lint:full":"npm run build:check && npm run test:types:bin && npm run lint:fix","lint:full:silent":"npm run -s lint:full && echo LINT OK",prepare:'[ "$CI" != "true" ] && [ -d node_modules/husky ] && husky || true',prepack:"npm run test:full && npm run build:full","publish:dry":"npm pack --dry-run","version:patch":"npm version patch","version:minor":"npm version minor","version:major":"npm version major","agent:stop":"npm run -s lint:full:silent"},keywords:["ai","aip","project","task","kanban","cli","agent","automation"],author:"Ariel Flesler <aflesler@gmail.com>",license:"MIT",repository:{type:"git",url:"git+https://github.com/flesler/ai-projects.git"},homepage:"https://github.com/flesler/ai-projects#readme",bugs:{url:"https://github.com/flesler/ai-projects/issues"},engines:{node:">=20.0.0"},dependencies:{dotenv:"^17.3.1",lodash:"^4.17.21",moment:"^2.30.1",tslib:"^2.8.1",yaml:"^2.8.0",zod:"^3.25.76","zod-opts":"^1.0.0"},devDependencies:{"@eslint/js":"^10.0.1","@stylistic/eslint-plugin":"^5.7.0","@types/dotenv":"^8.2.3","@types/eslint":"^9.6.1","@types/lodash":"^4.17.23","@types/moment":"^2.13.0","@types/node":"^25.0.9","@types/source-map-support":"^0.5.10","@typescript-eslint/eslint-plugin":"^8.53.0","@typescript-eslint/parser":"^8.53.0",eslint:"^10.0.3","eslint-plugin-import-x":"^4.16.2","eslint-plugin-unused-imports":"^4.4.1","fast-glob":"^3.3.3",husky:"^9.1.7",rimraf:"^6.0.1","source-map-support":"^0.5.21",tsup:"^8.5.1",tsx:"^4.20.3","types-package-json":"^2.0.39",typescript:"^5.8.3",vitest:"^4.0.17"}};});function p(t){let{description:e,options:o=z$1.object({}),args:r,handler:n}=t,i=o.shape,c={};for(let[m,l]of Object.entries(i))c[m]={type:l};let d=parser().options(c);if(r){let m=r.shape,l=Object.entries(m).map(([g,b])=>({name:g,type:b}));l.length>0&&(d=d.args(l));}return e&&(d=d.description(e)),{description:e,options:o,args:r,parser:d,handler:n,cli:m=>n(d.parse(m))}}var k=f(()=>{});var a,P=f(()=>{a={dirs:{PROJECTS:"projects",SKILLS:"skills",AGENTS:"agents",TASKS:"tasks",INPUTS:"inputs",OUTPUTS:"outputs",HOOKS:"hooks",SCRIPTS:"scripts"},files:{MAIN:"main.md",LOG:"log.tsv",SKILL:"SKILL.md"},hookTypes:["pre-create","post-create","pre-complete","post-complete","pre-start","post-start","pre-update","post-update"],languages:["ts","js","sh","py"],targets:["project","task"]};});var J,Ge,D,H=f(()=>{P();J=process.env.AIP_HOME;if(!J){J=process.cwd();let t=J.split(rt.sep);for(let e of [a.dirs.PROJECTS,a.dirs.SKILLS,a.dirs.AGENTS]){let o=t.indexOf(e);if(o!==-1){J=t.slice(0,o).join(rt.sep);break}}}Ge={AIP_HOME:J},D=Ge;});var y,s,j=f(()=>{H();y={REPO:fileURLToPath(import.meta.url.replace(/\/(dist|src)\/.*/,"/")),join:(...t)=>rt.join(...t),onRepo:(...t)=>y.join(y.REPO,...t),joinHome:(...t)=>y.join(D.AIP_HOME,...t),async ensureDir(t){await K.mkdir(t,{recursive:true});},async write(t,e){await y.ensureDir(rt.dirname(t)),await K.writeFile(t,e,"utf8");},async append(t,e){await y.ensureDir(rt.dirname(t)),await K.appendFile(t,e,"utf8");},async read(t){return K.readFile(t,"utf8")},async readRepo(...t){return y.read(y.onRepo(...t))},async readMany(...t){return (await Promise.all(t.map(async o=>{let r=await y.fileExists(o)?await y.read(o):"ERROR: File not found";return `# ${o}
3
3
 
4
- ${r}`}return ""}))).filter(Boolean)},async logFiles(...t){let e=await y.readMany(...t);console.log(e.join(`
4
+ ${r}`}))).filter(Boolean)},async logFiles(...t){let e=await y.readMany(...t);console.log(e.join(`
5
5
 
6
6
  ---
7
7
 
8
- `));},dumpCommandMapLines(t,e){let o=e?w.pick(t,e):t,r=[];for(let[n,i]of y.entriesOf(o))r.push(`${n} {${Object.keys(i).join("|")}}`);return r},async fileExists(t){try{return await z.access(t),!0}catch{return false}},async listDir(t){try{return await z.readdir(t)}catch{return []}},spawn:spawn,cd(t){process.chdir(t);},async exec(t,e){return new Promise(o=>{exec(t,{encoding:"utf8",...e},(r,n,i)=>{let a=r?.code;o({stdout:n??"",stderr:i??"",code:r?typeof a=="number"?a:1:0});});})},noop:()=>{},omitByDeep:(t,e)=>w.isArray(t)?t.map(o=>y.omitByDeep(o,e)):w.isPlainObject(t)?w.mapValues(w.omitBy(t,e),o=>y.omitByDeep(o,e)):t,omitNilsDeep:t=>y.omitByDeep(t,w.isNil),omitUndefinedsDeep:t=>y.omitByDeep(t,w.isUndefined),cloneDeep:t=>w.cloneDeep(t),int:t=>Number.parseInt(t,10),keysOf:t=>Object.keys(t),entriesOf:t=>Object.entries(t),isKeyOf:(t,e)=>!w.isNil(t)&&t in e,typeOf:t=>typeof t,never:{},undef:t=>t??void 0,toNull:t=>t??null,same:t=>t,notNil:t=>{if(w.isNil(t))throw new Error(`Received unexpected ${t} value`);return t},randomInt:(t,e)=>Math.floor(Math.random()*(e-t+1))+t,promise:()=>{let t,e=new Promise((o,r)=>{t={resolve:o,reject:r};});return w.extend(e,t)},isPromise:t=>w.isObject(t)&&"catch"in t,delay:t=>{let e=w.isObject(t)?y.toMS(t):t;return new Promise(o=>setTimeout(o,e))},promiseMap:(t,e)=>Promise.all(t.map(e)),promiseEach:(t,e)=>Promise.all(t.map(e)).then(()=>{}),memoize:t=>w.memoize(t,y.memoizeKey),toMS:t=>Z.duration(t).asMilliseconds(),toSecs:t=>Z.duration(t).asSeconds(),inspect:(t,e)=>inspect(t,{colors:false,showHidden:false,depth:null,compact:true,breakLength:1/0,...e}),stringify(t,e,o){let r=new WeakSet;return JSON.stringify(t,(n,i)=>{if(w.isObject(i)){if(r.has(i))return "[Circular]";r.add(i);}return w.isFunction(e)?e(n,i):i},o)},dump:t=>y.oneLine(y.stringify(t)),compactWhitespace:t=>t.replace(/\\n/g,`
8
+ `));},dumpCommandMapLines(t,e){let o=e?T.pick(t,e):t,r=[];for(let[n,i]of y.entriesOf(o))r.push(`${n} {${Object.keys(i).join("|")}}`);return r},async fileExists(t){try{return await K.access(t),!0}catch{return false}},async listDir(t){try{return await K.readdir(t)}catch{return []}},spawn:spawn,cd(t){process.chdir(t);},async exec(t,e){return new Promise(o=>{exec(t,{encoding:"utf8",...e},(r,n,i)=>{let c=r?.code;o({stdout:n??"",stderr:i??"",code:r?typeof c=="number"?c:1:0});});})},noop:()=>{},omitByDeep:(t,e)=>T.isArray(t)?t.map(o=>y.omitByDeep(o,e)):T.isPlainObject(t)?T.mapValues(T.omitBy(t,e),o=>y.omitByDeep(o,e)):t,omitNilsDeep:t=>y.omitByDeep(t,T.isNil),omitUndefinedsDeep:t=>y.omitByDeep(t,T.isUndefined),cloneDeep:t=>T.cloneDeep(t),int:t=>Number.parseInt(t,10),keysOf:t=>Object.keys(t),entriesOf:t=>Object.entries(t),isKeyOf:(t,e)=>!T.isNil(t)&&t in e,typeOf:t=>typeof t,never:{},undef:t=>t??void 0,toNull:t=>t??null,same:t=>t,notNil:t=>{if(T.isNil(t))throw new Error(`Received unexpected ${t} value`);return t},randomInt:(t,e)=>Math.floor(Math.random()*(e-t+1))+t,promise:()=>{let t,e=new Promise((o,r)=>{t={resolve:o,reject:r};});return T.extend(e,t)},isPromise:t=>T.isObject(t)&&"catch"in t,delay:t=>{let e=T.isObject(t)?y.toMS(t):t;return new Promise(o=>setTimeout(o,e))},promiseMap:(t,e)=>Promise.all(t.map(e)),promiseEach:(t,e)=>Promise.all(t.map(e)).then(()=>{}),memoize:t=>T.memoize(t,y.memoizeKey),toMS:t=>V.duration(t).asMilliseconds(),toSecs:t=>V.duration(t).asSeconds(),inspect:(t,e)=>inspect(t,{colors:false,showHidden:false,depth:null,compact:true,breakLength:1/0,...e}),stringify(t,e,o){let r=new WeakSet;return JSON.stringify(t,(n,i)=>{if(T.isObject(i)){if(r.has(i))return "[Circular]";r.add(i);}return T.isFunction(e)?e(n,i):i},o)},dump:t=>y.oneLine(y.stringify(t)),compactWhitespace:t=>t.replace(/\\n/g,`
9
9
  `).replace(/\r/g,"").replace(/[ \t]*\n[ \t]*/g,`
10
10
  `).replace(/\n{3,}/g,`
11
11
 
12
- `).replace(/ {2,}/g," ").trim(),oneLine:t=>t.replace(/\n/g,"\\n").replace(/\t/g,"\\t").replace(/ +/g," ").trim(),fuzzySearch:(t,e)=>w.includes(w.toLower(t||""),w.toLower(e||"")),elapsed:(t,e=Date.now())=>Z.duration(Z(e).diff(t||0)),iso:t=>Z.utc(t).toISOString(),isoDate:t=>y.iso(t).slice(0,10),memoizeKey:(...t)=>t.join(""),exit:(t=0)=>{process.exit(t);},set:(t,e,o)=>(t[e]=o,t),run:async t=>{try{await t(),process.exit(0);}catch(e){console.error(e),process.exit(1);}},isMain:()=>{let t=process.argv[1]||"";return t.includes("/index.")||t.endsWith("/bin/aip")},errorMessage:t=>t instanceof Error?t.message:String(t),slugify:t=>t.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")},s=y;});var et,B,ft,q,Et=g(()=>{j();et=t=>{let e=t.trim();if(!e.startsWith("---"))return null;let o=e.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);return o?{frontmatter:vt.parse(o[1]),content:o[2].trim()}:null},B=async(t,e,o="")=>{let n=`---
13
- ${vt.stringify(e).trim()}
12
+ `).replace(/ {2,}/g," ").trim(),oneLine:t=>t.replace(/\n/g,"\\n").replace(/\t/g,"\\t").replace(/ +/g," ").trim(),fuzzySearch:(t,e)=>T.includes(T.toLower(t||""),T.toLower(e||"")),elapsed:(t,e=Date.now())=>V.duration(V(e).diff(t||0)),iso:t=>V.utc(t).toISOString(),isoDate:t=>y.iso(t).slice(0,10),memoizeKey:(...t)=>t.join(""),exit:(t=0)=>{process.exit(t);},set:(t,e,o)=>(t[e]=o,t),run:async t=>{try{await t(),process.exit(0);}catch(e){console.error(e),process.exit(1);}},isMain:()=>{let t=process.argv[1]||"";return t.includes("/index.")||t.endsWith("/bin/aip")},errorMessage:t=>t instanceof Error?t.message:String(t),slugify:t=>t.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")},s=y;});var tt,G,ut,Z,$t=f(()=>{j();tt=t=>{let e=t.trim();if(!e.startsWith("---"))return null;let o=e.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);return o?{frontmatter:xt.parse(o[1]),content:o[2].trim()}:null},G=async(t,e,o="")=>{let n=`---
13
+ ${xt.stringify(e).trim()}
14
14
  ---
15
15
 
16
16
  ${o}`.trim();await s.write(t,n+`
17
- `);},ft=async(t,e)=>{let o=await s.read(t),r=et(o);if(!r)throw new Error(`No frontmatter found in ${t}`);let n={...r.frontmatter,...e};return await B(t,n,r.content),n},q=async t=>{let e=await s.read(t),o=et(e);if(!o)throw new Error(`No frontmatter found in ${t}`);return o.frontmatter};});var J,ot,At,Ot,oo,ro,u,x=g(()=>{P();M();Et();j();J=(a=>(a.BACKLOG="backlog",a.IN_PROGRESS="in-progress",a.ONGOING="ongoing",a.DONE="done",a.BLOCKED="blocked",a.TO_DO="to-do",a))(J||{}),ot=Object.values(J),At=["backlog","in-progress","ongoing"],Ot=[c.dirs.HOOKS,c.dirs.INPUTS,c.dirs.OUTPUTS,c.dirs.SCRIPTS],oo=[c.dirs.TASKS,...Ot],ro={getProjectDir(t){return s.joinHome(c.dirs.PROJECTS,t)},getTaskDir(t,e){return s.join(this.getProjectDir(t),c.dirs.TASKS,e)},async findTask(t,e){if(e)return {project:e,task:t};let o=await this.listProjects(),r=[];if(await s.promiseEach(o,async n=>{(await this.listTasks(n)).includes(t)&&r.push(n);}),r.length===0)throw new Error(`Task '${t}' not found. Use --project to specify the project.`);if(r.length>1)throw new Error(`Task '${t}' found in multiple projects: ${r.join(", ")}. Use --project to specify which one.`);return {project:r[0],task:t}},getAgentDir(t){return s.join(A.AIP_HOME,c.dirs.AGENTS,t)},async listProjects(){let t=s.join(A.AIP_HOME,c.dirs.PROJECTS),e=await s.listDir(t);return (await s.promiseMap(e,async r=>{let n=this.getProjectDir(r);return await s.fileExists(n)&&r!==c.dirs.AGENTS?r:null})).filter(r=>r!==null).sort()},async listTasks(t){let e=s.join(this.getProjectDir(t),c.dirs.TASKS);return await s.fileExists(e)?await s.listDir(e):[]},async listAgents(){let t=s.join(A.AIP_HOME,c.dirs.AGENTS);return await s.fileExists(t)?await s.listDir(t):[]},async createProject(t,e,o){let r=this.getProjectDir(t);return await s.ensureDir(r),await Promise.all(oo.map(n=>s.ensureDir(s.join(r,n)))),await B(s.join(r,c.files.MAIN),e,o),await s.write(s.join(r,c.files.LOG),""),r},async createTask(t,e,o,r){let n=this.getTaskDir(t,e);return await s.ensureDir(n),await Promise.all(Ot.map(i=>s.ensureDir(s.join(n,i)))),await B(s.join(n,c.files.MAIN),o,r),await s.write(s.join(n,c.files.LOG),""),n},async createAgent(t,e){let o=this.getAgentDir(t);return await s.ensureDir(o),await B(s.join(o,c.files.MAIN),e),o},async getProject(t){let e=s.join(this.getProjectDir(t),c.files.MAIN);return await s.fileExists(e)?await q(e):null},async getTask(t,e){let o=s.join(this.getTaskDir(t,e),c.files.MAIN);return await s.fileExists(o)?await q(o):null},async getAgent(t){let e=s.join(this.getAgentDir(t),c.files.MAIN);return await s.fileExists(e)?await q(e):null},async updateProject(t,e){let o=s.join(this.getProjectDir(t),c.files.MAIN);return await ft(o,e)},async updateBody(t,e){let o=await s.read(t),r=et(o);if(!r)throw new Error(`No frontmatter found in ${t}`);await B(t,r.frontmatter,e);},async updateTask(t,e,o){let r=s.join(this.getTaskDir(t,e),c.files.MAIN);if((await q(r))?.status==="ongoing")throw new Error("Cannot update ongoing task. Should be done by user or update manually");return await ft(r,o)},async ingestTask(t,e){let o=this.getTaskDir(t,e),r=this.getProjectDir(t),n=[s.join(r,c.files.MAIN),s.join(o,c.files.MAIN),s.join(o,c.files.LOG)];await s.logFiles(...n);},async ingestProject(t){let e=this.getProjectDir(t),o=await this.listTasks(t),r=[s.join(e,c.files.MAIN),s.join(e,c.files.LOG),...o.map(n=>s.join(this.getTaskDir(t,n),c.files.MAIN))];await s.logFiles(...r);},async ingestFiles(t){await s.logFiles(...t);}},u=ro;});var Dt,Ct=g(()=>{k();j();x();Dt=p({options:z$1.object({description:z$1.string().describe("Agent description"),status:z$1.string().default("active").describe("Initial status")}),args:z$1.object({name:z$1.string().describe("Agent name")}),handler:async({name:t,description:e,status:o})=>{let r=s.slugify(t);await u.createAgent(r,{name:t,description:e,status:o,created:new Date().toISOString()}),console.log(`Agent created: ${r}`),console.log(` Path: ${u.getAgentDir(r)}`);}});});var Nt,Rt=g(()=>{k();Nt=p({options:z$1.object({}),handler:async()=>{let t=process.env.CURRENT_AGENT;t||(console.error("CURRENT_AGENT not set"),process.exit(1)),console.log(t);}});});var It,Lt=g(()=>{k();x();It=p({options:z$1.object({}),handler:async()=>{let t=await u.listAgents(),e=[];for(let o of t){let r=await u.getAgent(o);r&&e.push({slug:o,name:r.name||o,status:r.status,description:r.description});}if(e.length===0){console.log("No agents found");return}console.log("Agents:"),console.log("---");for(let o of e)console.log(`${o.slug.padEnd(20)} ${o.name?.padEnd(30)||""} ${o.status||""} ${o.description||""}`);}});});var Ft,Ut=g(()=>{P();k();M();j();Ft=p({description:"Output agent directory path (for cd)",options:z$1.object({}),args:z$1.object({name:z$1.string().describe("Agent name (directory name)")}),handler:async({name:t})=>{let e=s.join(A.AIP_HOME,c.dirs.AGENTS,t),o=s.join(e,c.files.MAIN);if(!await s.fileExists(o))throw new Error(`Agent not found: ${t}
18
- Expected at: ${o}`);console.log(e);}});});var _t,Ht=g(()=>{P();k();M();j();_t=p({description:"Start an agent: read SOUL.md and AGENTS.md content",options:z$1.object({}),args:z$1.object({name:z$1.string().describe("Agent name (directory name)")}),handler:async({name:t})=>{let e=s.join(A.AIP_HOME,c.dirs.AGENTS,t),o=s.join(e,c.files.MAIN),r=s.join(e,"SOUL.md");if(!await s.fileExists(o))throw new Error(`Agent not found: ${t}
19
- Expected at: ${o}`);let i=[r,o];await s.logFiles(...i);}});});var Kt,Gt,ao,Mt,zt=g(()=>{k();Kt=t=>{let e=t.shape,o=[];for(let[r,n]of Object.entries(e)){let i=n._def,a="unknown",l,m;i.typeName==="ZodString"?a="string":i.typeName==="ZodNumber"?a="number":i.typeName==="ZodBoolean"?a="boolean":i.typeName==="ZodEnum"?a=`enum: ${i.values.join(" | ")}`:i.typeName==="ZodOptional"?a=Gt(i.innerType):i.typeName==="ZodDefault"&&(a=Gt(i.innerType),m=i.defaultValue()),i.description&&(l=i.description);let d=i.typeName!=="ZodOptional"&&i.typeName!=="ZodDefault";o.push({name:r,type:a,required:d,description:l,defaultValue:m});}return o},Gt=t=>{let e=t._def;return e.typeName==="ZodString"?"string":e.typeName==="ZodNumber"?"number":e.typeName==="ZodBoolean"?"boolean":e.typeName==="ZodEnum"?`enum: ${e.values.join(" | ")}`:"unknown"},ao=(t,e,o)=>{let r=Kt(o.options),n=o.args?Kt(o.args):[],i=o.description,a=`\`${t} ${e}\``;if(i&&(a+=`: ${i}`),a+=`
20
- `,r.length>0||n.length>0){let m=[];for(let d of n){let f=d.required?`<${d.name}>`:`[${d.name}]`,b=d.description||"";d.defaultValue!==void 0&&(b+=b?` (default: ${d.defaultValue})`:`(default: ${d.defaultValue})`),m.push(`\xB7 ${f}${b?": "+b:""}`);}for(let d of r){let f=d.description||"";d.defaultValue!==void 0&&(f+=f?` (default: ${d.defaultValue})`:`(default: ${d.defaultValue})`),m.push(`\xB7 --${d.name}${f?": "+f:""}`);}a+=m.join(`
17
+ `);},ut=async(t,e)=>{let o=await s.read(t),r=tt(o);if(!r)throw new Error(`No frontmatter found in ${t}`);let n={...r.frontmatter,...e};return await G(t,n,r.content),n},Z=async t=>{let e=await s.read(t),o=tt(e);if(!o)throw new Error(`No frontmatter found in ${t}`);return o.frontmatter};});var M,et,vt,Et,Ve,Ze,u,x=f(()=>{P();H();$t();j();M=(c=>(c.BACKLOG="backlog",c.IN_PROGRESS="in-progress",c.ONGOING="ongoing",c.DONE="done",c.BLOCKED="blocked",c.TO_DO="to-do",c))(M||{}),et=Object.values(M),vt=["backlog","in-progress","ongoing"],Et=[a.dirs.HOOKS,a.dirs.INPUTS,a.dirs.OUTPUTS,a.dirs.SCRIPTS],Ve=[a.dirs.TASKS,...Et],Ze={getProjectDir(t){return s.joinHome(a.dirs.PROJECTS,t)},getTaskDir(t,e){return s.join(this.getProjectDir(t),a.dirs.TASKS,e)},async findTask(t,e){if(e)return {project:e,task:t};let o=await this.listProjects(),r=[];if(await s.promiseEach(o,async n=>{(await this.listTasks(n)).includes(t)&&r.push(n);}),r.length===0)throw new Error(`Task '${t}' not found. Use --project to specify the project.`);if(r.length>1)throw new Error(`Task '${t}' found in multiple projects: ${r.join(", ")}. Use --project to specify which one.`);return {project:r[0],task:t}},getAgentDir(t){return s.join(D.AIP_HOME,a.dirs.AGENTS,t)},async listProjects(){let t=s.join(D.AIP_HOME,a.dirs.PROJECTS),e=await s.listDir(t);return (await s.promiseMap(e,async r=>{let n=this.getProjectDir(r);return await s.fileExists(n)&&r!==a.dirs.AGENTS?r:null})).filter(r=>r!==null).sort()},async listTasks(t){let e=s.join(this.getProjectDir(t),a.dirs.TASKS);return await s.fileExists(e)?await s.listDir(e):[]},async listAgents(){let t=s.join(D.AIP_HOME,a.dirs.AGENTS);return await s.fileExists(t)?await s.listDir(t):[]},async createProject(t,e,o){let r=this.getProjectDir(t);return await s.ensureDir(r),await Promise.all(Ve.map(n=>s.ensureDir(s.join(r,n)))),await G(s.join(r,a.files.MAIN),e,o),await s.write(s.join(r,a.files.LOG),""),r},async createTask(t,e,o,r){let n=this.getTaskDir(t,e);return await s.ensureDir(n),await Promise.all(Et.map(i=>s.ensureDir(s.join(n,i)))),await G(s.join(n,a.files.MAIN),o,r),await s.write(s.join(n,a.files.LOG),""),n},async createAgent(t,e){let o=this.getAgentDir(t);return await s.ensureDir(o),await G(s.join(o,a.files.MAIN),e),o},async getProject(t){let e=s.join(this.getProjectDir(t),a.files.MAIN);return await s.fileExists(e)?await Z(e):null},async getTask(t,e){let o=s.join(this.getTaskDir(t,e),a.files.MAIN);return await s.fileExists(o)?await Z(o):null},async getAgent(t){let e=s.join(this.getAgentDir(t),a.files.MAIN);return await s.fileExists(e)?await Z(e):null},async updateProject(t,e){let o=s.join(this.getProjectDir(t),a.files.MAIN);return await ut(o,e)},async updateBody(t,e){let o=await s.read(t),r=tt(o);if(!r)throw new Error(`No frontmatter found in ${t}`);await G(t,r.frontmatter,e);},async updateTask(t,e,o){let r=s.join(this.getTaskDir(t,e),a.files.MAIN);if((await Z(r))?.status==="ongoing")throw new Error("Cannot update ongoing task. Should be done by user or update manually");return await ut(r,o)},async ingestTask(t,e){let o=this.getTaskDir(t,e),r=this.getProjectDir(t),n=[s.join(r,a.files.MAIN),s.join(o,a.files.MAIN),s.join(o,a.files.LOG)];await s.logFiles(...n);},async ingestProject(t){let e=this.getProjectDir(t),o=await this.listTasks(t),r=[s.join(e,a.files.MAIN),s.join(e,a.files.LOG),...o.map(n=>s.join(this.getTaskDir(t,n),a.files.MAIN))];await s.logFiles(...r);},async ingestFiles(t){await s.logFiles(...t);}},u=Ze;});var At,Dt=f(()=>{k();j();x();At=p({options:z$1.object({description:z$1.string().describe("Agent description"),status:z$1.string().default("active").describe("Initial status")}),args:z$1.object({name:z$1.string().describe("Agent name")}),handler:async({name:t,description:e,status:o})=>{let r=s.slugify(t);await u.createAgent(r,{name:t,description:e,status:o,created:new Date().toISOString()}),console.log(`Agent created: ${r}`),console.log(` Path: ${u.getAgentDir(r)}`);}});});var Ot,Ct=f(()=>{k();Ot=p({options:z$1.object({}),handler:async()=>{let t=process.env.CURRENT_AGENT;t||(console.error("CURRENT_AGENT not set"),process.exit(1)),console.log(t);}});});var Nt,Rt=f(()=>{k();x();Nt=p({options:z$1.object({}),handler:async()=>{let t=await u.listAgents(),e=[];for(let o of t){let r=await u.getAgent(o);r&&e.push({slug:o,name:r.name||o,status:r.status,description:r.description});}if(e.length===0){console.log("No agents found");return}console.log("Agents:"),console.log("---");for(let o of e)console.log(`${o.slug.padEnd(20)} ${o.name?.padEnd(30)||""} ${o.status||""} ${o.description||""}`);}});});var It,Ft=f(()=>{P();k();H();j();It=p({description:"Output agent directory path (for cd)",options:z$1.object({}),args:z$1.object({name:z$1.string().describe("Agent name (directory name)")}),handler:async({name:t})=>{let e=s.join(D.AIP_HOME,a.dirs.AGENTS,t),o=s.join(e,a.files.MAIN);if(!await s.fileExists(o))throw new Error(`Agent not found: ${t}
18
+ Expected at: ${o}`);console.log(e);}});});var Lt,_t=f(()=>{P();k();H();j();Lt=p({description:"Start an agent: read SOUL.md and AGENTS.md content",options:z$1.object({}),args:z$1.object({name:z$1.string().describe("Agent name (directory name)")}),handler:async({name:t})=>{let e=s.join(D.AIP_HOME,a.dirs.AGENTS,t),o=s.join(e,a.files.MAIN),r=s.join(e,"SOUL.md");if(!await s.fileExists(o))throw new Error(`Agent not found: ${t}
19
+ Expected at: ${o}`);let i=[r,o];await s.logFiles(...i);}});});var Ut,Ht,Qe,Kt,Gt=f(()=>{k();Ut=t=>{let e=t.shape,o=[];for(let[r,n]of Object.entries(e)){let i=n._def,c="unknown",d,m;i.typeName==="ZodString"?c="string":i.typeName==="ZodNumber"?c="number":i.typeName==="ZodBoolean"?c="boolean":i.typeName==="ZodEnum"?c=`enum: ${i.values.join(" | ")}`:i.typeName==="ZodOptional"?c=Ht(i.innerType):i.typeName==="ZodDefault"&&(c=Ht(i.innerType),m=i.defaultValue()),i.description&&(d=i.description);let l=i.typeName!=="ZodOptional"&&i.typeName!=="ZodDefault";o.push({name:r,type:c,required:l,description:d,defaultValue:m});}return o},Ht=t=>{let e=t._def;return e.typeName==="ZodString"?"string":e.typeName==="ZodNumber"?"number":e.typeName==="ZodBoolean"?"boolean":e.typeName==="ZodEnum"?`enum: ${e.values.join(" | ")}`:"unknown"},Qe=(t,e,o)=>{let r=Ut(o.options),n=o.args?Ut(o.args):[],i=o.description,c=`\`${t} ${e}\``;if(i&&(c+=`: ${i}`),c+=`
20
+ `,r.length>0||n.length>0){let m=[];for(let l of n){let g=l.required?`<${l.name}>`:`[${l.name}]`,b=l.description||"";l.defaultValue!==void 0&&(b+=b?` (default: ${l.defaultValue})`:`(default: ${l.defaultValue})`),m.push(`\xB7 ${g}${b?": "+b:""}`);}for(let l of r){let g=l.description||"";l.defaultValue!==void 0&&(g+=g?` (default: ${l.defaultValue})`:`(default: ${l.defaultValue})`),m.push(`\xB7 --${l.name}${g?": "+g:""}`);}c+=m.join(`
21
21
  `)+`
22
- `;}return a+=`
23
- `,a},Mt=p({description:"Print generated CLI reference from command schemas",options:z$1.object({}),handler:async()=>{let{default:t}=await Promise.resolve().then(()=>(rt(),yt)),e="Prepend `aip` to each command\n\n",o=Object.keys(t).sort();for(let r of o){let n=t[r],i=Object.keys(n).sort();for(let a of i){let l=n[a];e+=ao(r,a,l);}}console.log(e);}});});var po,Bt,Jt=g(()=>{k();po=`# AIP Hooks
22
+ `;}return c+=`
23
+ `,c},Kt=p({description:"Print generated CLI reference from command schemas",options:z$1.object({}),handler:async()=>{let{default:t}=await Promise.resolve().then(()=>(ot(),kt)),e="Prepend `aip` to each command\n\n",o=Object.keys(t).sort();for(let r of o){let n=t[r],i=Object.keys(n).sort();for(let c of i){let d=n[c];e+=Qe(r,c,d);}}console.log(e);}});});var to,Mt,zt=f(()=>{k();to=`# AIP Hooks
24
24
 
25
25
  Automated scripts that run before/after project/task actions.
26
26
 
@@ -200,30 +200,30 @@ DEBUG=1 aip task update --status done
200
200
  ---
201
201
 
202
202
  *Hooks automate workflow enforcement. Pre-hooks guard quality, post-hooks handle cleanup.*
203
- `,Bt=p({description:"Hook types, env vars, and patterns",options:z$1.object({}),handler:async()=>{console.log(po);}});});var O,Vt,mo,Wt,Zt=g(()=>{P();k();W();O=Object.keys(S.bin)[0],{LOG:Vt}=c.files,mo=`# Quick Start
203
+ `,Mt=p({description:"Hook types, env vars, and patterns",options:z$1.object({}),handler:async()=>{console.log(to);}});});var $,Bt,oo,Jt,Vt=f(()=>{B();P();k();$=Object.keys(S.bin)[0],{LOG:Bt}=a.files,oo=`# Quick Start
204
204
 
205
205
  ## New Task/Project
206
206
 
207
207
  \`\`\`bash
208
208
  # 1. Create project (if needed)
209
- ${O} project create "my-project" --description "What I'm building" --body $'# Goals
209
+ ${$} project create "my-project" --description "What I'm building" --body $'# Goals
210
210
  - Build X
211
211
  - Solve Y'
212
212
 
213
213
  # 2. Create task (heredoc works too)
214
- ${O} task create my-project "first-task" --description "Start here" --body "$(cat <<< '# Task Details
214
+ ${$} task create my-project "first-task" --description "Start here" --body "$(cat <<< '# Task Details
215
215
  - Step 1
216
216
  - Step 2')"
217
217
 
218
218
  # 3. Navigate to task
219
- cd $(${O} task path first-task)
219
+ cd $(${$} task path first-task)
220
220
 
221
221
  # 4. Start working (implicit from PWD)
222
- ${O} task start
222
+ ${$} task start
223
223
  # \u2192 sets status to in-progress, reads all context to stdout
224
224
 
225
225
  # 5. Work session
226
- # Log progress: ${O} log append "API integration complete"
226
+ # Log progress: ${$} log append "API integration complete"
227
227
  # Save: outputs/ to deliver, inputs/ for data
228
228
  \`\`\`
229
229
 
@@ -231,47 +231,56 @@ ${O} task start
231
231
 
232
232
  \`\`\`bash
233
233
  # Find your tasks (searches all projects)
234
- ${O} task list
234
+ ${$} task list
235
235
 
236
236
  # Navigate to task
237
- cd $(${O} task path task-slug)
237
+ cd $(${$} task path task-slug)
238
238
 
239
239
  # All commands work implicitly from PWD:
240
- ${O} task start # Start working (sets status to in-progress, reads all context to stdout)
240
+ ${$} task start # Start working (sets status to in-progress, reads all context to stdout)
241
241
  \`\`\`
242
242
 
243
243
  ## Completing
244
244
 
245
245
  \`\`\`bash
246
246
  # Mark done (implicit from PWD)
247
- ${O} task update --status done
248
- ${O} log append "if you want to log something extra"
247
+ ${$} task update --status done
248
+ ${$} log append "if you want to log something extra"
249
249
  \`\`\`
250
250
 
251
251
  ## Check current task
252
252
 
253
253
  \`\`\`bash
254
- ${O} task current
254
+ ${$} task current
255
255
  \`\`\`
256
256
 
257
- **Note:** All task commands accept an optional task slug, but use PWD if not provided. Navigate with \`cd\` first for smoother workflow.
257
+ **Note:** All task commands (except create) accept an optional task slug, but use PWD if not provided. Navigate with \`cd\` first for smoother workflow.
258
258
 
259
259
  ## Structure
260
260
 
261
- \`\`\`
262
261
  $AIP_HOME/projects/slug/
263
262
  \u251C\u2500\u2500 main.md # Definition + body
264
- \u251C\u2500\u2500 ${Vt} # Log (auto-appended, has key task updates too)
263
+ \u251C\u2500\u2500 ${Bt} # Log (auto-appended, has key task updates too)
265
264
  \u2514\u2500\u2500 tasks/task/
266
265
  \u251C\u2500\u2500 main.md # Task definition + body
267
- \u2514\u2500\u2500 ${Vt} # Updates
268
- \`\`\`
266
+ \u2514\u2500\u2500 ${Bt} # Updates
269
267
 
270
268
  **Log format:** TSV with columns: date, time, entityType, slug, action, text
271
269
  **Example:** \`2026-03-30<TAB>14:30:00<TAB>task<TAB>api-integration<TAB>log<TAB>API integration complete\`
272
270
 
273
- Run \`${O} help usage\` for all commands.
274
- `,Wt=p({description:"Quick start guide for new users",options:z$1.object({}),handler:async()=>{console.log(mo);}});});var uo,go,fo,ko,ho,yo,jo,Yt,jt,R,Tt,Qt,Xt=g(()=>{W();P();k();x();uo=Object.values(J).join("|"),{PROJECTS:go,TASKS:fo,HOOKS:ko,INPUTS:ho,OUTPUTS:yo,SCRIPTS:jo}=c.dirs,{MAIN:Yt,LOG:jt}=c.files,R=Object.keys(S.bin)[0],Tt=`# AIP - Project Management Skill
271
+ ## Help
272
+
273
+ \`\`\`bash
274
+ # Get all nouns and verbs
275
+ ${$} --help
276
+
277
+ # All verbs for a noun
278
+ ${$} <noun> --help
279
+
280
+ # All parameters and --options for a command
281
+ ${$} <noun> <verb> --help
282
+ \`\`\`
283
+ `,Jt=p({description:"Quick start guide for new users",options:z$1.object({}),handler:async()=>{console.log(oo);}});});var ro,so,no,io,ao,co,po,Wt,ht,q,yt,qt,Yt=f(()=>{B();P();k();x();ro=Object.values(M).join("|"),{PROJECTS:so,TASKS:no,HOOKS:io,INPUTS:ao,OUTPUTS:co,SCRIPTS:po}=a.dirs,{MAIN:Wt,LOG:ht}=a.files,q=Object.keys(S.bin)[0],yt=`# AIP - Project Management Skill
275
284
 
276
285
  Automated project and task creation with proper structure, front-matter, and file organization.
277
286
 
@@ -281,25 +290,25 @@ Streamline creation of new projects and tasks with the correct directory structu
281
290
 
282
291
  ## Quick Start
283
292
 
284
- - New user? Run: \`${R} help quickstart\`
285
- - All commands? Run: \`${R} help usage\`
286
- - Just for one noun? Run: \`${R} help usage <noun>\` (e.g., \`${R} help usage task\`)
287
- - Need EVERYTHING (big)? Run: \`${R} help api\` - Shows all commands with full option details
293
+ - New user? Run: \`${q} help quickstart\`
294
+ - All commands? Run: \`${q} help usage\`
295
+ - Just for one noun? Run: \`${q} help usage <noun>\` (e.g., \`${q} help usage task\`)
296
+ - Need EVERYTHING (big)? Run: \`${q} help api\` - Shows all commands with full option details
288
297
 
289
298
  ## File Structure Overview
290
299
 
291
300
  \`\`\`
292
- $AIP_HOME/${go}/{project-slug}/
293
- \u251C\u2500\u2500 ${Yt} # Goals + body (YAML frontmatter + markdown content)
294
- \u251C\u2500\u2500 ${jt} # Chronological log (TSV: date, time, entityType, slug, action, text)
295
- \u251C\u2500\u2500 ${ko}/ # pre|post-{create,start,update,complete}.*
296
- \u251C\u2500\u2500 ${yo}/ # Deliverables
297
- \u251C\u2500\u2500 ${ho}/ # External data
298
- \u251C\u2500\u2500 ${jo}/ # Automation
299
- \u2514\u2500\u2500 ${fo}/
301
+ $AIP_HOME/${so}/{project-slug}/
302
+ \u251C\u2500\u2500 ${Wt} # Goals + body (YAML frontmatter + markdown content)
303
+ \u251C\u2500\u2500 ${ht} # Chronological log (TSV: date, time, entityType, slug, action, text)
304
+ \u251C\u2500\u2500 ${io}/ # pre|post-{create,start,update,complete}.*
305
+ \u251C\u2500\u2500 ${co}/ # Deliverables
306
+ \u251C\u2500\u2500 ${ao}/ # External data
307
+ \u251C\u2500\u2500 ${po}/ # Automation
308
+ \u2514\u2500\u2500 ${no}/
300
309
  \u2514\u2500\u2500 {task-slug}/
301
- \u251C\u2500\u2500 ${Yt} # Task definition + body
302
- \u251C\u2500\u2500 ${jt} # Activity log
310
+ \u251C\u2500\u2500 ${Wt} # Task definition + body
311
+ \u251C\u2500\u2500 ${ht} # Activity log
303
312
  \u2514\u2500\u2500 ... (same structure)
304
313
  \`\`\`
305
314
 
@@ -310,27 +319,14 @@ $AIP_HOME/${go}/{project-slug}/
310
319
  name: Clear Title
311
320
  description: One-line summary
312
321
  assignee: agent-name
313
- status: ${uo}
322
+ status: ${ro}
314
323
  created: YYYY-MM-DD
315
324
  ---
316
325
  \`\`\`
317
326
 
318
327
  ## Body/Content
319
328
 
320
- Markdown after frontmatter. Add via CLI:
321
-
322
- \`\`\`bash
323
- # Using heredoc (multi-line)
324
- ${R} project create "my-project" --description "..." --body "$(cat <<'EOF'
325
- # Goals
326
- - Build X
327
- - Solve Y
328
- EOF
329
- )"
330
-
331
- # Update/replace body
332
- ${R} project update --body "$(cat new-content.md)"
333
- \`\`\`
329
+ Markdown content after frontmatter. See \`aip help quickstart\` for examples of adding body content via CLI.
334
330
 
335
331
  ## Best Practices
336
332
 
@@ -339,16 +335,11 @@ ${R} project update --body "$(cat new-content.md)"
339
335
 
340
336
  ## For Agents
341
337
 
342
- When working on a task:
343
- 1. Read \`main.md\` first (goals/context)
344
- 2. Review \`${jt}\` (activity history)
345
- 3. Work and save outputs to \`outputs/\`
346
- 4. Log progress: \`${R} log append "message"\`
347
- 5. On completion: set status=\`done\`, log summary
348
- `,Qt=p({description:"Project management skill for creating and managing projects/tasks",options:z$1.object({mode:z$1.enum(["md","claude","hermes"]).default("md").describe("Output format: md (no header), claude (name+description), hermes (full frontmatter)")}),handler:async t=>{let e=Object.keys(S.bin)[0];if(t.mode==="md"){console.log(Tt);return}if(t.mode==="claude"){console.log(`---
338
+ Typical workflow: read \`main.md\` for context, check \`${ht}\` for history, work, and log progress with \`aip log append\`.
339
+ `,qt=p({description:"Project management skill for creating and managing projects/tasks",options:z$1.object({mode:z$1.enum(["md","claude","hermes"]).default("md").describe("Output format: md (no header), claude (name+description), hermes (full frontmatter)")}),handler:async t=>{let e=Object.keys(S.bin)[0];if(t.mode==="md"){console.log(yt);return}if(t.mode==="claude"){console.log(`---
349
340
  name: ${e}
350
341
  description: ${S.description}
351
- ---`),console.log(),console.log(Tt);return}if(t.mode==="hermes"){console.log(`---
342
+ ---`),console.log(),console.log(yt);return}if(t.mode==="hermes"){console.log(`---
352
343
  name: ${e}
353
344
  description: ${S.description}
354
345
  version: ${S.version}
@@ -357,14 +348,14 @@ license: ${S.license}
357
348
  metadata:
358
349
  hermes:
359
350
  tags: [${S.keywords.join(", ")}]
360
- ---`),console.log(),console.log(Tt);return}}});});var te,ee=g(()=>{W();k();j();te=p({description:"Print compact CLI usage (all nouns, or one noun if name is given)",options:z$1.object({}),args:z$1.object({name:z$1.string().optional().describe("Noun (e.g. task) to list verbs for")}),handler:async({name:t})=>{let{default:e}=await Promise.resolve().then(()=>(rt(),yt)),o=`${S.name} ${S.version} -`,r=s.dumpCommandMapLines(e,t);if(!t)console.log(o,"Usage: aip <noun> <verb> [options]"),console.log(r.map(n=>`-> ${n}`).join(`
361
- `)),console.log(),console.log("Run `aip help quickstart` for a quick start guide"),console.log("Run `aip help skill` for a broader overview");else {let n=r[0]??`${t} {?}`;console.log(o,`Usage: aip ${n} [options]`);}}});});var bt,To,h,D=g(()=>{P();j();bt=s.joinHome(c.dirs.PROJECTS),To={getProjectFromPwd(t=process.cwd()){let e=G.relative(bt,t);if(!e||e.startsWith(".."))return null;let o=e.split(G.sep).filter(Boolean);return o.length===0?null:o[0]},getTaskFromPwd(t=process.cwd()){let e=G.relative(bt,t);if(!e||e.startsWith(".."))return null;let o=e.split(G.sep).filter(Boolean);return o.length<3||o[1]!==c.dirs.TASKS?null:o[2]},getCurrentContext(t=process.cwd()){return {project:this.getProjectFromPwd(t),task:this.getTaskFromPwd(t)}},requireProject(t=process.cwd()){let e=this.getProjectFromPwd(t);if(!e)throw new Error(`Not in a project directory. PWD: ${t}, projects: ${bt}`);return e},requireTask(t=process.cwd()){let e=this.getCurrentContext(t);if(!e.project||!e.task)throw new Error(`Not in a task directory. PWD: ${t}`);return {project:e.project,task:e.task}},exportContext(t=process.cwd()){let e=this.getCurrentContext(t),o=[];return e.project&&o.push(`export CURRENT_PROJECT="${e.project}"`),e.task&&o.push(`export CURRENT_TASK="${e.task}"`),process.env.CURRENT_AGENT&&o.push(`export CURRENT_AGENT="${process.env.CURRENT_AGENT}"`),o.join(`
362
- `)},getTargetDir(t,e=process.cwd()){let o=this.getCurrentContext(e);if(t==="project"){let r=this.getProjectFromPwd(e);if(!r)throw new Error("Not in a project directory. Use --project flag or cd into a project.");let n=s.joinHome(c.dirs.PROJECTS,r);return {targetDir:n,projectDir:n,entityType:"project"}}if(t==="task"){if(!o.project||!o.task)throw new Error("Not in a task directory. Use --project and --task flags or cd into a task.");let r=s.joinHome(c.dirs.PROJECTS,o.project);return {targetDir:s.join(r,c.dirs.TASKS,o.task),projectDir:r,entityType:"task"}}if(o.task&&o.project){let r=s.joinHome(c.dirs.PROJECTS,o.project);return {targetDir:s.join(r,c.dirs.TASKS,o.task),projectDir:r,entityType:"task"}}if(o.project){let r=s.joinHome(c.dirs.PROJECTS,o.project);return {targetDir:r,projectDir:r,entityType:"project"}}throw new Error("Not in a project or task directory. Specify --target flag.")}},h=To;});var oe,re=g(()=>{k();j();D();P();oe=p({options:z$1.object({lang:z$1.enum(c.languages).default("ts").describe("Language"),target:z$1.enum(c.targets).default("project").describe("Target level")}),args:z$1.object({type:z$1.enum(c.hookTypes).describe("Hook type (e.g., pre-create, post-complete)")}),handler:async({type:t,lang:e,target:o})=>{let r=e,n=`.${r}`,{targetDir:i,entityType:a}=h.getTargetDir(o),l=s.join(i,c.dirs.HOOKS);await s.ensureDir(l);let m=s.join(l,`${t}${n}`);if(await s.fileExists(m))throw new Error(`Hook already exists: ${m}`);let f;if(r==="ts")f=`#!/usr/bin/env tsx
363
- /** ${t} hook for ${a} */
351
+ ---`),console.log(),console.log(yt);return}}});});var Qt,Xt=f(()=>{B();k();j();Qt=p({description:"Print compact CLI usage (all nouns, or one noun if name is given)",options:z$1.object({}),args:z$1.object({name:z$1.string().optional().describe("Noun (e.g. task) to list verbs for")}),handler:async({name:t})=>{let{default:e}=await Promise.resolve().then(()=>(ot(),kt)),o=`${S.name} ${S.version} -`,r=s.dumpCommandMapLines(e,t);if(!t)console.log(o,"Usage: aip <noun> <verb> [options]"),console.log(r.map(n=>`-> ${n}`).join(`
352
+ `)),console.log(),console.log("Run `aip help quickstart` for a quick start guide"),console.log("Run `aip help skill` for a broader overview");else {let n=r[0]??`${t} {?}`;console.log(o,`Usage: aip ${n} [options]`);}}});});var Tt,lo,h,O=f(()=>{P();j();Tt=s.joinHome(a.dirs.PROJECTS),lo={getProjectFromPwd(t=process.cwd()){let e=rt.relative(Tt,t);if(!e||e.startsWith(".."))return null;let o=e.split(rt.sep).filter(Boolean);return o.length===0?null:o[0]},getTaskFromPwd(t=process.cwd()){let e=rt.relative(Tt,t);if(!e||e.startsWith(".."))return null;let o=e.split(rt.sep).filter(Boolean);return o.length<3||o[1]!==a.dirs.TASKS?null:o[2]},getCurrentContext(t=process.cwd()){return {project:this.getProjectFromPwd(t),task:this.getTaskFromPwd(t)}},requireProject(t=process.cwd()){let e=this.getProjectFromPwd(t);if(!e)throw new Error(`Not in a project directory. PWD: ${t}, projects: ${Tt}`);return e},requireTask(t=process.cwd()){let e=this.getCurrentContext(t);if(!e.project||!e.task)throw new Error(`Not in a task directory. PWD: ${t}`);return {project:e.project,task:e.task}},exportContext(t=process.cwd()){let e=this.getCurrentContext(t),o=[];return e.project&&o.push(`export CURRENT_PROJECT="${e.project}"`),e.task&&o.push(`export CURRENT_TASK="${e.task}"`),process.env.CURRENT_AGENT&&o.push(`export CURRENT_AGENT="${process.env.CURRENT_AGENT}"`),o.join(`
353
+ `)},getTargetDir(t,e=process.cwd()){let o=this.getCurrentContext(e);if(t==="project"){let r=this.getProjectFromPwd(e);if(!r)throw new Error("Not in a project directory. Use --project flag or cd into a project.");let n=s.joinHome(a.dirs.PROJECTS,r);return {targetDir:n,projectDir:n,entityType:"project"}}if(t==="task"){if(!o.project||!o.task)throw new Error("Not in a task directory. Use --project and --task flags or cd into a task.");let r=s.joinHome(a.dirs.PROJECTS,o.project);return {targetDir:s.join(r,a.dirs.TASKS,o.task),projectDir:r,entityType:"task"}}if(o.task&&o.project){let r=s.joinHome(a.dirs.PROJECTS,o.project);return {targetDir:s.join(r,a.dirs.TASKS,o.task),projectDir:r,entityType:"task"}}if(o.project){let r=s.joinHome(a.dirs.PROJECTS,o.project);return {targetDir:r,projectDir:r,entityType:"project"}}throw new Error("Not in a project or task directory. Specify --target flag.")}},h=lo;});var te,ee=f(()=>{k();j();O();P();te=p({options:z$1.object({lang:z$1.enum(a.languages).default("ts").describe("Language"),target:z$1.enum(a.targets).default("project").describe("Target level")}),args:z$1.object({type:z$1.enum(a.hookTypes).describe("Hook type (e.g., pre-create, post-complete)")}),handler:async({type:t,lang:e,target:o})=>{let r=e,n=`.${r}`,{targetDir:i,entityType:c}=h.getTargetDir(o),d=s.join(i,a.dirs.HOOKS);await s.ensureDir(d);let m=s.join(d,`${t}${n}`);if(await s.fileExists(m))throw new Error(`Hook already exists: ${m}`);let g;if(r==="ts")g=`#!/usr/bin/env tsx
354
+ /** ${t} hook for ${c} */
364
355
 
365
356
  import { env } from 'node:process'
366
357
 
367
- console.log('Running ${t} hook for ${a}')
358
+ console.log('Running ${t} hook for ${c}')
368
359
  console.log('PROJECT_SLUG:', env.PROJECT_SLUG)
369
360
  if (env.TASK_SLUG) {
370
361
  console.log('TASK_SLUG:', env.TASK_SLUG)
@@ -372,10 +363,10 @@ if (env.TASK_SLUG) {
372
363
 
373
364
  // Exit with non-zero to prevent action (for pre-hooks)
374
365
  // process.exit(1)
375
- `;else if(r==="js")f=`#!/usr/bin/env node
376
- /** ${t} hook for ${a} */
366
+ `;else if(r==="js")g=`#!/usr/bin/env node
367
+ /** ${t} hook for ${c} */
377
368
 
378
- console.log('Running ${t} hook for ${a}')
369
+ console.log('Running ${t} hook for ${c}')
379
370
  console.log('PROJECT_SLUG:', process.env.PROJECT_SLUG)
380
371
  if (process.env.TASK_SLUG) {
381
372
  console.log('TASK_SLUG:', process.env.TASK_SLUG)
@@ -383,10 +374,10 @@ if (process.env.TASK_SLUG) {
383
374
 
384
375
  // Exit with non-zero to prevent action (for pre-hooks)
385
376
  // process.exit(1)
386
- `;else if(r==="sh")f=`#!/bin/bash
387
- # ${t} hook for ${a}
377
+ `;else if(r==="sh")g=`#!/bin/bash
378
+ # ${t} hook for ${c}
388
379
 
389
- echo "Running ${t} hook for ${a}"
380
+ echo "Running ${t} hook for ${c}"
390
381
  echo "PROJECT_SLUG: $PROJECT_SLUG"
391
382
  if [ -n "$TASK_SLUG" ]; then
392
383
  echo "TASK_SLUG: $TASK_SLUG"
@@ -394,25 +385,19 @@ fi
394
385
 
395
386
  # Exit with non-zero to prevent action (for pre-hooks)
396
387
  # exit 1
397
- `;else if(r==="py")f=`#!/usr/bin/env python3
398
- """${t} hook for ${a}"""
388
+ `;else if(r==="py")g=`#!/usr/bin/env python3
389
+ """${t} hook for ${c}"""
399
390
 
400
391
  import os
401
392
 
402
- print(f"Running ${t} hook for ${a}")
393
+ print(f"Running ${t} hook for ${c}")
403
394
  print(f"PROJECT_SLUG: {os.environ.get('PROJECT_SLUG')}")
404
395
  if os.environ.get('TASK_SLUG'):
405
396
  print(f"TASK_SLUG: {os.environ.get('TASK_SLUG')}")
406
397
 
407
398
  # Exit with non-zero to prevent action (for pre-hooks)
408
399
  # sys.exit(1)
409
- `;else throw new Error(`Unsupported language: ${r}`);await s.write(m,f);let{chmod:b}=await import('fs/promises');await b(m,493),console.log(`Hook created: ${m}`);}});});var bo,$,V=g(()=>{P();j();bo={async findHooks(t,e){let o=s.join(t,c.dirs.HOOKS);if(!await s.fileExists(o))return [];let n=await s.listDir(o),i=`${e}.`;return n.filter(a=>a.startsWith(i)).map(a=>s.join(o,a))},async executeHook(t,e,o){if(!await s.fileExists(t))return true;let n=e.project?s.joinHome(c.dirs.PROJECTS,e.project):o,i=e.task?s.join(n,c.dirs.TASKS,e.task):"",a={...process.env,HOOK_TYPE:e.action,ENTITY_TYPE:e.entityType,TARGET_DIR:o,PROJECT_DIR:n,...e.project?{PROJECT_SLUG:e.project}:{},...e.task?{TASK_SLUG:e.task,TASK_DIR:i}:{}};return new Promise(l=>{let m=spawn(t,[],{stdio:"inherit",env:a,cwd:G.dirname(t),shell:false});m.on("close",(d,f)=>{d===0?l(true):(console.error(`Hook ${G.basename(t)} failed (code=${d??f})`),l(false));}),m.on("error",d=>{console.error(`Failed to execute hook ${t}: ${d.message}`),l(false);});})},async runHooks(t,e,o){let r=await this.findHooks(t,e),n=e.startsWith("pre-");for(let i of r)if(!await this.executeHook(i,o,t)&&n)return false;return true},async runHooksForContext(t,e,o,r){return !(!await this.runHooks(t,o,r)||e&&!await this.runHooks(e,o,r))}},$=bo;});var ne,ie=g(()=>{k();V();D();P();ne=p({options:z$1.object({target:z$1.enum(c.targets).optional().describe("Target level")}),args:z$1.object({type:z$1.enum(c.hookTypes).describe("Hook type to run")}),handler:async({type:t,target:e})=>{let{targetDir:o,entityType:r}=h.getTargetDir(e),n={action:t,entityType:r,project:h.getProjectFromPwd()||void 0,task:h.getTaskFromPwd()||void 0};await $.runHooks(o,t,n)||(console.error(`Hook ${t} failed`),process.exit(1)),console.log(`Hook ${t} completed successfully`);}});});var Po,T,I=g(()=>{P();D();j();Po={formatEntry(t,e,o,r){let n=new Date,i=n.getFullYear(),a=String(n.getMonth()+1).padStart(2,"0"),l=String(n.getDate()).padStart(2,"0"),m=n.toLocaleTimeString("en-US",{hour12:false,hour:"2-digit",minute:"2-digit",second:"2-digit"});return `${`${i}-${a}-${l}`} ${m} ${t} ${e} ${o} ${r}
410
- `},async append(t,e,o,r,n){let i=s.join(t,c.files.LOG),a=this.formatEntry(e,o,r,n);await s.append(i,a);},async read(t){let e=s.join(t,c.files.LOG);return await s.fileExists(e)?await s.read(e):""},async task(t,e,o){let r=h.getCurrentContext();if(!r.project||!r.task)throw new Error("Not in a task directory");let n=s.joinHome(c.dirs.PROJECTS,r.project,c.dirs.TASKS,r.task);await this.append(n,"task",t,"log",o?`${o}: ${e}`:e);},async project(t,e,o){let r=h.getProjectFromPwd();if(!r)throw new Error("Not in a project directory");let n=s.joinHome(c.dirs.PROJECTS,r);await this.append(n,"project",t,"log",o?`${o}: ${e}`:e);}},T=Po;});var ae,ce=g(()=>{P();D();k();j();I();ae=p({description:"Append a custom entry to log.tsv",options:z$1.object({project:z$1.string().optional().describe("Project slug (uses current project from $PWD if not provided)"),task:z$1.string().optional().describe("Task slug (uses current task from $PWD if not provided)")}),args:z$1.object({text:z$1.string().describe("Text to append")}),handler:async({project:t,task:e,text:o})=>{let r=h.getCurrentContext(),n=t||r.project;if(!n)throw new Error("No project specified. Use --project or run from a project/task directory");let i=s.joinHome(c.dirs.PROJECTS,n);if(e||r.task){let a=e||r.task;if(!a)throw new Error("No task specified");let l=s.join(i,c.dirs.TASKS,a);await T.append(l,"task",a,"log",o),console.log(`Appended to task ${a} log.tsv`);}else await T.append(i,"project",n,"log",o),console.log(`Appended to project ${n} log.tsv`);}});});var pe,le=g(()=>{P();D();k();j();I();pe=p({description:"Read log.tsv history",options:z$1.object({project:z$1.string().optional().describe("Project slug (uses current project from $PWD if not provided)"),task:z$1.string().optional().describe("Task slug (uses current task from $PWD if not provided)")}),args:z$1.object({}),handler:async({project:t,task:e})=>{let o=h.getCurrentContext(),r=t||o.project;if(!r)throw new Error("No project specified. Use --project or run from a project/task directory");let n=s.joinHome(c.dirs.PROJECTS,r);if(e||o.task){let i=e||o.task;if(!i)throw new Error("No task specified");let a=s.join(n,c.dirs.TASKS,i),l=await T.read(a);console.log(l||`No log.tsv found for task ${i}`);}else {let i=await T.read(n);console.log(i||`No log.tsv found for project ${r}`);}}});});var me,de=g(()=>{k();V();j();x();I();me=p({description:"Create a new project with name, description, optional status, assignee and body",options:z$1.object({description:z$1.string().describe("Project description"),status:z$1.string().default("active").describe("Initial status"),assignee:z$1.string().optional().describe("Assignee agent slug"),body:z$1.string().optional().describe("Initial body/content (markdown)")}),args:z$1.object({name:z$1.string().describe("Project name")}),handler:async({name:t,description:e,status:o,assignee:r,body:n})=>{let i=s.slugify(t),a=u.getProjectDir(i);if(!await $.runHooks(a,"pre-create",{action:"pre-create",entityType:"project"}))throw new Error("Pre-create hook failed, aborting project creation");await u.createProject(i,{name:t,description:e,status:o,assignee:r,created:new Date().toISOString()},n),await T.append(a,"project",i,"created",`${t} > status is ${o}`),await $.runHooks(a,"post-create",{action:"post-create",entityType:"project"}),console.log(`Project created: ${i}`),console.log(` Path: ${a}`);}});});var ue,ge=g(()=>{k();D();ue=p({options:z$1.object({}),handler:async()=>{let t=h.getProjectFromPwd();t||(console.error("Not in a project directory"),process.exit(1)),console.log(t);}});});var ke,he=g(()=>{k();x();ke=p({description:"List all projects, optionally filtered by status",options:z$1.object({status:z$1.string().optional().describe("Filter by status")}),handler:async({status:t})=>{let e=await u.listProjects(),o=[];for(let r of e){let n=await u.getProject(r);n&&(t&&n.status!==t||o.push({slug:r,name:n.name||r,status:n.status,assignee:n.assignee}));}if(o.length===0){console.log("No projects found");return}console.log("Projects:"),console.log("---");for(let r of o)console.log(`${r.slug.padEnd(20)} ${r.name?.padEnd(30)||""} ${r.status||""} ${r.assignee||""}`);}});});var ye,je=g(()=>{k();x();ye=p({description:"Output project directory path (for cd)",options:z$1.object({}),args:z$1.object({name:z$1.string().describe("Project name (slug)")}),handler:async({name:t})=>{let e=u.getProjectDir(t);console.log(e);}});});var Te,we=g(()=>{P();D();k();V();j();x();I();Te=p({description:"Update project properties: name, description, status, assignee, or replace body",options:z$1.object({name:z$1.string().optional().describe("New name"),description:z$1.string().optional().describe("New description"),status:z$1.string().optional().describe("New status"),assignee:z$1.string().optional().describe("New assignee"),body:z$1.string().optional().describe("Replace entire body/content (markdown)")}),args:z$1.object({project:z$1.string().optional().describe("Project slug (defaults to current project from $PWD)")}),handler:async({project:t,name:e,description:o,status:r,assignee:n,body:i})=>{let a=t||h.getProjectFromPwd();if(!a)throw new Error("No project specified and not in a project directory");let l=u.getProjectDir(a),m=s.join(l,c.files.MAIN);if(!await $.runHooks(l,"pre-update",{action:"pre-update",entityType:"project"}))throw new Error("Pre-update hook failed, aborting update");let f={};if(e&&(f.name=e),o&&(f.description=o),r&&(f.status=r),n&&(f.assignee=n),Object.keys(f).length===0&&!i){console.log("No updates provided");return}if(Object.keys(f).length>0){await u.updateProject(a,f);let b=Object.entries(f).map(([C,E])=>`${C}=${E}`).join(", ");await T.append(l,"project",a,"updated",b);}i!==void 0&&(await u.updateBody(m,i),await T.append(l,"project",a,"updated",`body replaced (${i.length} chars)`)),await $.runHooks(l,"post-update",{action:"post-update",entityType:"project"}),console.log(`Project ${a} updated`);}});});var be,Pe=g(()=>{P();k();M();j();be=p({description:"Read a skill's SKILL.md file into the console for agent context",options:z$1.object({}),args:z$1.object({name:z$1.string().describe("Skill name (directory name)")}),handler:async({name:t})=>{let e=s.join(A.AIP_HOME,c.dirs.SKILLS,t),o=s.join(e,c.files.SKILL);if(!await s.fileExists(o))throw new Error(`Skill not found: ${t}
411
- Expected at: ${o}`);await s.logFiles(o);}});});var Se,xe=g(()=>{k();V();j();x();I();Se=p({description:"Create a new task with assignee, initial status and optional body",options:z$1.object({description:z$1.string().optional().describe("Task description"),assignee:z$1.string().optional().describe("Assignee agent slug"),status:z$1.string().default("backlog").describe("Initial status"),body:z$1.string().optional().describe("Initial body/content (markdown)")}),args:z$1.object({project:z$1.string().describe("Project slug"),name:z$1.string().describe("Task name")}),handler:async({project:t,name:e,description:o,assignee:r,status:n,body:i})=>{let a=s.slugify(e),l=u.getProjectDir(t),m=u.getTaskDir(t,a);if(!await $.runHooksForContext(l,m,"pre-create",{action:"pre-create",entityType:"task",project:t}))throw new Error("Pre-create hook failed, aborting task creation");await u.createTask(t,a,{name:e,description:o,assignee:r,status:n,created:new Date().toISOString()},i),await T.append(m,"task",a,"created",e),await T.append(l,"task",a,"created",`${a} > status is ${n}`),await $.runHooksForContext(l,m,"post-create",{action:"post-create",entityType:"task",project:t}),console.log(`Task created: ${a}`),console.log(` Project: ${t}`),console.log(` Path: ${m}`);}});});var $e,ve=g(()=>{k();D();$e=p({description:"Get the current task slug from PWD",options:z$1.object({}),handler:async()=>{let t=h.getTaskFromPwd();t||(console.error("Not in a task directory"),process.exit(1)),console.log(t);}});});var Ee,Ae=g(()=>{D();k();x();Ee=p({description:"Output full task context (main.md, log.tsv) for ingestion by agents",options:z$1.object({project:z$1.string().optional().describe("Project slug (searches all projects if not provided)")}),args:z$1.object({task:z$1.string().optional().describe("Task slug (default: from $PWD)")}),handler:async({project:t,task:e})=>{let o=h.getCurrentContext(),r=e??o.task;if(!r)throw new Error("Need task slug (or cd into task dir)");let{project:n}=await u.findTask(r,t);await u.ingestTask(n,r);}});});var Oe,De=g(()=>{k();x();Oe=p({description:"List tasks, optionally filtered by project, status, assignee, or search query",options:z$1.object({project:z$1.string().optional().describe("Project slug (searches all projects if not provided)"),statuses:z$1.array(z$1.string()).default([]).describe("Filter by statuses (multiple allowed)"),assignee:z$1.string().optional().describe("Filter by assignee"),all:z$1.boolean().default(false).describe("Include all tasks (including done/blocked)"),search:z$1.string().optional().describe("Search query (matches task slug or name, case-insensitive)")}),handler:async({project:t,statuses:e,assignee:o,all:r,search:n})=>{if(e&&e.length>0){for(let d of e)if(!ot.includes(d))throw new Error(`Invalid status: ${d}. Valid values: ${ot.join(", ")}`)}let i;e&&e.length>0?i=e:r?i=ot:i=At;let a=t?[t]:await u.listProjects(),l={};for(let d of a){let f=await u.listTasks(d),b=[];for(let C of f){let E=await u.getTask(d,C);if(E&&!(i.length>0&&!i.includes(E.status||""))&&!(o&&E.assignee!==o)){if(n){let v=n.toLowerCase(),dt=C.toLowerCase().includes(v),ut=(E.name||"").toLowerCase().includes(v);if(!dt&&!ut)continue}b.push({slug:C,name:E.name||C,status:E.status,assignee:E.assignee});}}b.length>0&&(l[d]=b.sort((C,E)=>C.slug.localeCompare(E.slug)));}let m=Object.keys(l).sort();if(m.length===0){console.log("No tasks found");return}for(let d of m){console.log(`
412
- ${d}:`),console.log("---");for(let f of l[d])console.log(`${f.slug.padEnd(20)} ${f.name?.padEnd(30)||""} ${f.status||""} ${f.assignee||""}`);}}});});var Ce,Ne=g(()=>{k();x();Ce=p({description:"Output task directory path (for cd)",options:z$1.object({project:z$1.string().optional().describe("Project slug (searches all projects if not provided)")}),args:z$1.object({task:z$1.string().describe("Task slug")}),handler:async({project:t,task:e})=>{let{project:o,task:r}=await u.findTask(e,t),n=u.getTaskDir(o,r);console.log(n);}});});var pt,xt=g(()=>{P();D();k();V();j();x();I();pt=p({description:"Update task properties: name, description, status, assignee, or replace body",options:z$1.object({name:z$1.string().optional().describe("New name"),description:z$1.string().optional().describe("New description"),status:z$1.string().optional().describe("New status"),assignee:z$1.string().optional().describe("New assignee"),project:z$1.string().optional().describe("Project slug (searches all projects if not provided)"),body:z$1.string().optional().describe("Replace entire body/content (markdown)")}),args:z$1.object({task:z$1.string().optional().describe("Task slug (default: from $PWD)")}),handler:async({project:t,task:e,name:o,description:r,status:n,assignee:i,body:a})=>{let l=h.getCurrentContext(),m=e??l.task;if(!m)throw new Error("No task specified (use --task or cd into task dir)");let{project:d}=await u.findTask(m,t),f=u.getTaskDir(d,m),b=u.getProjectDir(d),C=s.join(f,c.files.MAIN);if(!await $.runHooksForContext(b,f,"pre-update",{action:"pre-update",entityType:"task",project:d,task:m}))throw new Error("Pre-update hook failed, aborting update");let v={};if(o&&(v.name=o),r&&(v.description=r),n&&(v.status=n),i&&(v.assignee=i),Object.keys(v).length===0&&!a){console.log("No updates provided");return}if(Object.keys(v).length>0){await u.updateTask(d,m,v);let dt=Object.entries(v).map(([ut,Ke])=>`${ut}=${Ke}`).join(", ");await T.append(f,"task",m,"updated",dt);}a!==void 0&&(await u.updateBody(C,a),await T.append(f,"task",m,"updated",`body replaced (${a.length} chars)`)),v.status&&await T.append(b,"task",m,"updated",`status to ${v.status}`),await $.runHooksForContext(u.getProjectDir(d),f,"post-update",{action:"post-update",entityType:"task",project:d,task:m}),console.log(`Task ${m} updated`);}});});var Re,Ie=g(()=>{D();k();x();xt();Re=p({description:"Start a task: set status to in-progress, optionally print context",options:z$1.object({project:z$1.string().optional().describe("Project slug (searches all projects if not provided)"),ingest:z$1.boolean().default(false).describe("Also output context for this task")}),args:z$1.object({task:z$1.string().optional().describe("Task slug (default: from $PWD)")}),handler:async({project:t,task:e,ingest:o})=>{let r=h.getCurrentContext(),n=e??r.task;if(!n)throw new Error("No task specified (use --task or cd into task dir)");let{project:i}=await u.findTask(n,t);(await u.getTask(i,n))?.status!=="in-progress"&&await pt.handler({project:i,task:n,status:"in-progress"}),o&&await u.ingestTask(i,n);}});});var Le,Fe=g(()=>{k();x();I();Le=p({description:"Post-mortem analysis for a completed task",options:z$1.object({}),args:z$1.object({project:z$1.string().describe("Project slug"),task:z$1.string().describe("Task slug")}),handler:async({project:t,task:e})=>{let o=u.getTaskDir(t,e),r=await u.getTask(t,e),i=(await T.read(o)).split(`
413
- `).filter(m=>m.trim()).length,a=[],l=r?.name||e;i>5&&a.push("High log entry count - consider breaking into smaller tasks"),l.toLowerCase().includes("implement")&&a.push("Implementation task - check if similar patterns exist to reuse"),l.toLowerCase().includes("create")&&l.toLowerCase().includes("command")&&a.push("Command creation - check existing command patterns in src/commands/"),console.log(`
414
- === Post-Mortem Analysis ===`),console.log(`Project: ${t}`),console.log(`Task: ${e}`),console.log(`Name: ${l}`),console.log(`Status: ${r?.status||"unknown"}`),console.log(`Log entries: ${i}`),a.length>0?(console.log(`
415
- Suggestions:`),a.forEach(m=>console.log(` - ${m}`))):console.log(`
416
- No specific suggestions - task looks well-scoped`),console.log(`
417
- === End Post-Mortem ===
418
- `);}});});var Ue,_e=g(()=>{k();j();Ue=p({description:"Read one or more files into the console",options:z$1.object({}),args:z$1.object({paths:z$1.array(z$1.string()).describe("File paths to read")}),handler:async({paths:t})=>{await s.logFiles(...t);}});});var yt={};Me(yt,{default:()=>K});var $o,K,rt=g(()=>{Ct();Rt();Lt();Ut();Ht();zt();Jt();Zt();Xt();ee();re();ie();ce();le();de();ge();he();je();we();Pe();xe();ve();Ae();De();Ne();Ie();xt();Fe();_e();$o={agent:{create:Dt,current:Nt,list:It,path:Ft,start:_t},help:{api:Mt,hooks:Bt,quickstart:Wt,skill:Qt,usage:te},hook:{create:oe,run:ne},log:{append:ae,read:pe},project:{create:me,current:ue,list:ke,path:ye,update:Te},skill:{read:be},task:{create:Se,current:$e,ingest:Ee,list:Oe,path:Ce,start:Re,update:pt},util:{postmortem:Le,read:Ue}},K=$o;});W();rt();j();process.on("unhandledRejection",t=>{console.error("Unhandled Rejection:",t),process.exit(1);});process.on("uncaughtException",t=>{console.error("Unhandled Exception:",t),process.exit(1);});async function He(t){let[e,o,...r]=t;(e==="--version"||e==="-v")&&(console.log(S.version),process.exit(0));try{(!e||!s.isKeyOf(e,K))&&(await K.help.usage.handler({}),process.exit(1));let n=K[e];(!o||!s.isKeyOf(o,n))&&(await K.help.usage.handler({name:e}),process.exit(1));let i=n[o];i||(console.error(`Error: unknown command '${e} ${o}'`),console.log("Run with --help for more information"),process.exit(1)),await i.handler(i.parser.name(`${e} ${o}`).parse(r));}catch(n){console.error("Error:",s.errorMessage(n)),process.exit(1);}}var Hi=He,Ki=K;s.isMain()&&He(process.argv.slice(2));export{Ki as commands,Hi as default};
400
+ `;else throw new Error(`Unsupported language: ${r}`);await s.write(m,g);let{chmod:b}=await import('fs/promises');await b(m,493),console.log(`Hook created: ${m}`);}});});var fo,v,z=f(()=>{P();j();fo={async findHooks(t,e){let o=s.join(t,a.dirs.HOOKS);if(!await s.fileExists(o))return [];let n=await s.listDir(o),i=`${e}.`;return n.filter(c=>c.startsWith(i)).map(c=>s.join(o,c))},async executeHook(t,e,o){if(!await s.fileExists(t))return true;let n=e.project?s.joinHome(a.dirs.PROJECTS,e.project):o,i=e.task?s.join(n,a.dirs.TASKS,e.task):"",c={...process.env,HOOK_TYPE:e.action,ENTITY_TYPE:e.entityType,TARGET_DIR:o,PROJECT_DIR:n,...e.project?{PROJECT_SLUG:e.project}:{},...e.task?{TASK_SLUG:e.task,TASK_DIR:i}:{}};return new Promise(d=>{let m=spawn(t,[],{stdio:"inherit",env:c,cwd:o,shell:false});m.on("close",(l,g)=>{l===0?d(true):(console.error(`Hook ${rt.basename(t)} failed (code=${l??g})`),d(false));}),m.on("error",l=>{console.error(`Failed to execute hook ${t}: ${l.message}`),d(false);});})},async runHooks(t,e,o){let r=await this.findHooks(t,e),n=e.startsWith("pre-");for(let i of r)if(!await this.executeHook(i,o,t)&&n)return false;return true},async runHooksForContext(t,e,o,r){return !(!await this.runHooks(t,o,r)||e&&!await this.runHooks(e,o,r))}},v=fo;});var oe,re=f(()=>{k();z();O();P();oe=p({options:z$1.object({target:z$1.enum(a.targets).optional().describe("Target level")}),args:z$1.object({type:z$1.enum(a.hookTypes).describe("Hook type to run")}),handler:async({type:t,target:e})=>{let{targetDir:o,entityType:r}=h.getTargetDir(e),n={action:t,entityType:r,project:h.getProjectFromPwd()||void 0,task:h.getTaskFromPwd()||void 0};await v.runHooks(o,t,n)||(console.error(`Hook ${t} failed`),process.exit(1)),console.log(`Hook ${t} completed successfully`);}});});var go,w,F=f(()=>{P();O();j();go={formatEntry(t,e,o,r){let n=new Date,i=n.getFullYear(),c=String(n.getMonth()+1).padStart(2,"0"),d=String(n.getDate()).padStart(2,"0"),m=n.toLocaleTimeString("en-US",{hour12:false,hour:"2-digit",minute:"2-digit",second:"2-digit"});return `${`${i}-${c}-${d}`} ${m} ${t} ${e} ${o} ${r}
401
+ `},async append(t,e,o,r,n){let i=s.join(t,a.files.LOG),c=this.formatEntry(e,o,r,n);await s.append(i,c);},async read(t){let e=s.join(t,a.files.LOG);return await s.fileExists(e)?await s.read(e):""},async task(t,e,o){let r=h.getCurrentContext();if(!r.project||!r.task)throw new Error("Not in a task directory");let n=s.joinHome(a.dirs.PROJECTS,r.project,a.dirs.TASKS,r.task);await this.append(n,"task",t,"log",o?`${o}: ${e}`:e);},async project(t,e,o){let r=h.getProjectFromPwd();if(!r)throw new Error("Not in a project directory");let n=s.joinHome(a.dirs.PROJECTS,r);await this.append(n,"project",t,"log",o?`${o}: ${e}`:e);}},w=go;});var se,ne=f(()=>{P();O();k();j();F();se=p({description:"Append a custom entry to log.tsv",options:z$1.object({project:z$1.string().optional().describe("Project slug (uses current project from $PWD if not provided)"),task:z$1.string().optional().describe("Task slug (uses current task from $PWD if not provided)")}),args:z$1.object({text:z$1.string().describe("Text to append")}),handler:async({project:t,task:e,text:o})=>{let r=h.getCurrentContext(),n=t||r.project;if(!n)throw new Error("No project specified. Use --project or run from a project/task directory");let i=s.joinHome(a.dirs.PROJECTS,n);if(e||r.task){let c=e||r.task;if(!c)throw new Error("No task specified");let d=s.join(i,a.dirs.TASKS,c);await w.append(d,"task",c,"log",o),console.log(`Appended to task ${c} log.tsv`);}else await w.append(i,"project",n,"log",o),console.log(`Appended to project ${n} log.tsv`);}});});var ie,ae=f(()=>{P();O();k();j();F();ie=p({description:"Read log.tsv history",options:z$1.object({project:z$1.string().optional().describe("Project slug (uses current project from $PWD if not provided)"),task:z$1.string().optional().describe("Task slug (uses current task from $PWD if not provided)")}),args:z$1.object({}),handler:async({project:t,task:e})=>{let o=h.getCurrentContext(),r=t||o.project;if(!r)throw new Error("No project specified. Use --project or run from a project/task directory");let n=s.joinHome(a.dirs.PROJECTS,r);if(e||o.task){let i=e||o.task;if(!i)throw new Error("No task specified");let c=s.join(n,a.dirs.TASKS,i),d=await w.read(c);console.log(d||`No log.tsv found for task ${i}`);}else {let i=await w.read(n);console.log(i||`No log.tsv found for project ${r}`);}}});});var ce,pe=f(()=>{k();j();F();x();ce=p({description:"Create a new project with name, description, optional status, assignee and body",options:z$1.object({description:z$1.string().describe("Project description"),status:z$1.string().default("active").describe("Initial status"),assignee:z$1.string().optional().describe("Assignee agent slug"),body:z$1.string().optional().describe("Initial body/content (markdown)")}),args:z$1.object({name:z$1.string().describe("Project name")}),handler:async({name:t,description:e,status:o,assignee:r,body:n})=>{let i=s.slugify(t),c=u.getProjectDir(i);await u.createProject(i,{name:t,description:e,status:o,assignee:r,created:new Date().toISOString()},n),await w.append(c,"project",i,"created",`${t} > status is ${o}`),console.log(`Project created: ${i}. Path: ${c}`);}});});var le,de=f(()=>{k();O();le=p({options:z$1.object({}),handler:async()=>{let t=h.getProjectFromPwd();t||(console.error("Not in a project directory"),process.exit(1)),console.log(t);}});});var ue,fe=f(()=>{k();x();ue=p({description:"List all projects, optionally filtered by status",options:z$1.object({status:z$1.string().optional().describe("Filter by status")}),handler:async({status:t})=>{let e=await u.listProjects(),o=[];for(let r of e){let n=await u.getProject(r);n&&(t&&n.status!==t||o.push({slug:r,name:n.name||r,status:n.status,assignee:n.assignee}));}if(o.length===0){console.log("No projects found");return}console.log("Projects:"),console.log("---");for(let r of o)console.log(`${r.slug.padEnd(20)} ${r.name?.padEnd(30)||""} ${r.status||""} ${r.assignee||""}`);}});});var ge,ke=f(()=>{k();x();ge=p({description:"Output project directory path (for cd)",options:z$1.object({}),args:z$1.object({name:z$1.string().describe("Project name (slug)")}),handler:async({name:t})=>{let e=u.getProjectDir(t);console.log(e);}});});var he,ye=f(()=>{P();O();k();z();j();x();F();he=p({description:"Update project properties: name, description, status, assignee, or replace body",options:z$1.object({name:z$1.string().optional().describe("New name"),description:z$1.string().optional().describe("New description"),status:z$1.string().optional().describe("New status"),assignee:z$1.string().optional().describe("New assignee"),body:z$1.string().optional().describe("Replace entire body/content (markdown)")}),args:z$1.object({project:z$1.string().optional().describe("Project slug (defaults to current project from $PWD)")}),handler:async({project:t,name:e,description:o,status:r,assignee:n,body:i})=>{let c=t||h.getProjectFromPwd();if(!c)throw new Error("No project specified and not in a project directory");let d=u.getProjectDir(c),m=s.join(d,a.files.MAIN);if(!await v.runHooks(d,"pre-update",{action:"pre-update",entityType:"project"}))throw new Error("Pre-update hook failed, aborting update");let g={};if(e&&(g.name=e),o&&(g.description=o),r&&(g.status=r),n&&(g.assignee=n),Object.keys(g).length===0&&!i){console.log("No updates provided");return}if(Object.keys(g).length>0){await u.updateProject(c,g);let b=Object.entries(g).map(([C,A])=>`${C}=${A}`).join(", ");await w.append(d,"project",c,"updated",b);}i!==void 0&&(await u.updateBody(m,i),await w.append(d,"project",c,"updated",`body replaced (${i.length} chars)`)),await v.runHooks(d,"post-update",{action:"post-update",entityType:"project"}),console.log(`Project ${c} updated`);}});});var je,Te=f(()=>{P();k();H();j();je=p({description:"Read a skill's SKILL.md file into the console for agent context",options:z$1.object({}),args:z$1.object({name:z$1.string().describe("Skill name (directory name)")}),handler:async({name:t})=>{let e=s.join(D.AIP_HOME,a.dirs.SKILLS,t),o=s.join(e,a.files.SKILL);if(!await s.fileExists(o))throw new Error(`Skill not found: ${t}
402
+ Expected at: ${o}`);await s.logFiles(o);}});});var we,be=f(()=>{k();z();j();x();F();we=p({description:"Create a new task with assignee, initial status and optional body",options:z$1.object({description:z$1.string().optional().describe("Task description"),assignee:z$1.string().optional().describe("Assignee agent slug"),status:z$1.string().default("backlog").describe("Initial status"),body:z$1.string().optional().describe("Initial body/content (markdown)")}),args:z$1.object({project:z$1.string().describe("Project slug"),name:z$1.string().describe("Task name")}),handler:async({project:t,name:e,description:o,assignee:r,status:n,body:i})=>{let c=s.slugify(e),d=u.getProjectDir(t),m=u.getTaskDir(t,c);if(!await v.runHooksForContext(d,m,"pre-create",{action:"pre-create",entityType:"task",project:t}))throw new Error("Pre-create hook failed, aborting task creation");await u.createTask(t,c,{name:e,description:o,assignee:r,status:n,created:new Date().toISOString()},i),await w.append(m,"task",c,"created",e),await w.append(d,"task",c,"created",`${c} > status is ${n}`),await v.runHooksForContext(d,m,"post-create",{action:"post-create",entityType:"task",project:t}),console.log(`Task created: ${c}`),console.log(` Project: ${t}`),console.log(` Path: ${m}`);}});});var Pe,Se=f(()=>{k();O();Pe=p({description:"Get the current task slug from PWD",options:z$1.object({}),handler:async()=>{let t=h.getTaskFromPwd();t||(console.error("Not in a task directory"),process.exit(1)),console.log(t);}});});var xe,$e=f(()=>{O();k();x();xe=p({description:"Output full task context (main.md, log.tsv) for ingestion by agents",options:z$1.object({project:z$1.string().optional().describe("Project slug (searches all projects if not provided)")}),args:z$1.object({task:z$1.string().optional().describe("Task slug (default: from $PWD)")}),handler:async({project:t,task:e})=>{let o=h.getCurrentContext(),r=e??o.task;if(!r)throw new Error("Need task slug (or cd into task dir)");let{project:n}=await u.findTask(r,t);await u.ingestTask(n,r);}});});var ve,Ee=f(()=>{k();x();ve=p({description:"List tasks, optionally filtered by project, status, assignee, or search query",options:z$1.object({project:z$1.string().optional().describe("Project slug (searches all projects if not provided)"),statuses:z$1.array(z$1.string()).default([]).describe("Filter by statuses (multiple allowed)"),assignee:z$1.string().optional().describe("Filter by assignee"),all:z$1.boolean().default(false).describe("Include all tasks (including done/blocked)"),search:z$1.string().optional().describe("Search query (matches task slug or name, case-insensitive)")}),handler:async({project:t,statuses:e,assignee:o,all:r,search:n})=>{if(e&&e.length>0){for(let l of e)if(!et.includes(l))throw new Error(`Invalid status: ${l}. Valid values: ${et.join(", ")}`)}let i;e&&e.length>0?i=e:r?i=et:i=vt;let c=t?[t]:await u.listProjects(),d={};for(let l of c){let g=await u.listTasks(l),b=[];for(let C of g){let A=await u.getTask(l,C);if(A&&!(i.length>0&&!i.includes(A.status||""))&&!(o&&A.assignee!==o)){if(n){let E=n.toLowerCase(),lt=C.toLowerCase().includes(E),dt=(A.name||"").toLowerCase().includes(E);if(!lt&&!dt)continue}b.push({slug:C,name:A.name||C,status:A.status,assignee:A.assignee});}}b.length>0&&(d[l]=b.sort((C,A)=>C.slug.localeCompare(A.slug)));}let m=Object.keys(d).sort();if(m.length===0){console.log("No tasks found");return}for(let l of m){console.log(`
403
+ ${l}:`),console.log("---");for(let g of d[l])console.log(`${g.slug.padEnd(20)} ${g.name?.padEnd(30)||""} ${g.status||""} ${g.assignee||""}`);}}});});var Ae,De=f(()=>{k();x();Ae=p({description:"Output task directory path (for cd)",options:z$1.object({project:z$1.string().optional().describe("Project slug (searches all projects if not provided)")}),args:z$1.object({task:z$1.string().describe("Task slug")}),handler:async({project:t,task:e})=>{let{project:o,task:r}=await u.findTask(e,t),n=u.getTaskDir(o,r);console.log(n);}});});var ct,Pt=f(()=>{P();O();k();z();j();x();F();ct=p({description:"Update task properties: name, description, status, assignee, or replace body",options:z$1.object({name:z$1.string().optional().describe("New name"),description:z$1.string().optional().describe("New description"),status:z$1.string().optional().describe("New status"),assignee:z$1.string().optional().describe("New assignee"),project:z$1.string().optional().describe("Project slug (searches all projects if not provided)"),body:z$1.string().optional().describe("Replace entire body/content (markdown)")}),args:z$1.object({task:z$1.string().optional().describe("Task slug (default: from $PWD)")}),handler:async({project:t,task:e,name:o,description:r,status:n,assignee:i,body:c})=>{let d=h.getCurrentContext(),m=e??d.task;if(!m)throw new Error("No task specified (use --task or cd into task dir)");let{project:l}=await u.findTask(m,t),g=u.getTaskDir(l,m),b=u.getProjectDir(l),C=s.join(g,a.files.MAIN);if(!await v.runHooksForContext(b,g,"pre-update",{action:"pre-update",entityType:"task",project:l,task:m}))throw new Error("Pre-update hook failed, aborting update");let E={};if(o&&(E.name=o),r&&(E.description=r),n&&(E.status=n),i&&(E.assignee=i),Object.keys(E).length===0&&!c){console.log("No updates provided");return}if(Object.keys(E).length>0){await u.updateTask(l,m,E);let lt=Object.entries(E).map(([dt,Fe])=>`${dt}=${Fe}`).join(", ");await w.append(g,"task",m,"updated",lt);}c!==void 0&&(await u.updateBody(C,c),await w.append(g,"task",m,"updated",`body replaced (${c.length} chars)`)),E.status&&await w.append(b,"task",m,"updated",`status to ${E.status}`),await v.runHooksForContext(u.getProjectDir(l),g,"post-update",{action:"post-update",entityType:"task",project:l,task:m}),console.log(`Task ${m} updated`);}});});var Oe,Ce=f(()=>{O();k();z();x();Pt();Oe=p({description:"Start a task: set status to in-progress, optionally print context",options:z$1.object({project:z$1.string().optional().describe("Project slug (searches all projects if not provided)"),ingest:z$1.boolean().default(true).describe("Also output context for this task")}),args:z$1.object({task:z$1.string().optional().describe("Task slug (default: from $PWD)")}),handler:async({project:t,task:e,ingest:o})=>{let r=h.getCurrentContext(),n=e??r.task;if(!n)throw new Error("No task specified (use --task or cd into task dir)");let{project:i}=await u.findTask(n,t),c=u.getProjectDir(i),d=u.getTaskDir(i,n);if(!await v.runHooksForContext(c,d,"pre-start",{action:"pre-start",entityType:"task",project:i,task:n}))throw new Error("Pre-start hook failed, aborting task start");(await u.getTask(i,n))?.status!=="in-progress"&&await ct.handler({project:i,task:n,status:"in-progress"}),o&&await u.ingestTask(i,n),await v.runHooksForContext(c,d,"post-start",{action:"post-start",entityType:"task",project:i,task:n});}});});var Ne,Re=f(()=>{k();j();Ne=p({description:"Read one or more files into the console",options:z$1.object({}),args:z$1.object({paths:z$1.array(z$1.string()).describe("File paths to read")}),handler:async({paths:t})=>{await s.logFiles(...t);}});});var kt={};_e(kt,{default:()=>U});var yo,U,ot=f(()=>{Dt();Ct();Rt();Ft();_t();Gt();zt();Vt();Yt();Xt();ee();re();ne();ae();pe();de();fe();ke();ye();Te();be();Se();$e();Ee();De();Ce();Pt();Re();yo={agent:{create:At,current:Ot,list:Nt,path:It,start:Lt},help:{api:Kt,hooks:Mt,quickstart:Jt,skill:qt,usage:Qt},hook:{create:te,run:oe},log:{append:se,read:ie},project:{create:ce,current:le,list:ue,path:ge,update:he},skill:{read:je},task:{create:we,current:Pe,ingest:xe,list:ve,path:Ae,start:Oe,update:ct},util:{read:Ne}},U=yo;});B();ot();j();process.on("unhandledRejection",t=>{console.error("Unhandled Rejection:",t),process.exit(1);});process.on("uncaughtException",t=>{console.error("Unhandled Exception:",t),process.exit(1);});async function Ie(t){let[e,o,...r]=t;(e==="--version"||e==="-v")&&(console.log(S.version),process.exit(0));try{(!e||!s.isKeyOf(e,U))&&(await U.help.usage.handler({}),process.exit(1));let n=U[e];(!o||!s.isKeyOf(o,n))&&(await U.help.usage.handler({name:e}),process.exit(1));let i=n[o];i||(console.error(`Error: unknown command '${e} ${o}'`),console.log("Run with --help for more information"),process.exit(1)),await i.handler(i.parser.name(`${e} ${o}`).parse(r));}catch(n){console.error("Error:",s.errorMessage(n)),process.exit(1);}}var Pi=Ie,Si=U;s.isMain()&&Ie(process.argv.slice(2));export{Si as commands,Pi as default};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-projects",
3
- "version": "1.6.0",
3
+ "version": "1.6.2",
4
4
  "type": "module",
5
5
  "description": "Useful CLI for AI agents to create and manage projects, tasks, skills and agents",
6
6
  "main": "dist/index.js",
@@ -17,11 +17,10 @@
17
17
  "build": "npm run build:map && npm run build:code",
18
18
  "build:map": "tsx bin/map-commands.ts",
19
19
  "build:code": "tsup --no-dts",
20
- "build:all": "npm run build:map && tsup",
20
+ "build:full": "npm run build:map && tsup",
21
21
  "build:check": "tsc --noEmit",
22
22
  "build:watch": "npm run build:code -- --watch",
23
23
  "build:clean": "rimraf dist/*",
24
- "build:incr": "tsup --no-dts",
25
24
  "start": "dist/index.js",
26
25
  "dev": "npm run build:watch -- --onSuccess \"dist/index.js\"",
27
26
  "cli": "npm run build && npm start --",
@@ -29,20 +28,17 @@
29
28
  "vitest": "VITE_CJS_IGNORE_WARNING=true vitest",
30
29
  "test": "npm run test:types && npm run test:unit",
31
30
  "test:unit": "npm run vitest -- run",
32
- "test:types:test": "tsc -p tsconfig.test.json --incremental --tsBuildInfoFile dist/test.tsbuildinfo",
33
- "test:types:bin": "tsc -p bin/tsconfig.json --incremental --tsBuildInfoFile dist/bin.tsbuildinfo",
31
+ "test:types:test": "tsc -p tsconfig.test.json --incremental --tsBuildInfoFile test.tsbuildinfo",
32
+ "test:types:bin": "tsc -p bin/tsconfig.json --incremental --tsBuildInfoFile bin.tsbuildinfo",
34
33
  "test:types": "npm run test:types:test && npm run test:types:bin",
35
34
  "test:full": "npm run lint:full && npm run test",
36
35
  "eslint": "eslint --cache",
37
36
  "lint": "npm run eslint -- '{src,bin}/**/*.ts'",
38
37
  "lint:fix": "npm run lint -- --fix",
39
- "lint:full": "npm run build:incr && npm run test:types:bin && npm run lint:fix",
38
+ "lint:full": "npm run build:check && npm run test:types:bin && npm run lint:fix",
40
39
  "lint:full:silent": "npm run -s lint:full && echo LINT OK",
41
- "map": "npm run build:map",
42
- "link": "npm link",
43
- "unlink": "npm unlink",
44
40
  "prepare": "[ \"$CI\" != \"true\" ] && [ -d node_modules/husky ] && husky || true",
45
- "prepack": "npm run test:full && npm run build:all",
41
+ "prepack": "npm run test:full && npm run build:full",
46
42
  "publish:dry": "npm pack --dry-run",
47
43
  "version:patch": "npm version patch",
48
44
  "version:minor": "npm version minor",