ai-projects 1.0.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -18,7 +18,7 @@ aip <noun> <verb> [options]
18
18
 
19
19
  ## For Agents
20
20
 
21
- Read `tmp/hermes/AGENTS.md` first.
21
+ Read `$AIP_HOME/AGENTS.md` first.
22
22
 
23
23
  ## License
24
24
 
package/dist/index.d.ts CHANGED
@@ -67,6 +67,11 @@ declare const commands: {
67
67
  }, {
68
68
  [x: string]: any;
69
69
  }>>;
70
+ readonly skill: CommandDef<zod.ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, zod.ZodObject<any, zod.UnknownKeysParam, zod.ZodTypeAny, {
71
+ [x: string]: any;
72
+ }, {
73
+ [x: string]: any;
74
+ }>>;
70
75
  readonly structure: CommandDef<zod.ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, zod.ZodObject<any, zod.UnknownKeysParam, zod.ZodTypeAny, {
71
76
  [x: string]: any;
72
77
  }, {
package/dist/index.js CHANGED
@@ -1,26 +1,26 @@
1
1
  #!/usr/bin/env node
2
- import {z}from'zod';import {parser}from'zod-opts';import {exec,spawn}from'child_process';import _ from'fs/promises';import j from'lodash';import H from'moment';import R from'path';import {fileURLToPath}from'url';import {inspect}from'util';import De from'dotenv';import ve from'fs';import Oe from'os';import ut from'yaml';var Te=Object.defineProperty;var g=(t,e)=>()=>(t&&(e=t(t=0)),e);var be=(t,e)=>{for(var o in e)Te(t,o,{get:e[o],enumerable:true});};function p(t){let{description:e,options:o=z.object({}),args:r,handler:n}=t,i=o.shape,a={};for(let[l,u]of Object.entries(i))a[l]={type:u};let m=parser().options(a);if(r){let l=r.shape,u=Object.entries(l).map(([h,k])=>({name:h,type:k}));u.length>0&&(m=m.args(u));}return e&&(m=m.description(e)),{description:e,options:o,args:r,parser:m,handler:n,cli:l=>n(m.parse(l))}}var f=g(()=>{});var T,s,w=g(()=>{T={REPO:fileURLToPath(import.meta.url.replace(/\/(dist|src)\/.*/,"/")),join:(...t)=>R.join(...t),onRepo:(...t)=>T.join(T.REPO,...t),async ensureDir(t){await _.mkdir(t,{recursive:true});},async write(t,e){await T.ensureDir(R.dirname(t)),await _.writeFile(t,e,"utf8");},async read(t){return _.readFile(t,"utf8")},async readRepo(...t){return T.read(T.onRepo(...t))},async readMany(...t){return (await Promise.all(t.map(async o=>{if(await T.fileExists(o)){let r=await T.read(o);return `# ${o}
2
+ import {z as z$1}from'zod';import {parser}from'zod-opts';import {exec,spawn}from'child_process';import H from'fs/promises';import j from'lodash';import M from'moment';import N from'path';import {fileURLToPath}from'url';import {inspect}from'util';import Oe from'dotenv';import $e from'fs';import Ie from'os';import gt from'yaml';var be=Object.defineProperty;var g=(t,e)=>()=>(t&&(e=t(t=0)),e);var Pe=(t,e)=>{for(var o in e)be(t,o,{get:e[o],enumerable:true});};var _,ot=g(()=>{_={name:"ai-projects",version:"1.1.0",type:"module",description:"AI project management CLI - create and manage projects, tasks, 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"},keywords:["ai","project-management","task-management","cli","hermes-agent","autonomous-agents"],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,u]of Object.entries(i))a[m]={type:u};let l=parser().options(a);if(r){let m=r.shape,u=Object.entries(m).map(([y,k])=>({name:y,type:k}));u.length>0&&(l=l.args(u));}return e&&(l=l.description(e)),{description:e,options:o,args:r,parser:l,handler:n,cli:m=>n(l.parse(m))}}var f=g(()=>{});var w,s,b=g(()=>{w={REPO:fileURLToPath(import.meta.url.replace(/\/(dist|src)\/.*/,"/")),join:(...t)=>N.join(...t),onRepo:(...t)=>w.join(w.REPO,...t),async ensureDir(t){await H.mkdir(t,{recursive:true});},async write(t,e){await w.ensureDir(N.dirname(t)),await H.writeFile(t,e,"utf8");},async read(t){return H.readFile(t,"utf8")},async readRepo(...t){return w.read(w.onRepo(...t))},async readMany(...t){return (await Promise.all(t.map(async o=>{if(await w.fileExists(o)){let r=await w.read(o);return `# ${o}
3
3
 
4
- ${r}`}return ""}))).filter(Boolean)},async logFiles(...t){let e=await T.readMany(...t);console.log(e.join(`
4
+ ${r}`}return ""}))).filter(Boolean)},async logFiles(...t){let e=await w.readMany(...t);console.log(e.join(`
5
5
 
6
6
  ---
7
7
 
8
- `));},dumpCommandMapLines(t,e){let o=e?j.pick(t,e):t,r=[];for(let[n,i]of T.entriesOf(o))r.push(`${n} {${Object.keys(i).join("|")}}`);return r},async fileExists(t){try{return await _.access(t),!0}catch{return false}},async listDir(t){try{return await _.readdir(t)}catch{return []}},async spawn(t,e=[],o){return new Promise((r,n)=>{let i=spawn(t,e,{stdio:["ignore","pipe","pipe"],...o}),a="",m="";i.stdout?.on("data",l=>{a+=l;}),i.stderr?.on("data",l=>{m+=l;}),i.on("close",l=>r({stdout:a,stderr:m,code:l})),i.on("error",n);})},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)=>j.isArray(t)?t.map(o=>T.omitByDeep(o,e)):j.isPlainObject(t)?j.mapValues(j.omitBy(t,e),o=>T.omitByDeep(o,e)):t,omitNilsDeep:t=>T.omitByDeep(t,j.isNil),omitUndefinedsDeep:t=>T.omitByDeep(t,j.isUndefined),cloneDeep:t=>j.cloneDeep(t),int:t=>Number.parseInt(t,10),keysOf:t=>Object.keys(t),entriesOf:t=>Object.entries(t),isKeyOf:(t,e)=>!j.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(j.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 j.extend(e,t)},isPromise:t=>j.isObject(t)&&"catch"in t,delay:t=>{let e=j.isObject(t)?T.toMS(t):t;return new Promise(o=>setTimeout(o,e))},promiseMap:(t,e)=>Promise.all(t.map(e)),memoize:t=>j.memoize(t,T.memoizeKey),toMS:t=>H.duration(t).asMilliseconds(),toSecs:t=>H.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(j.isObject(i)){if(r.has(i))return "[Circular]";r.add(i);}return j.isFunction(e)?e(n,i):i},o)},dump:t=>T.oneLine(T.stringify(t)),compactWhitespace:t=>t.replace(/\\n/g,`
8
+ `));},dumpCommandMapLines(t,e){let o=e?j.pick(t,e):t,r=[];for(let[n,i]of w.entriesOf(o))r.push(`${n} {${Object.keys(i).join("|")}}`);return r},async fileExists(t){try{return await H.access(t),!0}catch{return false}},async listDir(t){try{return await H.readdir(t)}catch{return []}},async spawn(t,e=[],o){return new Promise((r,n)=>{let i=spawn(t,e,{stdio:["ignore","pipe","pipe"],...o}),a="",l="";i.stdout?.on("data",m=>{a+=m;}),i.stderr?.on("data",m=>{l+=m;}),i.on("close",m=>r({stdout:a,stderr:l,code:m})),i.on("error",n);})},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)=>j.isArray(t)?t.map(o=>w.omitByDeep(o,e)):j.isPlainObject(t)?j.mapValues(j.omitBy(t,e),o=>w.omitByDeep(o,e)):t,omitNilsDeep:t=>w.omitByDeep(t,j.isNil),omitUndefinedsDeep:t=>w.omitByDeep(t,j.isUndefined),cloneDeep:t=>j.cloneDeep(t),int:t=>Number.parseInt(t,10),keysOf:t=>Object.keys(t),entriesOf:t=>Object.entries(t),isKeyOf:(t,e)=>!j.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(j.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 j.extend(e,t)},isPromise:t=>j.isObject(t)&&"catch"in t,delay:t=>{let e=j.isObject(t)?w.toMS(t):t;return new Promise(o=>setTimeout(o,e))},promiseMap:(t,e)=>Promise.all(t.map(e)),memoize:t=>j.memoize(t,w.memoizeKey),toMS:t=>M.duration(t).asMilliseconds(),toSecs:t=>M.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(j.isObject(i)){if(r.has(i))return "[Circular]";r.add(i);}return j.isFunction(e)?e(n,i):i},o)},dump:t=>w.oneLine(w.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)=>j.includes(j.toLower(t||""),j.toLower(e||"")),elapsed:(t,e=Date.now())=>H.duration(H(e).diff(t||0)),iso:t=>H.utc(t).toISOString(),isoDate:t=>T.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=T;});var c,E=g(()=>{c={dirs:{PROJECTS:"projects",SKILLS:"skills",AGENTS:"agents",TASKS:"tasks",INPUTS:"inputs",OUTPUTS:"outputs",HOOKS:"hooks"},files:{MAIN:"main.md",STATUS:"status.md",LOG:"audit.log",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"]};});function Ne(t,e){return process.env[t]??e}var Ce,dt,D,Re,y,O=g(()=>{Ce=()=>{let t=fileURLToPath(import.meta.url),e=R.dirname(t),o=10;for(let r=0;r<o;r++)try{if(ve.existsSync(R.join(e,"package.json")))return e;let n=R.dirname(e);if(n===e)break;e=n;}catch{break}return process.cwd()};dt=Ce(),D=process.env.AIP_HOME;D||(De.config({path:R.join(dt,".env"),quiet:true}),D=process.env.AIP_HOME);D?.startsWith("~")&&(D=R.join(Oe.homedir(),D.slice(1)));(!D||!R.isAbsolute(D))&&(console.error("AIP_HOME env var must be set and be an absolute path",D),process.exit(1));Re={ROOT:dt,AIP_HOME:D,NODE_ENV:Ne("NODE_ENV","development")},y=Re;});var gt,L,et,M,ft=g(()=>{w();gt=t=>{let e=t.trim();if(!e.startsWith("---"))return null;let o=e.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);return o?{frontmatter:ut.parse(o[1]),content:o[2].trim()}:null},L=async(t,e,o="")=>{let n=`---
13
- ${ut.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)=>j.includes(j.toLower(t||""),j.toLower(e||"")),elapsed:(t,e=Date.now())=>M.duration(M(e).diff(t||0)),iso:t=>M.utc(t).toISOString(),isoDate:t=>w.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=w;});var c,A=g(()=>{c={dirs:{PROJECTS:"projects",SKILLS:"skills",AGENTS:"agents",TASKS:"tasks",INPUTS:"inputs",OUTPUTS:"outputs",HOOKS:"hooks"},files:{MAIN:"main.md",STATUS:"status.md",LOG:"audit.log",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"]};});function Fe(t,e){return process.env[t]??e}var Re,ut,v,Ue,h,C=g(()=>{Re=()=>{let t=fileURLToPath(import.meta.url),e=N.dirname(t),o=10;for(let r=0;r<o;r++)try{if($e.existsSync(N.join(e,"package.json")))return e;let n=N.dirname(e);if(n===e)break;e=n;}catch{break}return process.cwd()};ut=Re(),v=process.env.AIP_HOME;v||(Oe.config({path:N.join(ut,".env"),quiet:true}),v=process.env.AIP_HOME);v?.startsWith("~")&&(v=N.join(Ie.homedir(),v.slice(1)));(!v||!N.isAbsolute(v))&&(console.error("AIP_HOME env var must be set and be an absolute path",v||""),process.exit(1));Ue={ROOT:ut,AIP_HOME:v,NODE_ENV:Fe("NODE_ENV","development")},h=Ue;});var ft,L,rt,z,ht=g(()=>{b();ft=t=>{let e=t.trim();if(!e.startsWith("---"))return null;let o=e.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);return o?{frontmatter:gt.parse(o[1]),content:o[2].trim()}:null},L=async(t,e,o="")=>{let n=`---
13
+ ${gt.stringify(e).trim()}
14
14
  ---
15
15
 
16
16
  ${o}`.trim();await s.write(t,n+`
17
- `);},et=async(t,e)=>{let o=await s.read(t),r=gt(o);if(!r)throw new Error(`No frontmatter found in ${t}`);let n={...r.frontmatter,...e};return await L(t,n,r.content),n},M=async t=>{let e=await s.read(t),o=gt(e);if(!o)throw new Error(`No frontmatter found in ${t}`);return o.frontmatter};});var Ie,d,P=g(()=>{E();O();ft();w();Ie={getProjectDir(t){return s.join(y.AIP_HOME,c.dirs.PROJECTS,t)},getTaskDir(t,e){return s.join(this.getProjectDir(t),c.dirs.TASKS,e)},getAgentDir(t){return s.join(y.AIP_HOME,c.dirs.AGENTS,t)},async listProjects(){let t=s.join(y.AIP_HOME,c.dirs.PROJECTS),e=await s.listDir(t),o=[];for(let r of e){let n=this.getProjectDir(r);await s.fileExists(n)&&r!==c.dirs.AGENTS&&o.push(r);}return o},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(y.AIP_HOME,c.dirs.AGENTS);return await s.fileExists(t)?await s.listDir(t):[]},async createProject(t,e){let o=this.getProjectDir(t);return await s.ensureDir(o),await s.ensureDir(s.join(o,c.dirs.TASKS)),await s.ensureDir(s.join(o,c.dirs.HOOKS)),await L(s.join(o,c.files.MAIN),e),await s.write(s.join(o,c.files.STATUS),""),o},async createTask(t,e,o){let r=this.getTaskDir(t,e);return await s.ensureDir(r),await s.ensureDir(s.join(r,c.dirs.HOOKS)),await L(s.join(r,c.files.MAIN),o),await s.write(s.join(r,c.files.STATUS),""),r},async createAgent(t,e){let o=this.getAgentDir(t);return await s.ensureDir(o),await L(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 M(e):null},async getTask(t,e){let o=s.join(this.getTaskDir(t,e),c.files.MAIN);return await s.fileExists(o)?await M(o):null},async getAgent(t){let e=s.join(this.getAgentDir(t),c.files.MAIN);return await s.fileExists(e)?await M(e):null},async updateProject(t,e){let o=s.join(this.getProjectDir(t),c.files.MAIN);return await et(o,e)},async updateTask(t,e,o){let r=s.join(this.getTaskDir(t,e),c.files.MAIN);if((await M(r))?.status==="ongoing")throw new Error("Cannot update ongoing task. Should be done by user or update manually");return await et(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.STATUS)];await s.logFiles(...n);},async ingestProject(t){let e=this.getProjectDir(t),o=[s.join(e,c.files.MAIN),s.join(e,c.files.STATUS)],r=await this.listTasks(t);for(let n of r)o.push(s.join(this.getTaskDir(t,n),c.files.MAIN));await s.logFiles(...o);},async ingestFiles(t){await s.logFiles(...t);}},d=Ie;});var yt,kt=g(()=>{f();w();P();yt=p({options:z.object({description:z.string().describe("Agent description"),status:z.string().default("active").describe("Initial status")}),args:z.object({name:z.string().describe("Agent name")}),handler:async({name:t,description:e,status:o})=>{let r=s.slugify(t);await d.createAgent(r,{name:t,description:e,status:o,created:new Date().toISOString()}),console.log(`Agent created: ${r}`),console.log(` Path: ${d.getAgentDir(r)}`);}});});var ht,jt=g(()=>{f();ht=p({options:z.object({}),handler:async()=>{let t=process.env.CURRENT_AGENT;t||(console.error("CURRENT_AGENT not set"),process.exit(1)),console.log(t);}});});var Tt,bt=g(()=>{f();P();Tt=p({options:z.object({}),handler:async()=>{let t=await d.listAgents(),e=[];for(let o of t){let r=await d.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 wt,Pt=g(()=>{E();f();O();w();wt=p({description:"Output agent directory path (for cd)",options:z.object({}),args:z.object({name:z.string().describe("Agent name (directory name)")}),handler:async({name:t})=>{let e=s.join(y.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 xt,St=g(()=>{E();f();O();w();xt=p({description:"Start an agent: read SOUL.md and AGENTS.md content",options:z.object({}),args:z.object({name:z.string().describe("Agent name (directory name)")}),handler:async({name:t})=>{let e=s.join(y.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 Et,At,He,Dt,vt=g(()=>{f();Et=t=>{let e=t.shape,o=[];for(let[r,n]of Object.entries(e)){let i=n._def,a="unknown",m,l;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=At(i.innerType):i.typeName==="ZodDefault"&&(a=At(i.innerType),l=i.defaultValue()),i.description&&(m=i.description);let u=i.typeName!=="ZodOptional"&&i.typeName!=="ZodDefault";o.push({name:r,type:a,required:u,description:m,defaultValue:l});}return o},At=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"},He=(t,e,o)=>{let r=Et(o.options),n=o.args?Et(o.args):[],i=o.description,a=`\`${t} ${e}\``;if(i&&(a+=`: ${i}`),a+=`
20
- `,r.length>0||n.length>0){let l=[];for(let u of n){let h=u.required?`<${u.name}>`:`[${u.name}]`,k=u.description||"";u.defaultValue!==void 0&&(k+=k?` (default: ${u.defaultValue})`:`(default: ${u.defaultValue})`),l.push(`\xB7 ${h}${k?": "+k:""}`);}for(let u of r){let h=u.description||"";u.defaultValue!==void 0&&(h+=h?` (default: ${u.defaultValue})`:`(default: ${u.defaultValue})`),l.push(`\xB7 --${u.name}${h?": "+h:""}`);}a+=l.join(`
17
+ `);},rt=async(t,e)=>{let o=await s.read(t),r=ft(o);if(!r)throw new Error(`No frontmatter found in ${t}`);let n={...r.frontmatter,...e};return await L(t,n,r.content),n},z=async t=>{let e=await s.read(t),o=ft(e);if(!o)throw new Error(`No frontmatter found in ${t}`);return o.frontmatter};});var _e,d,P=g(()=>{A();C();ht();b();_e={getProjectDir(t){return s.join(h.AIP_HOME,c.dirs.PROJECTS,t)},getTaskDir(t,e){return s.join(this.getProjectDir(t),c.dirs.TASKS,e)},getAgentDir(t){return s.join(h.AIP_HOME,c.dirs.AGENTS,t)},async listProjects(){let t=s.join(h.AIP_HOME,c.dirs.PROJECTS),e=await s.listDir(t),o=[];for(let r of e){let n=this.getProjectDir(r);await s.fileExists(n)&&r!==c.dirs.AGENTS&&o.push(r);}return o},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(h.AIP_HOME,c.dirs.AGENTS);return await s.fileExists(t)?await s.listDir(t):[]},async createProject(t,e){let o=this.getProjectDir(t);return await s.ensureDir(o),await s.ensureDir(s.join(o,c.dirs.TASKS)),await s.ensureDir(s.join(o,c.dirs.HOOKS)),await L(s.join(o,c.files.MAIN),e),await s.write(s.join(o,c.files.STATUS),""),o},async createTask(t,e,o){let r=this.getTaskDir(t,e);return await s.ensureDir(r),await s.ensureDir(s.join(r,c.dirs.HOOKS)),await L(s.join(r,c.files.MAIN),o),await s.write(s.join(r,c.files.STATUS),""),r},async createAgent(t,e){let o=this.getAgentDir(t);return await s.ensureDir(o),await L(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 z(e):null},async getTask(t,e){let o=s.join(this.getTaskDir(t,e),c.files.MAIN);return await s.fileExists(o)?await z(o):null},async getAgent(t){let e=s.join(this.getAgentDir(t),c.files.MAIN);return await s.fileExists(e)?await z(e):null},async updateProject(t,e){let o=s.join(this.getProjectDir(t),c.files.MAIN);return await rt(o,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 rt(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.STATUS)];await s.logFiles(...n);},async ingestProject(t){let e=this.getProjectDir(t),o=[s.join(e,c.files.MAIN),s.join(e,c.files.STATUS)],r=await this.listTasks(t);for(let n of r)o.push(s.join(this.getTaskDir(t,n),c.files.MAIN));await s.logFiles(...o);},async ingestFiles(t){await s.logFiles(...t);}},d=_e;});var kt,yt=g(()=>{f();b();P();kt=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 d.createAgent(r,{name:t,description:e,status:o,created:new Date().toISOString()}),console.log(`Agent created: ${r}`),console.log(` Path: ${d.getAgentDir(r)}`);}});});var jt,wt=g(()=>{f();jt=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 Tt,bt=g(()=>{f();P();Tt=p({options:z$1.object({}),handler:async()=>{let t=await d.listAgents(),e=[];for(let o of t){let r=await d.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 Pt,xt=g(()=>{A();f();C();b();Pt=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(h.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 St,At=g(()=>{A();f();C();b();St=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(h.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 Et,vt,ze,Dt,Ct=g(()=>{f();Et=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=vt(i.innerType):i.typeName==="ZodDefault"&&(a=vt(i.innerType),m=i.defaultValue()),i.description&&(l=i.description);let u=i.typeName!=="ZodOptional"&&i.typeName!=="ZodDefault";o.push({name:r,type:a,required:u,description:l,defaultValue:m});}return o},vt=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"},ze=(t,e,o)=>{let r=Et(o.options),n=o.args?Et(o.args):[],i=o.description,a=`\`${t} ${e}\``;if(i&&(a+=`: ${i}`),a+=`
20
+ `,r.length>0||n.length>0){let m=[];for(let u of n){let y=u.required?`<${u.name}>`:`[${u.name}]`,k=u.description||"";u.defaultValue!==void 0&&(k+=k?` (default: ${u.defaultValue})`:`(default: ${u.defaultValue})`),m.push(`\xB7 ${y}${k?": "+k:""}`);}for(let u of r){let y=u.description||"";u.defaultValue!==void 0&&(y+=y?` (default: ${u.defaultValue})`:`(default: ${u.defaultValue})`),m.push(`\xB7 --${u.name}${y?": "+y:""}`);}a+=m.join(`
21
21
  `)+`
22
22
  `;}return a+=`
23
- `,a},Dt=p({description:"Print generated CLI reference from command schemas",options:z.object({}),handler:async()=>{let{default:t}=await Promise.resolve().then(()=>(J(),st)),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 m=n[a];e+=He(r,a,m);}}console.log(e);}});});var Me,Ot,$t=g(()=>{f();Me=`# AIP Hooks
23
+ `,a},Dt=p({description:"Print generated CLI reference from command schemas",options:z$1.object({}),handler:async()=>{let{default:t}=await Promise.resolve().then(()=>(J(),it)),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+=ze(r,a,l);}}console.log(e);}});});var We,Ot,$t=g(()=>{f();We=`# AIP Hooks
24
24
 
25
25
  Automated scripts that run before/after project/task actions.
26
26
 
@@ -41,16 +41,31 @@ Automated scripts that run before/after project/task actions.
41
41
  ## File Location
42
42
 
43
43
  \`\`\`
44
- tmp/hermes/projects/{project}/hooks/
44
+ $AIP_HOME/projects/{project}/hooks/
45
45
  \u251C\u2500\u2500 pre-complete.ts # Project-level hook
46
46
  \u2514\u2500\u2500 post-create.sh
47
47
 
48
- tmp/hermes/projects/{project}/tasks/{task}/hooks/
48
+ $AIP_HOME/projects/{project}/tasks/{task}/hooks/
49
49
  \u2514\u2500\u2500 pre-update.py # Task-level hook
50
50
  \`\`\`
51
51
 
52
52
  **Execution order:** Project hooks first, then task hooks.
53
53
 
54
+ ## Validation & Automation
55
+
56
+ Projects can include validation scripts and hooks to enforce folder semantics:
57
+
58
+ - **\`scripts/validate-structure.sh\`** \u2013 Validates folder structure follows conventions
59
+ - Usage: \`./scripts/validate-structure.sh [project|task] [path]\`
60
+ - Checks: required files, hook naming, executable permissions
61
+ - Exit 0 = valid, 1 = errors found
62
+
63
+ - **\`hooks/pre-complete.sh\`** \u2013 Runs before task completion
64
+ - Validates required files exist
65
+ - Checks status.md has completion entry
66
+ - Runs structure validation (warning only)
67
+ - Exit 1 blocks completion
68
+
54
69
  ## Environment Variables
55
70
 
56
71
  Hooks receive these automatic:
@@ -152,7 +167,7 @@ if lock_file.exists():
152
167
 
153
168
  \`\`\`bash
154
169
  # Test hook manually
155
- cd tmp/hermes/projects/my-project
170
+ cd $AIP_HOME/projects/my-project
156
171
  ./hooks/pre-complete.ts
157
172
 
158
173
  # Check environment
@@ -185,14 +200,319 @@ DEBUG=1 aip task update --status done
185
200
  ---
186
201
 
187
202
  *Hooks automate workflow enforcement. Pre-hooks guard quality, post-hooks handle cleanup.*
188
- `,Ot=p({description:"Hook types, env vars, and patterns",options:z.object({}),handler:async()=>{console.log(Me);}});});var ze,Ct,Nt=g(()=>{f();ze=`# AIP Project Structure
203
+ `,Ot=p({description:"Hook types, env vars, and patterns",options:z$1.object({}),handler:async()=>{console.log(We);}});});var Je,It,Nt=g(()=>{f();Je=`# AIP - Project Management Skill
204
+
205
+ Automated project and task creation with proper structure, front-matter, and file organization.
206
+
207
+ ## Purpose
208
+
209
+ Streamline creation of new projects and tasks with the correct directory structure, file templates, and front-matter. Ensures consistency across all autonomous work.
210
+
211
+ ## File Structure
212
+
213
+ Every project follows this structure:
214
+
215
+ \`\`\`
216
+ $AIP_HOME/projects/{project-slug}/
217
+ \u251C\u2500\u2500 main.md # Primary context: goals, objectives, scope, data
218
+ \u251C\u2500\u2500 status.md # Chronological log of status updates
219
+ \u251C\u2500\u2500 hooks/ # pre|post-{create,start,update,complete}.*
220
+ \u251C\u2500\u2500 outputs/ # Deliverables (reports, code, final files)
221
+ \u251C\u2500\u2500 inputs/ # External data (API responses, downloads)
222
+ \u251C\u2500\u2500 scripts/ # Automation (bash/python/js)
223
+ \u2514\u2500\u2500 tasks/
224
+ \u2514\u2500\u2500 {task-slug}/
225
+ \u251C\u2500\u2500 main.md # Task definition with front-matter
226
+ \u251C\u2500\u2500 status.md # Single-line updates per work session
227
+ \u251C\u2500\u2500 hooks/ # Task-level hooks
228
+ \u251C\u2500\u2500 outputs/ # Task-specific deliverables
229
+ \u251C\u2500\u2500 inputs/ # Task-specific data files
230
+ \u2514\u2500\u2500 scripts/ # Task-specific automation
231
+ \`\`\`
232
+
233
+ ## File Purposes
234
+
235
+ ### \`main.md\` - Primary Context (Read First)
236
+ **What goes here:**
237
+ - Project/task objectives and goals
238
+ - Scope and success criteria
239
+ - Background information and context
240
+ - Requirements and constraints
241
+ - Reference information
242
+
243
+ **Front-matter:**
244
+ \`\`\`yaml
245
+ ---
246
+ name: Clear Title
247
+ description: One-line summary for search
248
+ assignee: agent-name
249
+ status: pending|in-progress|ongoing|done|blocked
250
+ created: YYYY-MM-DD
251
+ ---
252
+ \`\`\`
253
+
254
+ **When to read:** Always first, before starting work
255
+
256
+ **When to update:** Only when scope/goals change (rare)
257
+
258
+ ### \`status.md\` - Activity Log (Append Only)
259
+ **What goes here:**
260
+ - **Tasks:** Single-line updates per work session
261
+ \`\`\`markdown
262
+ ### 2026-03-17 14:30 - Started implementation
263
+ \u2705 Completed API integration. Next: testing.
264
+ \`\`\`
265
+ - **Projects:** Packed summary when task completes
266
+ \`\`\`markdown
267
+ ### 2026-03-17 18:30 - Task: apply-optimizations \u2705
268
+ Implemented 7 optimizations (P0+P1). Config improved, fallbacks enabled. Details: tasks/apply-optimizations/
269
+ \`\`\`
270
+
271
+ **Status emojis:** \u{1F504} in-progress | \u2705 done | \u26A0\uFE0F blocked | \u274C failed
272
+
273
+ **When to read:** To understand current state and recent activity
274
+
275
+ **When to update:**
276
+ - **Tasks:** Every work session (append 1 line)
277
+ - **Projects:** When task completes (append 1 packed line)
278
+
279
+ ### \`outputs/\` - Deliverables
280
+ **What goes here:**
281
+ - Final reports and documents
282
+ - Generated code files
283
+ - Processed data
284
+ - Artifacts meant for use outside the project
285
+
286
+ **Examples:**
287
+ - \`outputs/final-report.md\`
288
+ - \`outputs/optimized-config.yaml\`
289
+ - \`outputs/website-code.zip\`
290
+ - \`outputs/database-migration.sql\`
291
+
292
+ **When to write:** When task produces tangible results
293
+
294
+ ### \`inputs/\` - External Data
295
+ **What goes here:**
296
+ - API responses (JSON, XML)
297
+ - Downloaded files (web pages, datasets)
298
+ - Reference documents used in process
299
+ - Raw data before processing
300
+
301
+ **Examples:**
302
+ - \`inputs/api-response-2026-03-17.json\`
303
+ - \`inputs/downloaded-docs.zip\`
304
+ - \`inputs/webpage-scrape.md\`
305
+
306
+ **When to write:** When fetching external data for processing
307
+
308
+ ### \`scripts/\` - Automation
309
+ **What goes here:**
310
+ - Bash scripts for simple automation
311
+ - Python scripts for complex logic
312
+ - JavaScript/TypeScript for tooling
313
+ - Any code that helps complete the task
314
+
315
+ **Language Choice:**
316
+ - **Bash**: Simple file ops, command chaining, system commands
317
+ - **Python**: Data processing, API calls, complex logic
318
+ - **JavaScript/TypeScript**: Web scraping, Node.js tooling
319
+
320
+ **Examples:**
321
+ - \`scripts/deploy.sh\`
322
+ - \`scripts/process-data.py\`
323
+ - \`scripts/scrape-docs.js\`
324
+
325
+ **When to write:** When automation saves time or improves reliability
326
+
327
+ ## Usage
328
+
329
+ ### Create New Project
330
+
331
+ \`\`\`bash
332
+ # Via AIP CLI
333
+ aip project create "optimize-hermes-config" \\
334
+ --description "Analyze and optimize Hermes Agent configuration" \\
335
+ --assignee basic \\
336
+ --priority high
337
+ \`\`\`
338
+
339
+ ### Create New Task in Existing Project
340
+
341
+ \`\`\`bash
342
+ aip task create "optimize-hermes-config" "apply-config-changes" \\
343
+ --description "Implement safe optimizations with backups" \\
344
+ --assignee basic \\
345
+ --priority high
346
+ \`\`\`
347
+
348
+ ### Navigate to Project/Task
349
+
350
+ \`\`\`bash
351
+ cd $(aip project path optimize-hermes-config)
352
+ cd $(aip task path optimize-hermes-config apply-config-changes)
353
+ \`\`\`
354
+
355
+ ### Update Task Status
356
+
357
+ \`\`\`bash
358
+ aip task update optimize-hermes-config apply-config-changes --status done
359
+ aip task update optimize-hermes-config apply-config-changes --summary "Completed implementation"
360
+ \`\`\`
361
+
362
+ ## Work Session Pattern
363
+
364
+ **When working on a task:**
365
+
366
+ 1. **Read Context**
367
+ \`\`\`bash
368
+ cat /state/projects/{project}/main.md
369
+ cat /state/projects/{project}/tasks/{task}/main.md
370
+ cat /state/projects/{project}/tasks/{task}/status.md
371
+ \`\`\`
372
+
373
+ 2. **Do Work**
374
+ - Create scripts in \`scripts/\` if automation helps
375
+ - Save external data to \`inputs/\`
376
+ - Place deliverables in \`outputs/\`
377
+
378
+ 3. **Update Status** (REQUIRED)
379
+ \`\`\`markdown
380
+ ### YYYY-MM-DD HH:MM - Brief description
381
+ \u2705 What was accomplished. Next: what's next.
382
+ \`\`\`
383
+
384
+ 4. **On Task Completion**
385
+ - Update task \`main.md\` status to \`completed\`
386
+ - Append packed summary to project \`status.md\`
387
+ - Ensure all outputs are in \`outputs/\`
388
+
389
+ ## Best Practices
390
+
391
+ ### Status Updates
392
+
393
+ **DO:**
394
+ \`\`\`markdown
395
+ ### 2026-03-17 14:30 - API integration
396
+ \u2705 Completed REST API integration with error handling. Next: write tests.
397
+ \`\`\`
398
+
399
+ **DON'T:**
400
+ \`\`\`markdown
401
+ ### 2026-03-17 14:30
402
+ So today I worked on the API integration and it took quite a while because there were some issues with the authentication but I managed to figure it out and now it's working properly. I think the next step should be to write some tests to make sure everything keeps working.
403
+ \`\`\`
404
+
405
+ **Use status emojis:** \u{1F504} in-progress | \u2705 done | \u26A0\uFE0F blocked | \u274C failed
406
+
407
+ ### File Organization
408
+
409
+ **DO:**
410
+ - Keep \`main.md\` focused on goals and context (update rarely)
411
+ - Append to \`status.md\` chronologically (single lines)
412
+ - Place final deliverables in \`outputs/\`
413
+ - Store external data in \`inputs/\`
414
+ - Create scripts only when they save time
415
+
416
+ **DON'T:**
417
+ - Put status updates in \`main.md\`
418
+ - Write long paragraphs in \`status.md\`
419
+ - Mix inputs and outputs
420
+ - Create scripts for one-time simple tasks
421
+
422
+ ### Front-matter
423
+
424
+ **Always include:**
425
+ - \`name\`: Clear, searchable title
426
+ - \`description\`: One-line summary (for search and listings)
427
+ - \`assignee\`: Agent name who should execute
428
+ - \`priority\`: \`low\`, \`medium\`, or \`high\`
429
+ - \`status\`: \`pending\`, \`in-progress\`, \`ongoing\`, \`done\`, or \`blocked\`
430
+ - \`created\`: Date in YYYY-MM-DD format
431
+
432
+ ## Task Lifecycle Commands
433
+
434
+ - \`task start\` - Sets status to \`in-progress\`, outputs cd command and env vars
435
+ - \`task update --status done\` - Marks task as complete
436
+ - \`task update --status ongoing\` - Marks task as ongoing/recurring (won't be auto-completed)
437
+
438
+ All status changes go through \`task update\`, which runs pre-update/post-update hooks.
439
+
440
+ ## Examples
441
+
442
+ ### Example Project: Website Redesign
443
+
444
+ \`\`\`
445
+ $AIP_HOME/projects/website-redesign/
446
+ \u251C\u2500\u2500 main.md
447
+ \u2502 ---
448
+ \u2502 name: Website Redesign
449
+ \u2502 description: Modernize company website with new branding
450
+ \u2502 assignee: boss
451
+ \u2502 priority: high
452
+ \u2502 status: in-progress
453
+ \u2502 created: 2026-03-17
454
+ \u2502 ---
455
+ \u2502 ## Objective
456
+ \u2502 Redesign company website with new branding guidelines...
457
+ \u2502
458
+ \u251C\u2500\u2500 status.md
459
+ \u2502 # Status: Website Redesign
460
+ \u2502 ### 2026-03-17 16:00 - Task: gather-requirements \u2705
461
+ \u2502 Collected stakeholder requirements, analyzed competitors. Details: tasks/gather-requirements/
462
+ \u2502
463
+ \u251C\u2500\u2500 hooks/
464
+ \u2502 \u2514\u2500\u2500 pre-complete.sh # Project-level validation
465
+ \u2502
466
+ \u251C\u2500\u2500 tasks/
467
+ \u2502 \u2514\u2500\u2500 gather-requirements/
468
+ \u2502 \u251C\u2500\u2500 main.md (assignee: basic, priority: high, status: done)
469
+ \u2502 \u251C\u2500\u2500 status.md
470
+ \u2502 \u2502 ### 2026-03-17 14:00 - Started research
471
+ \u2502 \u2502 \u{1F504} Analyzing competitor websites.
472
+ \u2502 \u2502 ### 2026-03-17 16:00 - Completed analysis
473
+ \u2502 \u2502 \u2705 Documented 15 requirements. Output: outputs/requirements.md
474
+ \u2502 \u251C\u2500\u2500 hooks/
475
+ \u2502 \u2502 \u2514\u2500\u2500 pre-complete.sh # Task-level validation
476
+ \u2502 \u251C\u2500\u2500 outputs/
477
+ \u2502 \u2502 \u2514\u2500\u2500 requirements.md
478
+ \u2502 \u2514\u2500\u2500 inputs/
479
+ \u2502 \u2514\u2500\u2500 competitor-analysis.json
480
+ \`\`\`
481
+
482
+ ### Example Task Status Flow
483
+
484
+ \`\`\`markdown
485
+ ### 2026-03-17 09:00 - Started implementation
486
+ \u{1F504} Setting up project structure.
487
+
488
+ ### 2026-03-17 10:30 - API integration
489
+ \u2705 REST API connected. Next: error handling.
490
+
491
+ ### 2026-03-17 11:15 - Error handling
492
+ \u2705 Added retry logic and fallbacks. Next: testing.
493
+
494
+ ### 2026-03-17 12:00 - Testing complete
495
+ \u2705 All tests passing (23/23). Ready for review.
496
+ \`\`\`
497
+
498
+ ## Related Files
499
+
500
+ - \`docs/dogfooding.md\` - AIP project management documentation
501
+ - \`$AIP_HOME/AGENTS.md\` - Agent profiles and workflows
502
+ - \`src/commands/help/structure.ts\` - CLI help for project structure
503
+ - \`src/commands/help/hooks.ts\` - CLI help for hooks system
504
+
505
+ ---
506
+
507
+ *This skill ensures consistent project structure across all autonomous work. Use it for all new projects and tasks.*
508
+ `,It=p({description:"Project management skill for creating and managing projects/tasks",options:z$1.object({}),handler:async()=>{console.log(Je);}});});var Be,Rt,Ft=g(()=>{f();Be=`# AIP Project Structure
189
509
 
190
510
  File organization for autonomous AI work.
191
511
 
192
512
  ## Directory Layout
193
513
 
194
514
  \`\`\`
195
- $ROOT/
515
+ $AIP_HOME/
196
516
  \u251C\u2500\u2500 projects/
197
517
  \u2502 \u251C\u2500\u2500 {project-slug}/
198
518
  \u2502 \u2502 \u251C\u2500\u2500 main.md # Goals, scope, context
@@ -240,6 +560,13 @@ created: YYYY-MM-DD
240
560
  ---
241
561
  \`\`\`
242
562
 
563
+ **Status meanings:**
564
+ - \`pending\` - Not started yet
565
+ - \`in-progress\` - Currently being worked on
566
+ - \`ongoing\` - Recurring or continuous task (should not be auto-completed by AI)
567
+ - \`done\` - Completed
568
+ - \`blocked\` - Waiting on external dependency
569
+
243
570
  ### status.md (Activity Log - Append Only)
244
571
 
245
572
  **Task updates** (each work session):
@@ -260,6 +587,8 @@ Implemented 5 endpoints with validation. Details: tasks/api-integration/
260
587
  - State what's done + what's next
261
588
  - Use emojis: \u{1F504} in-progress | \u2705 done | \u26A0\uFE0F blocked | \u274C failed
262
589
 
590
+ **Note:** Tasks with ongoing status are meant for continuous/recurring work. AI agents should not automatically mark these as done - only users should mark them complete when the ongoing work is truly finished.
591
+
263
592
  ### inputs/ (External Data)
264
593
 
265
594
  Store here:
@@ -332,14 +661,18 @@ aip task create {project} {name} --description "{desc}"
332
661
  cd $(aip project path {name})
333
662
  cd $(aip task path {project} {task})
334
663
 
335
- # Update
664
+ # Task Lifecycle
665
+ aip task start {project} {task} # Sets in-progress, outputs cd command
336
666
  aip task update {project} {task} --status done
667
+ aip task update {project} {task} --status ongoing
337
668
  aip task update {project} {task} --summary "Completed X"
338
669
 
339
670
  # Context
340
671
  aip task ingest {project} {task} # Full context for AI
341
672
  \`\`\`
342
673
 
674
+ **Note:** All status changes go through \`task update\`, which runs pre-update/post-update hooks automatically.
675
+
343
676
  ## Best Practices
344
677
 
345
678
  **DO:**
@@ -359,9 +692,9 @@ aip task ingest {project} {task} # Full context for AI
359
692
  ---
360
693
 
361
694
  *Structure enables autonomy. Clean files = clear context = better execution.*
362
- `,Ct=p({description:"Project and task directory layout for autonomous work",options:z.object({}),handler:async()=>{console.log(ze);}});});var nt,Rt=g(()=>{nt={name:"ai-projects",version:"1.0.1",type:"module",description:"AI project management CLI - create and manage projects, tasks, 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",publish:"npm publish","version:patch":"npm version patch","version:minor":"npm version minor","version:major":"npm version major"},keywords:["ai","project-management","task-management","cli","hermes-agent","autonomous-agents"],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"}};});var It,Ft=g(()=>{Rt();f();w();It=p({description:"Print compact CLI usage (all nouns, or one noun if name is given)",options:z.object({}),args:z.object({name:z.string().optional().describe("Noun (e.g. task) to list verbs for")}),handler:async({name:t})=>{let{default:e}=await Promise.resolve().then(()=>(J(),st)),o=`${nt.name} ${nt.version} -`,r=s.dumpCommandMapLines(e,t);if(!t)console.log(o,"Usage: aip <noun> <verb> [options]"),console.log(r.map(n=>`-> ${n}`).join(`
363
- `));else {let n=r[0]??`${t} {?}`;console.log(o,`Usage: aip ${n} [options]`);}}});});var at,Je,b,v=g(()=>{E();O();w();at=s.join(y.AIP_HOME,c.dirs.PROJECTS),Je={getProjectFromPwd(t=process.cwd()){let e=R.relative(at,t);if(!e||e.startsWith(".."))return null;let o=e.split(R.sep).filter(Boolean);return o.length===0?null:o[0]},getTaskFromPwd(t=process.cwd()){let e=R.relative(at,t);if(!e||e.startsWith(".."))return null;let o=e.split(R.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: ${at}`);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(`
364
- `)},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.join(y.AIP_HOME,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.join(y.AIP_HOME,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.join(y.AIP_HOME,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.join(y.AIP_HOME,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.")}},b=Je;});var Ut,_t=g(()=>{f();w();v();E();Ut=p({options:z.object({lang:z.enum(c.languages).default("ts").describe("Language"),target:z.enum(c.targets).default("project").describe("Target level")}),args:z.object({type:z.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}=b.getTargetDir(o),m=s.join(i,c.dirs.HOOKS);await s.ensureDir(m);let l=s.join(m,`${t}${n}`);if(await s.fileExists(l))throw new Error(`Hook already exists: ${l}`);let h;if(r==="ts")h=`#!/usr/bin/env tsx
695
+ `,Rt=p({description:"Project and task directory layout for autonomous work",options:z$1.object({}),handler:async()=>{console.log(Be);}});});var Ut,_t=g(()=>{ot();f();b();Ut=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(()=>(J(),it)),o=`${_.name} ${_.version} -`,r=s.dumpCommandMapLines(e,t);if(!t)console.log(o,"Usage: aip <noun> <verb> [options]"),console.log(r.map(n=>`-> ${n}`).join(`
696
+ `));else {let n=r[0]??`${t} {?}`;console.log(o,`Usage: aip ${n} [options]`);}}});});var ct,Ze,T,D=g(()=>{A();C();b();ct=s.join(h.AIP_HOME,c.dirs.PROJECTS),Ze={getProjectFromPwd(t=process.cwd()){let e=N.relative(ct,t);if(!e||e.startsWith(".."))return null;let o=e.split(N.sep).filter(Boolean);return o.length===0?null:o[0]},getTaskFromPwd(t=process.cwd()){let e=N.relative(ct,t);if(!e||e.startsWith(".."))return null;let o=e.split(N.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: ${ct}`);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(`
697
+ `)},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.join(h.AIP_HOME,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.join(h.AIP_HOME,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.join(h.AIP_HOME,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.join(h.AIP_HOME,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.")}},T=Ze;});var Ht,Mt=g(()=>{f();b();D();A();Ht=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}=T.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 y;if(r==="ts")y=`#!/usr/bin/env tsx
365
698
  /** ${t} hook for ${a} */
366
699
 
367
700
  import { env } from 'node:process'
@@ -374,7 +707,7 @@ if (env.TASK_SLUG) {
374
707
 
375
708
  // Exit with non-zero to prevent action (for pre-hooks)
376
709
  // process.exit(1)
377
- `;else if(r==="js")h=`#!/usr/bin/env node
710
+ `;else if(r==="js")y=`#!/usr/bin/env node
378
711
  /** ${t} hook for ${a} */
379
712
 
380
713
  console.log('Running ${t} hook for ${a}')
@@ -385,7 +718,7 @@ if (process.env.TASK_SLUG) {
385
718
 
386
719
  // Exit with non-zero to prevent action (for pre-hooks)
387
720
  // process.exit(1)
388
- `;else if(r==="sh")h=`#!/bin/bash
721
+ `;else if(r==="sh")y=`#!/bin/bash
389
722
  # ${t} hook for ${a}
390
723
 
391
724
  echo "Running ${t} hook for ${a}"
@@ -396,7 +729,7 @@ fi
396
729
 
397
730
  # Exit with non-zero to prevent action (for pre-hooks)
398
731
  # exit 1
399
- `;else if(r==="py")h=`#!/usr/bin/env python3
732
+ `;else if(r==="py")y=`#!/usr/bin/env python3
400
733
  """${t} hook for ${a}"""
401
734
 
402
735
  import os
@@ -408,12 +741,12 @@ if os.environ.get('TASK_SLUG'):
408
741
 
409
742
  # Exit with non-zero to prevent action (for pre-hooks)
410
743
  # sys.exit(1)
411
- `;else throw new Error(`Unsupported language: ${r}`);await s.write(l,h);let{chmod:k}=await import('fs/promises');await k(l,493),console.log(`Hook created: ${l}`);}});});var Ze,x,I=g(()=>{E();O();w();Ze={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.join(y.AIP_HOME,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(m=>{let l=spawn(t,[],{stdio:"inherit",env:a,cwd:R.dirname(t),shell:false});l.on("close",(u,h)=>{u===0?m(true):(console.error(`Hook ${R.basename(t)} failed (code=${u??h})`),m(false));}),l.on("error",u=>{console.error(`Failed to execute hook ${t}: ${u.message}`),m(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))}},x=Ze;});var Lt,Mt=g(()=>{f();I();v();E();Lt=p({options:z.object({target:z.enum(c.targets).optional().describe("Target level")}),args:z.object({type:z.enum(c.hookTypes).describe("Hook type to run")}),handler:async({type:t,target:e})=>{let{targetDir:o,entityType:r}=b.getTargetDir(e),n={action:t,entityType:r,project:b.getProjectFromPwd()||void 0,task:b.getTaskFromPwd()||void 0};await x.runHooks(o,t,n)||(console.error(`Hook ${t} failed`),process.exit(1)),console.log(`Hook ${t} completed successfully`);}});});var Be,S,F=g(()=>{E();v();O();w();Be={formatLogEntry(t,e){let o=new Date().toISOString().replace("T"," ").replace(/\.\d{3}Z$/,""),r=e?` | ${e}`:"";return `[${o}${r}] ${t}
412
- `},async appendStatus(t,e,o){let r=s.join(t,c.files.STATUS),n=this.formatLogEntry(e,o);await s.write(r,n);},async appendStatusIfExists(t,e,o){let r=s.join(t,c.files.STATUS);if(!await s.fileExists(r))return false;let i=this.formatLogEntry(e,o);return await s.write(r,i),true},async readStatus(t){let e=s.join(t,c.files.STATUS);return await s.fileExists(e)?await s.read(e):""},getCurrentAgent(){return process.env.CURRENT_AGENT},async logTask(t,e){let o=b.getCurrentContext();if(!o.project||!o.task)throw new Error("Not in a task directory");let r=s.join(y.AIP_HOME,c.dirs.PROJECTS,o.project,c.dirs.TASKS,o.task);await this.appendStatus(r,t,e||this.getCurrentAgent());},async logProject(t,e){let o=b.getProjectFromPwd();if(!o)throw new Error("Not in a project directory");let r=s.join(y.AIP_HOME,c.dirs.PROJECTS,o);await this.appendStatus(r,t,e||this.getCurrentAgent());},async logStatusChange(t,e,o,r){let n=e;if(o&&Object.keys(o).length>0){let i=Object.entries(o).map(([a,m])=>`${a}=${m}`).join(", ");n=`${e}: ${i}`;}await this.appendStatus(t,n,r);}},S=Be;});var Kt,zt=g(()=>{f();w();P();I();F();Kt=p({description:"Create a new project with name, description, optional status and assignee",options:z.object({description:z.string().describe("Project description"),status:z.string().default("active").describe("Initial status"),assignee:z.string().optional().describe("Assignee agent slug")}),args:z.object({name:z.string().describe("Project name")}),handler:async({name:t,description:e,status:o,assignee:r})=>{let n=s.slugify(t),i=d.getProjectDir(n);if(!await x.runHooks(i,"pre-create",{action:"pre-create",entityType:"project"}))throw new Error("Pre-create hook failed, aborting project creation");await d.createProject(n,{name:t,description:e,status:o,assignee:r,created:new Date().toISOString()}),await S.appendStatus(i,`Project created: ${t}`),await x.runHooks(i,"post-create",{action:"post-create",entityType:"project"}),console.log(`Project created: ${n}`),console.log(` Path: ${i}`);}});});var Gt,Jt=g(()=>{f();v();Gt=p({options:z.object({}),handler:async()=>{let t=b.getProjectFromPwd();t||(console.error("Not in a project directory"),process.exit(1)),console.log(t);}});});var Zt,Bt=g(()=>{f();P();Zt=p({description:"List all projects, optionally filtered by status",options:z.object({status:z.string().optional().describe("Filter by status")}),handler:async({status:t})=>{let e=await d.listProjects(),o=[];for(let r of e){let n=await d.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 Vt,qt=g(()=>{f();P();Vt=p({description:"Output project directory path (for cd)",options:z.object({}),args:z.object({name:z.string().describe("Project name (slug)")}),handler:async({name:t})=>{let e=d.getProjectDir(t);console.log(e);}});});var Yt,Xt=g(()=>{f();P();I();F();v();Yt=p({description:"Update project properties: name, description, status, assignee, or append summary",options:z.object({name:z.string().optional().describe("New name"),description:z.string().optional().describe("New description"),status:z.string().optional().describe("New status"),assignee:z.string().optional().describe("New assignee"),summary:z.string().optional().describe("Optional summary to append to status.md")}),args:z.object({project:z.string().optional().describe("Project slug (defaults to current project from $PWD)")}),handler:async({project:t,name:e,description:o,status:r,assignee:n,summary:i})=>{let a=t||b.getProjectFromPwd();if(!a)throw new Error("No project specified and not in a project directory");let m=d.getProjectDir(a);if(!await x.runHooks(m,"pre-update",{action:"pre-update",entityType:"project"}))throw new Error("Pre-update hook failed, aborting update");let u={};if(e&&(u.name=e),o&&(u.description=o),r&&(u.status=r),n&&(u.assignee=n),Object.keys(u).length===0){console.log("No updates provided");return}await d.updateProject(a,u);let h=Object.entries(u).map(([k,tt])=>`${k}=${tt}`).join(", ");await S.appendStatus(m,`Updated: ${h}`),i&&await S.appendStatus(m,i),await x.runHooks(m,"post-update",{action:"post-update",entityType:"project"}),console.log(`Project ${a} updated`);}});});var Qt,te=g(()=>{E();f();O();w();Qt=p({description:"Read a skill's SKILL.md file into the console for agent context",options:z.object({}),args:z.object({name:z.string().describe("Skill name (directory name)")}),handler:async({name:t})=>{let e=s.join(y.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}
413
- Expected at: ${o}`);await s.logFiles(o);}});});var ee,oe=g(()=>{f();I();w();P();F();ee=p({description:"Create a new task with optional priority, assignee, and initial status",options:z.object({description:z.string().optional().describe("Task description"),priority:z.enum(["low","medium","high"]).optional().describe("Task priority"),assignee:z.string().optional().describe("Assignee agent slug"),status:z.enum(["pending","in-progress","ongoing","done"]).default("pending").describe("Initial status")}),args:z.object({project:z.string().describe("Project slug"),name:z.string().describe("Task name")}),handler:async({project:t,name:e,description:o,priority:r,assignee:n,status:i})=>{let a=s.slugify(e),m=d.getTaskDir(t,a);if(!await x.runHooksForContext(d.getProjectDir(t),m,"pre-create",{action:"pre-create",entityType:"task",project:t}))throw new Error("Pre-create hook failed, aborting task creation");await d.createTask(t,a,{name:e,description:o,priority:r,assignee:n,status:i,created:new Date().toISOString()}),await S.appendStatus(m,`Task created: ${e}`),await x.runHooksForContext(d.getProjectDir(t),m,"post-create",{action:"post-create",entityType:"task",project:t}),console.log(`Task created: ${a}`),console.log(` Project: ${t}`),console.log(` Path: ${m}`);}});});var re,se=g(()=>{f();v();re=p({description:"Get the current task slug from PWD",options:z.object({}),handler:async()=>{let t=b.getTaskFromPwd();t||(console.error("Not in a task directory"),process.exit(1)),console.log(t);}});});var ne,ie=g(()=>{v();f();P();ne=p({description:"Output full task context (main.md, status.md) for ingestion by agents",options:z.object({}),args:z.object({project:z.string().optional().describe("Project slug (default: from $PWD)"),task:z.string().optional().describe("Task slug (default: from $PWD)")}),handler:async({project:t,task:e})=>{let o=b.getCurrentContext(),r=t??o.project,n=e??o.task;if(!r||!n)throw new Error("Need project and task (or cd into task dir)");await d.ingestTask(r,n);}});});var ae,ce=g(()=>{f();P();v();ae=p({description:"List tasks in a project, optionally filtered by status or assignee",options:z.object({project:z.string().optional().describe("Project slug (defaults to current project from $PWD)"),status:z.string().optional().describe("Filter by status"),assignee:z.string().optional().describe("Filter by assignee")}),handler:async({project:t,status:e,assignee:o})=>{let r=t||b.getProjectFromPwd();if(!r)throw new Error("No project specified and not in a project directory");let n=await d.listTasks(r),i=[];for(let a of n){let m=await d.getTask(r,a);m&&(e&&m.status!==e||o&&m.assignee!==o||i.push({slug:a,name:m.name||a,status:m.status,assignee:m.assignee,priority:m.priority}));}if(i.length===0){console.log("No tasks found");return}console.log(`Tasks in ${r}:`),console.log("---");for(let a of i)console.log(`${a.slug.padEnd(20)} ${a.name?.padEnd(30)||""} ${a.status||""} ${a.assignee||""} ${a.priority||""}`);}});});var pe,me=g(()=>{f();P();pe=p({description:"Output task directory path (for cd)",options:z.object({}),args:z.object({project:z.string().describe("Project slug"),task:z.string().describe("Task slug")}),handler:async({project:t,task:e})=>{let o=d.getTaskDir(t,e);console.log(o);}});});var Y,mt=g(()=>{f();I();P();F();Y=p({description:"Update task properties: name, description, status, priority, assignee, or append summary",options:z.object({name:z.string().optional().describe("New name"),description:z.string().optional().describe("New description"),status:z.enum(["pending","in-progress","ongoing","done","blocked"]).optional().describe("New status"),priority:z.enum(["low","medium","high"]).optional().describe("New priority"),assignee:z.string().optional().describe("New assignee"),summary:z.string().optional().describe("Optional summary to append to status.md")}),args:z.object({project:z.string().optional().describe("Project slug (defaults to current project from $PWD)"),task:z.string().optional().describe("Task slug (defaults to current task from $PWD)")}),handler:async({project:t,task:e,name:o,description:r,status:n,priority:i,assignee:a,summary:m})=>{let l={project:t,task:e};if(!l.project||!l.task)throw new Error("No task specified and not in a task directory. Use --project and --task flags.");let u=d.getTaskDir(l.project,l.task);if(!await x.runHooksForContext(d.getProjectDir(l.project),u,"pre-update",{action:"pre-update",entityType:"task",project:l.project,task:l.task}))throw new Error("Pre-update hook failed, aborting update");let k={};if(o&&(k.name=o),r&&(k.description=r),n&&(k.status=n),i&&(k.priority=i),a&&(k.assignee=a),Object.keys(k).length===0&&!m){console.log("No updates provided");return}if(Object.keys(k).length>0){await d.updateTask(l.project,l.task,k);let tt=Object.entries(k).map(([he,je])=>`${he}=${je}`).join(", ");await S.appendStatus(u,`Updated: ${tt}`);}m&&await S.appendStatus(u,m),await x.runHooksForContext(d.getProjectDir(l.project),u,"post-update",{action:"post-update",entityType:"task",project:l.project,task:l.task}),console.log(`Task ${l.task} updated`);}});});var le,de=g(()=>{f();P();mt();le=p({description:"Start a task: set status to in-progress, optionally print context",options:z.object({ingest:z.boolean().default(false).describe("Also output context for this task")}),args:z.object({project:z.string().describe("Project slug"),task:z.string().describe("Task slug")}),handler:async({project:t,task:e,ingest:o})=>{(await d.getTask(t,e))?.status!=="in-progress"&&await Y.handler({project:t,task:e,status:"in-progress"}),o&&await d.ingestTask(t,e);}});});var ue,ge=g(()=>{f();P();F();ue=p({description:"Post-mortem analysis for a completed task",options:z.object({}),args:z.object({project:z.string().describe("Project slug"),task:z.string().describe("Task slug")}),handler:async({project:t,task:e})=>{let o=d.getTaskDir(t,e),r=await d.getTask(t,e),i=(await S.readStatus(o)).split(`
414
- `).filter(l=>l.startsWith("[")).length,a=[],m=r?.name||e;i>5&&a.push("High status update count - consider breaking into smaller tasks"),m.toLowerCase().includes("implement")&&a.push("Implementation task - check if similar patterns exist to reuse"),m.toLowerCase().includes("create")&&m.toLowerCase().includes("command")&&a.push("Command creation - check existing command patterns in src/commands/"),console.log(`
415
- === Post-Mortem Analysis ===`),console.log(`Project: ${t}`),console.log(`Task: ${e}`),console.log(`Name: ${m}`),console.log(`Status: ${r?.status||"unknown"}`),console.log(`Priority: ${r?.priority||"none"}`),console.log(`Status updates: ${i}`),a.length>0?(console.log(`
416
- Suggestions:`),a.forEach(l=>console.log(` - ${l}`))):console.log(`
744
+ `;else throw new Error(`Unsupported language: ${r}`);await s.write(m,y);let{chmod:k}=await import('fs/promises');await k(m,493),console.log(`Hook created: ${m}`);}});});var Ye,x,R=g(()=>{A();C();b();Ye={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.join(h.AIP_HOME,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:N.dirname(t),shell:false});m.on("close",(u,y)=>{u===0?l(true):(console.error(`Hook ${N.basename(t)} failed (code=${u??y})`),l(false));}),m.on("error",u=>{console.error(`Failed to execute hook ${t}: ${u.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))}},x=Ye;});var zt,Kt=g(()=>{f();R();D();A();zt=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}=T.getTargetDir(e),n={action:t,entityType:r,project:T.getProjectFromPwd()||void 0,task:T.getTaskFromPwd()||void 0};await x.runHooks(o,t,n)||(console.error(`Hook ${t} failed`),process.exit(1)),console.log(`Hook ${t} completed successfully`);}});});var Xe,S,F=g(()=>{A();D();C();b();Xe={formatLogEntry(t,e){let o=new Date().toISOString().replace("T"," ").replace(/\.\d{3}Z$/,""),r=e?` | ${e}`:"";return `[${o}${r}] ${t}
745
+ `},async appendStatus(t,e,o){let r=s.join(t,c.files.STATUS),n=this.formatLogEntry(e,o);await s.write(r,n);},async appendStatusIfExists(t,e,o){let r=s.join(t,c.files.STATUS);if(!await s.fileExists(r))return false;let i=this.formatLogEntry(e,o);return await s.write(r,i),true},async readStatus(t){let e=s.join(t,c.files.STATUS);return await s.fileExists(e)?await s.read(e):""},getCurrentAgent(){return process.env.CURRENT_AGENT},async logTask(t,e){let o=T.getCurrentContext();if(!o.project||!o.task)throw new Error("Not in a task directory");let r=s.join(h.AIP_HOME,c.dirs.PROJECTS,o.project,c.dirs.TASKS,o.task);await this.appendStatus(r,t,e||this.getCurrentAgent());},async logProject(t,e){let o=T.getProjectFromPwd();if(!o)throw new Error("Not in a project directory");let r=s.join(h.AIP_HOME,c.dirs.PROJECTS,o);await this.appendStatus(r,t,e||this.getCurrentAgent());},async logStatusChange(t,e,o,r){let n=e;if(o&&Object.keys(o).length>0){let i=Object.entries(o).map(([a,l])=>`${a}=${l}`).join(", ");n=`${e}: ${i}`;}await this.appendStatus(t,n,r);}},S=Xe;});var Wt,Gt=g(()=>{f();b();P();R();F();Wt=p({description:"Create a new project with name, description, optional status and assignee",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")}),args:z$1.object({name:z$1.string().describe("Project name")}),handler:async({name:t,description:e,status:o,assignee:r})=>{let n=s.slugify(t),i=d.getProjectDir(n);if(!await x.runHooks(i,"pre-create",{action:"pre-create",entityType:"project"}))throw new Error("Pre-create hook failed, aborting project creation");await d.createProject(n,{name:t,description:e,status:o,assignee:r,created:new Date().toISOString()}),await S.appendStatus(i,`Project created: ${t}`),await x.runHooks(i,"post-create",{action:"post-create",entityType:"project"}),console.log(`Project created: ${n}`),console.log(` Path: ${i}`);}});});var Jt,qt=g(()=>{f();D();Jt=p({options:z$1.object({}),handler:async()=>{let t=T.getProjectFromPwd();t||(console.error("Not in a project directory"),process.exit(1)),console.log(t);}});});var Zt,Vt=g(()=>{f();P();Zt=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 d.listProjects(),o=[];for(let r of e){let n=await d.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 Yt,Xt=g(()=>{f();P();Yt=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=d.getProjectDir(t);console.log(e);}});});var Qt,te=g(()=>{f();P();R();F();D();Qt=p({description:"Update project properties: name, description, status, assignee, or append summary",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"),summary:z$1.string().optional().describe("Optional summary to append to status.md")}),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,summary:i})=>{let a=t||T.getProjectFromPwd();if(!a)throw new Error("No project specified and not in a project directory");let l=d.getProjectDir(a);if(!await x.runHooks(l,"pre-update",{action:"pre-update",entityType:"project"}))throw new Error("Pre-update hook failed, aborting update");let u={};if(e&&(u.name=e),o&&(u.description=o),r&&(u.status=r),n&&(u.assignee=n),Object.keys(u).length===0){console.log("No updates provided");return}await d.updateProject(a,u);let y=Object.entries(u).map(([k,et])=>`${k}=${et}`).join(", ");await S.appendStatus(l,`Updated: ${y}`),i&&await S.appendStatus(l,i),await x.runHooks(l,"post-update",{action:"post-update",entityType:"project"}),console.log(`Project ${a} updated`);}});});var ee,oe=g(()=>{A();f();C();b();ee=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(h.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}
746
+ Expected at: ${o}`);await s.logFiles(o);}});});var re,se=g(()=>{f();R();b();P();F();re=p({description:"Create a new task with optional priority, assignee, and initial status",options:z$1.object({description:z$1.string().optional().describe("Task description"),priority:z$1.enum(["low","medium","high"]).optional().describe("Task priority"),assignee:z$1.string().optional().describe("Assignee agent slug"),status:z$1.enum(["pending","in-progress","ongoing","done"]).default("pending").describe("Initial status")}),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,priority:r,assignee:n,status:i})=>{let a=s.slugify(e),l=d.getTaskDir(t,a);if(!await x.runHooksForContext(d.getProjectDir(t),l,"pre-create",{action:"pre-create",entityType:"task",project:t}))throw new Error("Pre-create hook failed, aborting task creation");await d.createTask(t,a,{name:e,description:o,priority:r,assignee:n,status:i,created:new Date().toISOString()}),await S.appendStatus(l,`Task created: ${e}`),await x.runHooksForContext(d.getProjectDir(t),l,"post-create",{action:"post-create",entityType:"task",project:t}),console.log(`Task created: ${a}`),console.log(` Project: ${t}`),console.log(` Path: ${l}`);}});});var ne,ie=g(()=>{f();D();ne=p({description:"Get the current task slug from PWD",options:z$1.object({}),handler:async()=>{let t=T.getTaskFromPwd();t||(console.error("Not in a task directory"),process.exit(1)),console.log(t);}});});var ae,ce=g(()=>{D();f();P();ae=p({description:"Output full task context (main.md, status.md) for ingestion by agents",options:z$1.object({}),args:z$1.object({project:z$1.string().optional().describe("Project slug (default: from $PWD)"),task:z$1.string().optional().describe("Task slug (default: from $PWD)")}),handler:async({project:t,task:e})=>{let o=T.getCurrentContext(),r=t??o.project,n=e??o.task;if(!r||!n)throw new Error("Need project and task (or cd into task dir)");await d.ingestTask(r,n);}});});var pe,le=g(()=>{f();P();D();pe=p({description:"List tasks in a project, optionally filtered by status or assignee",options:z$1.object({project:z$1.string().optional().describe("Project slug (defaults to current project from $PWD)"),status:z$1.string().optional().describe("Filter by status"),assignee:z$1.string().optional().describe("Filter by assignee")}),handler:async({project:t,status:e,assignee:o})=>{let r=t||T.getProjectFromPwd();if(!r)throw new Error("No project specified and not in a project directory");let n=await d.listTasks(r),i=[];for(let a of n){let l=await d.getTask(r,a);l&&(e&&l.status!==e||o&&l.assignee!==o||i.push({slug:a,name:l.name||a,status:l.status,assignee:l.assignee,priority:l.priority}));}if(i.length===0){console.log("No tasks found");return}console.log(`Tasks in ${r}:`),console.log("---");for(let a of i)console.log(`${a.slug.padEnd(20)} ${a.name?.padEnd(30)||""} ${a.status||""} ${a.assignee||""} ${a.priority||""}`);}});});var me,de=g(()=>{f();P();me=p({description:"Output task directory path (for cd)",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=d.getTaskDir(t,e);console.log(o);}});});var X,mt=g(()=>{f();R();P();F();X=p({description:"Update task properties: name, description, status, priority, assignee, or append summary",options:z$1.object({name:z$1.string().optional().describe("New name"),description:z$1.string().optional().describe("New description"),status:z$1.enum(["pending","in-progress","ongoing","done","blocked"]).optional().describe("New status"),priority:z$1.enum(["low","medium","high"]).optional().describe("New priority"),assignee:z$1.string().optional().describe("New assignee"),summary:z$1.string().optional().describe("Optional summary to append to status.md")}),args:z$1.object({project:z$1.string().optional().describe("Project slug (defaults to current project from $PWD)"),task:z$1.string().optional().describe("Task slug (defaults to current task from $PWD)")}),handler:async({project:t,task:e,name:o,description:r,status:n,priority:i,assignee:a,summary:l})=>{let m={project:t,task:e};if(!m.project||!m.task)throw new Error("No task specified and not in a task directory. Use --project and --task flags.");let u=d.getTaskDir(m.project,m.task);if(!await x.runHooksForContext(d.getProjectDir(m.project),u,"pre-update",{action:"pre-update",entityType:"task",project:m.project,task:m.task}))throw new Error("Pre-update hook failed, aborting update");let k={};if(o&&(k.name=o),r&&(k.description=r),n&&(k.status=n),i&&(k.priority=i),a&&(k.assignee=a),Object.keys(k).length===0&&!l){console.log("No updates provided");return}if(Object.keys(k).length>0){await d.updateTask(m.project,m.task,k);let et=Object.entries(k).map(([we,Te])=>`${we}=${Te}`).join(", ");await S.appendStatus(u,`Updated: ${et}`);}l&&await S.appendStatus(u,l),await x.runHooksForContext(d.getProjectDir(m.project),u,"post-update",{action:"post-update",entityType:"task",project:m.project,task:m.task}),console.log(`Task ${m.task} updated`);}});});var ue,ge=g(()=>{f();P();mt();ue=p({description:"Start a task: set status to in-progress, optionally print context",options:z$1.object({ingest:z$1.boolean().default(false).describe("Also output context for this task")}),args:z$1.object({project:z$1.string().describe("Project slug"),task:z$1.string().describe("Task slug")}),handler:async({project:t,task:e,ingest:o})=>{(await d.getTask(t,e))?.status!=="in-progress"&&await X.handler({project:t,task:e,status:"in-progress"}),o&&await d.ingestTask(t,e);}});});var fe,he=g(()=>{f();P();F();fe=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=d.getTaskDir(t,e),r=await d.getTask(t,e),i=(await S.readStatus(o)).split(`
747
+ `).filter(m=>m.startsWith("[")).length,a=[],l=r?.name||e;i>5&&a.push("High status update 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(`
748
+ === Post-Mortem Analysis ===`),console.log(`Project: ${t}`),console.log(`Task: ${e}`),console.log(`Name: ${l}`),console.log(`Status: ${r?.status||"unknown"}`),console.log(`Priority: ${r?.priority||"none"}`),console.log(`Status updates: ${i}`),a.length>0?(console.log(`
749
+ Suggestions:`),a.forEach(m=>console.log(` - ${m}`))):console.log(`
417
750
  No specific suggestions - task looks well-scoped`),console.log(`
418
751
  === End Post-Mortem ===
419
- `);}});});var fe,ye=g(()=>{f();w();fe=p({description:"Read one or more files into the console",options:z.object({}),args:z.object({paths:z.array(z.string()).describe("File paths to read")}),handler:async({paths:t})=>{await s.logFiles(...t);}});});var st={};be(st,{default:()=>N});var Ye,N,J=g(()=>{kt();jt();bt();Pt();St();vt();$t();Nt();Ft();_t();Mt();zt();Jt();Bt();qt();Xt();te();oe();se();ie();ce();me();de();mt();ge();ye();Ye={agent:{create:yt,current:ht,list:Tt,path:wt,start:xt},help:{api:Dt,hooks:Ot,structure:Ct,usage:It},hook:{create:Ut,run:Lt},project:{create:Kt,current:Gt,list:Zt,path:Vt,update:Yt},skill:{read:Qt},task:{create:ee,current:re,ingest:ne,list:ae,path:pe,start:le,update:Y},util:{postmortem:ue,read:fe}},N=Ye;});J();w();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 ke(t){let[e,o,...r]=t;try{(!e||!s.isKeyOf(e,N))&&(await N.help.usage.handler({}),process.exit(1));let n=N[e];(!o||!s.isKeyOf(o,n))&&(await N.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 Un=ke,_n=N;s.isMain()&&ke(process.argv.slice(2));export{_n as commands,Un as default};
752
+ `);}});});var ke,ye=g(()=>{f();b();ke=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 it={};Pe(it,{default:()=>I});var eo,I,J=g(()=>{yt();wt();bt();xt();At();Ct();$t();Nt();Ft();_t();Mt();Kt();Gt();qt();Vt();Xt();te();oe();se();ie();ce();le();de();ge();mt();he();ye();eo={agent:{create:kt,current:jt,list:Tt,path:Pt,start:St},help:{api:Dt,hooks:Ot,skill:It,structure:Rt,usage:Ut},hook:{create:Ht,run:zt},project:{create:Wt,current:Jt,list:Zt,path:Yt,update:Qt},skill:{read:ee},task:{create:re,current:ne,ingest:ae,list:pe,path:me,start:ue,update:X},util:{postmortem:fe,read:ke}},I=eo;});ot();J();b();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 je(t){let[e,o,...r]=t;(e==="--version"||e==="-v")&&(console.log(_.version),process.exit(0));try{(!e||!s.isKeyOf(e,I))&&(await I.help.usage.handler({}),process.exit(1));let n=I[e];(!o||!s.isKeyOf(o,n))&&(await I.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 Jn=je,qn=I;s.isMain()&&je(process.argv.slice(2));export{qn as commands,Jn as default};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-projects",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "type": "module",
5
5
  "description": "AI project management CLI - create and manage projects, tasks, and agents",
6
6
  "main": "dist/index.js",
@@ -44,7 +44,6 @@
44
44
  "prepare": "[ \"$CI\" != \"true\" ] && [ -d node_modules/husky ] && husky || true",
45
45
  "prepack": "npm run test:full && npm run build:all",
46
46
  "publish:dry": "npm pack --dry-run",
47
- "publish": "npm publish",
48
47
  "version:patch": "npm version patch",
49
48
  "version:minor": "npm version minor",
50
49
  "version:major": "npm version major"