ai-projects 1.6.2 → 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +4 -3
  2. package/dist/index.js +46 -46
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -93,8 +93,8 @@ $AIP_HOME/projects/{project}/
93
93
  ├── main.md # Goals + body (YAML frontmatter + markdown)
94
94
  ├── log.tsv # Activity log (tab-separated: date, time, type, slug, action, text)
95
95
  ├── hooks/ # Automation: pre|post-{create,start,update,complete}
96
- ├── outputs/ # Deliverables go here
97
- ├── inputs/ # External data (API responses, downloads)
96
+ ├── inputs/ # Intermediate/raw data (e.g. API responses, downloads)
97
+ ├── outputs/ # Deliverables go here (e.g. reports, leads, etc.)
98
98
  ├── scripts/ # Automation scripts
99
99
  └── tasks/{task}/
100
100
  ├── main.md # Task definition + body
@@ -116,7 +116,8 @@ aip project path my-project # Get absolute path
116
116
  ```bash
117
117
  aip task create my-project "task-name" --description "..."
118
118
  aip task update --status in-progress
119
- aip task list
119
+ aip task list --project my-project
120
+ aip task list --search "-name"
120
121
  aip task path task-name # Get absolute path
121
122
  aip task start # Start working (and read in all context to stdout)
122
123
  ```
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 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}
2
+ import {z as z$1}from'zod';import {parser}from'zod-opts';import nt from'path';import {spawn,exec}from'child_process';import G from'fs/promises';import T from'lodash';import W from'moment';import {fileURLToPath}from'url';import {inspect}from'util';import vt from'yaml';var Ge=Object.defineProperty;var f=(t,e)=>()=>(t&&(e=t(t=0)),e);var Ke=(t,e)=>{for(var o in e)Ge(t,o,{get:e[o],enumerable:true});};var S,J=f(()=>{S={name:"ai-projects",version:"1.7.1",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,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(([g,b])=>({name:g,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=f(()=>{});var c,P=f(()=>{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 V,Je,A,H=f(()=>{P();V=process.env.AIP_HOME;if(!V){V=process.cwd();let t=V.split(nt.sep);for(let e of [c.dirs.PROJECTS,c.dirs.SKILLS,c.dirs.AGENTS]){let o=t.indexOf(e);if(o!==-1){V=t.slice(0,o).join(nt.sep);break}}}Je={AIP_HOME:V},A=Je;});var j,s,y=f(()=>{H();j={REPO:fileURLToPath(import.meta.url.replace(/\/(dist|src)\/.*/,"/")),join:(...t)=>nt.join(...t),onRepo:(...t)=>j.join(j.REPO,...t),joinHome:(...t)=>j.join(A.AIP_HOME,...t),async ensureDir(t){await G.mkdir(t,{recursive:true});},async write(t,e){await j.ensureDir(nt.dirname(t)),await G.writeFile(t,e,"utf8");},async append(t,e){await j.ensureDir(nt.dirname(t)),await G.appendFile(t,e,"utf8");},async read(t){return G.readFile(t,"utf8")},async readRepo(...t){return j.read(j.onRepo(...t))},async readMany(...t){return (await Promise.all(t.map(async o=>{let r=await j.fileExists(o)?await j.read(o):"ERROR: File not found";return `# ${o}
3
3
 
4
- ${r}`}))).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 j.readMany(...t);console.log(e.join(`
5
5
 
6
6
  ---
7
7
 
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,`
8
+ `));},dumpCommandMapLines(t,e){let o=e?T.pick(t,e):t,r=[];for(let[n,i]of j.entriesOf(o))r.push(`${n} {${Object.keys(i).join("|")}}`);return r},async fileExists(t){try{return await G.access(t),!0}catch{return false}},async listDir(t){try{return await G.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)=>T.isArray(t)?t.map(o=>j.omitByDeep(o,e)):T.isPlainObject(t)?T.mapValues(T.omitBy(t,e),o=>j.omitByDeep(o,e)):t,omitNilsDeep:t=>j.omitByDeep(t,T.isNil),omitUndefinedsDeep:t=>j.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)?j.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,j.memoizeKey),toMS:t=>W.duration(t).asMilliseconds(),toSecs:t=>W.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=>j.oneLine(j.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)=>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()}
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())=>W.duration(W(e).diff(t||0)),iso:t=>W.utc(t).toISOString(),isoDate:t=>j.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,""),matchesSearch:(t,e)=>{let o=e?.toLowerCase().split(/\s+/).filter(Boolean);if(!o?.length)return true;let r=t.toLowerCase();return o.every(n=>r.includes(n))}},s=j;});var Ye,et,Qe,$t=f(()=>{y();Ye=" ",et=class{filename;context;constructor(t){this.filename=t;}log=(t,e,...o)=>{this.filename&&!this.context&&(this.context=`<${Qe(this.filename)}>`),this.context&&o.unshift(this.context);let[r,n]=new Date().toISOString().split(/[T.]/);o.unshift(e,r,n);let i=o.map(this.stringify).map(this.sanitize).join(Ye);return t?console.error(i):console.log(i),i};stringify=t=>{if(!t)return "-";if(T.isNumber(t))return `${t}`;if(T.isError(t))return s.oneLine(t.message||"");if(T.isFunction(t))return s.oneLine(t.toString());if(T.isObject(t)||T.isArray(t))try{return s.dump(t)}catch(e){return `Failed to stringify: ${e.message}`}return T.toString(t)};sanitize=t=>t.replace(/ {2,}/g," ");debug=(...t)=>{this.log(false,"[DEBUG]",...t);};info=(...t)=>{this.log(false,"[INFO]",...t);};warn=(...t)=>{this.log(true,"[WARN]",...t);};error=(...t)=>{this.log(true,"[ERROR]",...t);}},Qe=t=>{let e=t.split(nt.sep),[o,r,...n]=e.reverse();if(!n.length)return t;let i=nt.basename(o,".js").replace(".ts","");if(i==="index")return r;let a=e.indexOf("commands");if(a!==-1&&a<e.length-1){let l=e.slice(a+1);if(l.length>=2){let[m,d]=l;return `<${m}/${d.replace(".js","").replace(".ts","")}>`}}return i};});var Xe,ot,M,ut,Z,At=f(()=>{y();$t();Xe=new et,ot=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},M=async(t,e,o="")=>{let n=`---
13
+ ${vt.stringify(e).trim()}
14
14
  ---
15
15
 
16
16
  ${o}`.trim();await s.write(t,n+`
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(`
17
+ `);},ut=async(t,e)=>{let o=await s.read(t),r=ot(o);if(!r)throw new Error(`No frontmatter found in ${t}`);let n={...r.frontmatter,...e};return await M(t,n,r.content),n},Z=async t=>{if(!await s.fileExists(t))return null;let o=await s.read(t),r=ot(o);return r?r.frontmatter:(Xe.warn(`No frontmatter found in ${t}`),null)};});var z,rt,Et,Ot,to,eo,u,x=f(()=>{P();H();At();y();z=(a=>(a.BACKLOG="backlog",a.IN_PROGRESS="in-progress",a.ONGOING="ongoing",a.DONE="done",a.BLOCKED="blocked",a.TO_DO="to-do",a))(z||{}),rt=Object.values(z),Et=["backlog","in-progress","ongoing"],Ot=[c.dirs.HOOKS,c.dirs.INPUTS,c.dirs.OUTPUTS,c.dirs.SCRIPTS],to=[c.dirs.TASKS,...Ot],eo={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(to.map(n=>s.ensureDir(s.join(r,n)))),await M(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 M(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 M(s.join(o,c.files.MAIN),e),o},async getProject(t){let e=s.join(this.getProjectDir(t),c.files.MAIN);return await Z(e)},async getTask(t,e){let o=s.join(this.getTaskDir(t,e),c.files.MAIN);return await Z(o)},async getAgent(t){let e=s.join(this.getAgentDir(t),c.files.MAIN);return await Z(e)},async updateProject(t,e){let o=s.join(this.getProjectDir(t),c.files.MAIN);return await ut(o,e)},async updateBody(t,e){let o=await s.read(t),r=ot(o);if(!r)throw new Error(`No frontmatter found in ${t}`);await M(t,r.frontmatter,e);},async updateTask(t,e,o){let r=s.join(this.getTaskDir(t,e),c.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,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=eo;});var Dt,Ct=f(()=>{k();y();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 Rt,Nt=f(()=>{k();Rt=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,Ft=f(()=>{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,description:r.description});}if(e.length===0)return console.log("No agents found");console.log("Agents:");for(let o of e)console.log(`- ${o.slug}: ${o.description||""}`);}});});var Lt,_t=f(()=>{P();k();H();y();Lt=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 Ut,Ht=f(()=>{P();k();H();y();Ut=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 Gt,Kt,no,Mt,zt=f(()=>{k();Gt=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=Kt(i.innerType):i.typeName==="ZodDefault"&&(a=Kt(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},Kt=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"},no=(t,e,o)=>{let r=Gt(o.options),n=o.args?Gt(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 g=d.required?`<${d.name}>`:`[${d.name}]`,b=d.description||"";d.defaultValue!==void 0&&(b+=b?` (default: ${d.defaultValue})`:`(default: ${d.defaultValue})`),m.push(`\xB7 ${g}${b?": "+b:""}`);}for(let d of r){let g=d.description||"";d.defaultValue!==void 0&&(g+=g?` (default: ${d.defaultValue})`:`(default: ${d.defaultValue})`),m.push(`\xB7 --${d.name}${g?": "+g:""}`);}a+=m.join(`
21
21
  `)+`
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
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(()=>(st(),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 a of i){let l=n[a];e+=no(r,a,l);}}console.log(e);}});});var ao,Bt,Jt=f(()=>{k();ao=`# AIP Hooks
24
24
 
25
25
  Automated scripts that run before/after project/task actions.
26
26
 
@@ -200,7 +200,7 @@ 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
- `,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
203
+ `,Bt=p({description:"Hook types, env vars, and patterns",options:z$1.object({}),handler:async()=>{console.log(ao);}});});var $,Vt,po,Wt,Zt=f(()=>{J();P();k();$=Object.keys(S.bin)[0],{LOG:Vt}=c.files,po=`# Quick Start
204
204
 
205
205
  ## New Task/Project
206
206
 
@@ -224,13 +224,14 @@ ${$} task start
224
224
 
225
225
  # 5. Work session
226
226
  # Log progress: ${$} log append "API integration complete"
227
- # Save: outputs/ to deliver, inputs/ for data
227
+ # Save deliverables to outputs/ (e.g. reports, leads, etc.)
228
+ # Save intermediate/raw (lower value) data to inputs/ (e.g. raw API responses, downloads)
228
229
  \`\`\`
229
230
 
230
231
  ## Resuming
231
232
 
232
233
  \`\`\`bash
233
- # Find your tasks (searches all projects)
234
+ # Find your tasks (searches all projects), can pass --project or --search to filter
234
235
  ${$} task list
235
236
 
236
237
  # Navigate to task
@@ -260,10 +261,10 @@ ${$} task current
260
261
 
261
262
  $AIP_HOME/projects/slug/
262
263
  \u251C\u2500\u2500 main.md # Definition + body
263
- \u251C\u2500\u2500 ${Bt} # Log (auto-appended, has key task updates too)
264
+ \u251C\u2500\u2500 ${Vt} # Log (auto-appended, has key task updates too)
264
265
  \u2514\u2500\u2500 tasks/task/
265
266
  \u251C\u2500\u2500 main.md # Task definition + body
266
- \u2514\u2500\u2500 ${Bt} # Updates
267
+ \u2514\u2500\u2500 ${Vt} # Updates
267
268
 
268
269
  **Log format:** TSV with columns: date, time, entityType, slug, action, text
269
270
  **Example:** \`2026-03-30<TAB>14:30:00<TAB>task<TAB>api-integration<TAB>log<TAB>API integration complete\`
@@ -280,7 +281,7 @@ ${$} <noun> --help
280
281
  # All parameters and --options for a command
281
282
  ${$} <noun> <verb> --help
282
283
  \`\`\`
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
284
+ `,Wt=p({description:"Quick start guide for new users",options:z$1.object({}),handler:async()=>{console.log(po);}});});var lo,mo,uo,fo,go,ko,ho,Yt,ht,Y,yt,Qt,Xt=f(()=>{J();P();k();x();lo=Object.values(z).join("|"),{PROJECTS:mo,TASKS:uo,HOOKS:fo,INPUTS:go,OUTPUTS:ko,SCRIPTS:ho}=c.dirs,{MAIN:Yt,LOG:ht}=c.files,Y=Object.keys(S.bin)[0],yt=`# AIP - Project Management Skill
284
285
 
285
286
  Automated project and task creation with proper structure, front-matter, and file organization.
286
287
 
@@ -290,24 +291,24 @@ Streamline creation of new projects and tasks with the correct directory structu
290
291
 
291
292
  ## Quick Start
292
293
 
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
294
+ - New user? Run: \`${Y} help quickstart\`
295
+ - All commands? Run: \`${Y} help usage\`
296
+ - Just for one noun? Run: \`${Y} help usage <noun>\` (e.g., \`${Y} help usage task\`)
297
+ - Need EVERYTHING (big)? Run: \`${Y} help api\` - Shows all commands with full option details
297
298
 
298
299
  ## File Structure Overview
299
300
 
300
301
  \`\`\`
301
- $AIP_HOME/${so}/{project-slug}/
302
- \u251C\u2500\u2500 ${Wt} # Goals + body (YAML frontmatter + markdown content)
302
+ $AIP_HOME/${mo}/{project-slug}/
303
+ \u251C\u2500\u2500 ${Yt} # Goals + body (YAML frontmatter + markdown content)
303
304
  \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}/
305
+ \u251C\u2500\u2500 ${fo}/ # pre|post-{create,start,update,complete}.*
306
+ \u251C\u2500\u2500 ${go}/ # Intermediate/raw data (e.g. API responses, downloads)
307
+ \u251C\u2500\u2500 ${ko}/ # Deliverables (e.g. reports, leads, etc.)
308
+ \u251C\u2500\u2500 ${ho}/ # Automation
309
+ \u2514\u2500\u2500 ${uo}/
309
310
  \u2514\u2500\u2500 {task-slug}/
310
- \u251C\u2500\u2500 ${Wt} # Task definition + body
311
+ \u251C\u2500\u2500 ${Yt} # Task definition + body
311
312
  \u251C\u2500\u2500 ${ht} # Activity log
312
313
  \u2514\u2500\u2500 ... (same structure)
313
314
  \`\`\`
@@ -319,7 +320,7 @@ $AIP_HOME/${so}/{project-slug}/
319
320
  name: Clear Title
320
321
  description: One-line summary
321
322
  assignee: agent-name
322
- status: ${ro}
323
+ status: ${lo}
323
324
  created: YYYY-MM-DD
324
325
  ---
325
326
  \`\`\`
@@ -336,7 +337,7 @@ Markdown content after frontmatter. See \`aip help quickstart\` for examples of
336
337
  ## For Agents
337
338
 
338
339
  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(`---
340
+ `,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(`---
340
341
  name: ${e}
341
342
  description: ${S.description}
342
343
  ---`),console.log(),console.log(yt);return}if(t.mode==="hermes"){console.log(`---
@@ -348,14 +349,14 @@ license: ${S.license}
348
349
  metadata:
349
350
  hermes:
350
351
  tags: [${S.keywords.join(", ")}]
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} */
352
+ ---`),console.log(),console.log(yt);return}}});});var te,ee=f(()=>{J();k();y();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(()=>(st(),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(`
353
+ `)),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,yo,h,E=f(()=>{P();y();Tt=s.joinHome(c.dirs.PROJECTS),yo={getProjectFromPwd(t=process.cwd()){let e=nt.relative(Tt,t);if(!e||e.startsWith(".."))return null;let o=e.split(nt.sep).filter(Boolean);return o.length===0?null:o[0]},getTaskFromPwd(t=process.cwd()){let e=nt.relative(Tt,t);if(!e||e.startsWith(".."))return null;let o=e.split(nt.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: ${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(`
354
+ `)},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=yo;});var oe,re=f(()=>{k();y();E();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 g;if(r==="ts")g=`#!/usr/bin/env tsx
355
+ /** ${t} hook for ${a} */
355
356
 
356
357
  import { env } from 'node:process'
357
358
 
358
- console.log('Running ${t} hook for ${c}')
359
+ console.log('Running ${t} hook for ${a}')
359
360
  console.log('PROJECT_SLUG:', env.PROJECT_SLUG)
360
361
  if (env.TASK_SLUG) {
361
362
  console.log('TASK_SLUG:', env.TASK_SLUG)
@@ -364,9 +365,9 @@ if (env.TASK_SLUG) {
364
365
  // Exit with non-zero to prevent action (for pre-hooks)
365
366
  // process.exit(1)
366
367
  `;else if(r==="js")g=`#!/usr/bin/env node
367
- /** ${t} hook for ${c} */
368
+ /** ${t} hook for ${a} */
368
369
 
369
- console.log('Running ${t} hook for ${c}')
370
+ console.log('Running ${t} hook for ${a}')
370
371
  console.log('PROJECT_SLUG:', process.env.PROJECT_SLUG)
371
372
  if (process.env.TASK_SLUG) {
372
373
  console.log('TASK_SLUG:', process.env.TASK_SLUG)
@@ -375,9 +376,9 @@ if (process.env.TASK_SLUG) {
375
376
  // Exit with non-zero to prevent action (for pre-hooks)
376
377
  // process.exit(1)
377
378
  `;else if(r==="sh")g=`#!/bin/bash
378
- # ${t} hook for ${c}
379
+ # ${t} hook for ${a}
379
380
 
380
- echo "Running ${t} hook for ${c}"
381
+ echo "Running ${t} hook for ${a}"
381
382
  echo "PROJECT_SLUG: $PROJECT_SLUG"
382
383
  if [ -n "$TASK_SLUG" ]; then
383
384
  echo "TASK_SLUG: $TASK_SLUG"
@@ -386,18 +387,17 @@ fi
386
387
  # Exit with non-zero to prevent action (for pre-hooks)
387
388
  # exit 1
388
389
  `;else if(r==="py")g=`#!/usr/bin/env python3
389
- """${t} hook for ${c}"""
390
+ """${t} hook for ${a}"""
390
391
 
391
392
  import os
392
393
 
393
- print(f"Running ${t} hook for ${c}")
394
+ print(f"Running ${t} hook for ${a}")
394
395
  print(f"PROJECT_SLUG: {os.environ.get('PROJECT_SLUG')}")
395
396
  if os.environ.get('TASK_SLUG'):
396
397
  print(f"TASK_SLUG: {os.environ.get('TASK_SLUG')}")
397
398
 
398
399
  # Exit with non-zero to prevent action (for pre-hooks)
399
400
  # sys.exit(1)
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};
401
+ `;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 wo,v,B=f(()=>{P();y();wo={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:o,shell:false});m.on("close",(d,g)=>{d===0?l(true):(console.error(`Hook ${nt.basename(t)} failed (code=${d??g})`),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))}},v=wo;});var se,ne=f(()=>{k();B();E();P();se=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 v.runHooks(o,t,n)||(console.error(`Hook ${t} failed`),process.exit(1)),console.log(`Hook ${t} completed successfully`);}});});var bo,w,F=f(()=>{P();E();y();bo={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}
402
+ `},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);}},w=bo;});var ie,ae=f(()=>{P();E();k();y();F();ie=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 w.append(l,"task",a,"log",o),console.log(`Appended to task ${a} log.tsv`);}else await w.append(i,"project",n,"log",o),console.log(`Appended to project ${n} log.tsv`);}});});var ce,pe=f(()=>{P();E();k();y();F();ce=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 w.read(a);console.log(l||`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 le,de=f(()=>{k();y();F();x();le=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);await u.createProject(i,{name:t,description:e,status:o,assignee:r,created:new Date().toISOString()},n),await w.append(a,"project",i,"created",`${t} > status is ${o}`),console.log(`Project created: ${i}. Path: ${a}`);}});});var me,ue=f(()=>{k();E();me=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 ge,ke=f(()=>{k();x();ge=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,status:n.status,assignee:n.assignee}));}if(o.length===0)return console.log("No projects found");console.log("Projects:");for(let r of o)console.log(`- ${r.slug}: ${r.status||""} ${r.assignee||""}`);}});});var he,ye=f(()=>{k();x();he=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 je,Te=f(()=>{P();E();k();B();y();x();F();je=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 v.runHooks(l,"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(a,g);let b=Object.entries(g).map(([D,C])=>`${D}=${C}`).join(", ");await w.append(l,"project",a,"updated",b);}i!==void 0&&(await u.updateBody(m,i),await w.append(l,"project",a,"updated",`body replaced (${i.length} chars)`)),await v.runHooks(l,"post-update",{action:"post-update",entityType:"project"}),console.log(`Project ${a} updated`);}});});var we,be=f(()=>{P();k();H();y();we=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}
403
+ Expected at: ${o}`);await s.logFiles(o);}});});var Pe,Se=f(()=>{k();B();y();x();F();Pe=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 v.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 w.append(m,"task",a,"created",e),await w.append(l,"task",a,"created",`${a} > status is ${n}`),await v.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 xe,$e=f(()=>{k();E();xe=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 ve,Ae=f(()=>{E();k();x();ve=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 Ee,Oe=f(()=>{k();y();x();Ee=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, case-insensitive, multi-part AND, any order)")}),handler:async({project:t,statuses:e,assignee:o,all:r,search:n})=>{if(e&&e.length>0){for(let d of e)if(!rt.includes(d))throw new Error(`Invalid status: ${d}. Valid values: ${rt.join(", ")}`)}let i;e&&e.length>0?i=e:r?i=rt:i=Et;let a=t?[t]:await u.listProjects(),l={};await s.promiseEach(a,async d=>{let g=await u.listTasks(d),b=[];await s.promiseEach(g,async D=>{let C=await u.getTask(d,D);C&&(i.length>0&&!i.includes(C.status||"")||o&&C.assignee!==o||s.matchesSearch(D,n)&&b.push({slug:D,description:C.description}));}),b.length>0&&(l[d]=b.sort((D,C)=>D.slug.localeCompare(C.slug)));});let m=Object.keys(l).sort();if(m.length===0)return console.log("No tasks found");for(let d of m){console.log(`${d}:`);for(let g of l[d])console.log(`- ${g.slug}: ${g.description||""}`);}}});});var De,Ce=f(()=>{k();x();De=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 lt,Pt=f(()=>{P();E();k();B();y();x();F();lt=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),g=u.getTaskDir(d,m),b=u.getProjectDir(d),D=s.join(g,c.files.MAIN);if(!await v.runHooksForContext(b,g,"pre-update",{action:"pre-update",entityType:"task",project:d,task:m}))throw new Error("Pre-update hook failed, aborting update");let O={};if(o&&(O.name=o),r&&(O.description=r),n&&(O.status=n),i&&(O.assignee=i),Object.keys(O).length===0&&!a){console.log("No updates provided");return}if(Object.keys(O).length>0){await u.updateTask(d,m,O);let _e=Object.entries(O).map(([Ue,He])=>`${Ue}=${He}`).join(", ");await w.append(g,"task",m,"updated",_e);}a!==void 0&&(await u.updateBody(D,a),await w.append(g,"task",m,"updated",`body replaced (${a.length} chars)`)),O.status&&await w.append(b,"task",m,"updated",`status to ${O.status}`),await v.runHooksForContext(u.getProjectDir(d),g,"post-update",{action:"post-update",entityType:"task",project:d,task:m}),console.log(`Task ${m} updated`);}});});var Re,Ne=f(()=>{E();k();B();x();Pt();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(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),a=u.getProjectDir(i),l=u.getTaskDir(i,n);if(!await v.runHooksForContext(a,l,"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 lt.handler({project:i,task:n,status:"in-progress"}),o&&await u.ingestTask(i,n),await v.runHooksForContext(a,l,"post-start",{action:"post-start",entityType:"task",project:i,task:n});}});});var Ie,Fe=f(()=>{k();y();Ie=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={};Ke(kt,{default:()=>U});var xo,U,st=f(()=>{Ct();Nt();Ft();_t();Ht();zt();Jt();Zt();Xt();ee();re();ne();ae();pe();de();ue();ke();ye();Te();be();Se();$e();Ae();Oe();Ce();Ne();Pt();Fe();xo={agent:{create:Dt,current:Rt,list:It,path:Lt,start:Ut},help:{api:Mt,hooks:Bt,quickstart:Wt,skill:Qt,usage:te},hook:{create:oe,run:se},log:{append:ie,read:ce},project:{create:le,current:me,list:ge,path:he,update:je},skill:{read:we},task:{create:Pe,current:xe,ingest:ve,list:Ee,path:De,start:Re,update:lt},util:{read:Ie}},U=xo;});J();st();y();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 Le(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 Li=Le,_i=U;s.isMain()&&Le(process.argv.slice(2));export{_i as commands,Li as default};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-projects",
3
- "version": "1.6.2",
3
+ "version": "1.7.1",
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",