ai-projects 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/index.d.ts +42 -33
  2. package/dist/index.js +163 -436
  3. package/package.json +2 -2
package/dist/index.d.ts CHANGED
@@ -67,12 +67,18 @@ 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, {
70
+ readonly quickstart: CommandDef<zod.ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, zod.ZodObject<any, zod.UnknownKeysParam, zod.ZodTypeAny, {
71
71
  [x: string]: any;
72
72
  }, {
73
73
  [x: string]: any;
74
74
  }>>;
75
- readonly structure: CommandDef<zod.ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, zod.ZodObject<any, zod.UnknownKeysParam, zod.ZodTypeAny, {
75
+ readonly skill: CommandDef<zod.ZodObject<{
76
+ mode: zod.ZodDefault<zod.ZodEnum<["md", "claude", "hermes"]>>;
77
+ }, "strip", zod.ZodTypeAny, {
78
+ mode: "md" | "claude" | "hermes";
79
+ }, {
80
+ mode?: "md" | "claude" | "hermes" | undefined;
81
+ }>, zod.ZodObject<any, zod.UnknownKeysParam, zod.ZodTypeAny, {
76
82
  [x: string]: any;
77
83
  }, {
78
84
  [x: string]: any;
@@ -197,19 +203,16 @@ declare const commands: {
197
203
  readonly task: {
198
204
  readonly create: CommandDef<zod.ZodObject<{
199
205
  description: zod.ZodOptional<zod.ZodString>;
200
- priority: zod.ZodOptional<zod.ZodEnum<["low", "medium", "high"]>>;
201
206
  assignee: zod.ZodOptional<zod.ZodString>;
202
- status: zod.ZodDefault<zod.ZodEnum<["pending", "in-progress", "ongoing", "done"]>>;
207
+ status: zod.ZodDefault<zod.ZodString>;
203
208
  }, "strip", zod.ZodTypeAny, {
204
- status: "pending" | "in-progress" | "ongoing" | "done";
209
+ status: string;
205
210
  description?: string | undefined;
206
211
  assignee?: string | undefined;
207
- priority?: "low" | "medium" | "high" | undefined;
208
212
  }, {
209
- status?: "pending" | "in-progress" | "ongoing" | "done" | undefined;
213
+ status?: string | undefined;
210
214
  description?: string | undefined;
211
215
  assignee?: string | undefined;
212
- priority?: "low" | "medium" | "high" | undefined;
213
216
  }>, zod.ZodObject<{
214
217
  project: zod.ZodString;
215
218
  name: zod.ZodString;
@@ -225,88 +228,94 @@ declare const commands: {
225
228
  }, {
226
229
  [x: string]: any;
227
230
  }>>;
228
- readonly ingest: CommandDef<zod.ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, zod.ZodObject<{
231
+ readonly ingest: CommandDef<zod.ZodObject<{
229
232
  project: zod.ZodOptional<zod.ZodString>;
230
- task: zod.ZodOptional<zod.ZodString>;
231
233
  }, "strip", zod.ZodTypeAny, {
232
234
  project?: string | undefined;
233
- task?: string | undefined;
234
235
  }, {
235
236
  project?: string | undefined;
237
+ }>, zod.ZodObject<{
238
+ task: zod.ZodOptional<zod.ZodString>;
239
+ }, "strip", zod.ZodTypeAny, {
240
+ task?: string | undefined;
241
+ }, {
236
242
  task?: string | undefined;
237
243
  }>>;
238
244
  readonly list: CommandDef<zod.ZodObject<{
239
245
  project: zod.ZodOptional<zod.ZodString>;
240
- status: zod.ZodOptional<zod.ZodString>;
246
+ statuses: zod.ZodDefault<zod.ZodArray<zod.ZodString, "many">>;
241
247
  assignee: zod.ZodOptional<zod.ZodString>;
248
+ all: zod.ZodDefault<zod.ZodBoolean>;
242
249
  }, "strip", zod.ZodTypeAny, {
243
- status?: string | undefined;
250
+ statuses: string[];
251
+ all: boolean;
244
252
  project?: string | undefined;
245
253
  assignee?: string | undefined;
246
254
  }, {
247
- status?: string | undefined;
248
255
  project?: string | undefined;
249
256
  assignee?: string | undefined;
257
+ statuses?: string[] | undefined;
258
+ all?: boolean | undefined;
250
259
  }>, zod.ZodObject<any, zod.UnknownKeysParam, zod.ZodTypeAny, {
251
260
  [x: string]: any;
252
261
  }, {
253
262
  [x: string]: any;
254
263
  }>>;
255
- readonly path: CommandDef<zod.ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, zod.ZodObject<{
256
- project: zod.ZodString;
264
+ readonly path: CommandDef<zod.ZodObject<{
265
+ project: zod.ZodOptional<zod.ZodString>;
266
+ }, "strip", zod.ZodTypeAny, {
267
+ project?: string | undefined;
268
+ }, {
269
+ project?: string | undefined;
270
+ }>, zod.ZodObject<{
257
271
  task: zod.ZodString;
258
272
  }, "strip", zod.ZodTypeAny, {
259
- project: string;
260
273
  task: string;
261
274
  }, {
262
- project: string;
263
275
  task: string;
264
276
  }>>;
265
277
  readonly start: CommandDef<zod.ZodObject<{
278
+ project: zod.ZodOptional<zod.ZodString>;
266
279
  ingest: zod.ZodDefault<zod.ZodBoolean>;
267
280
  }, "strip", zod.ZodTypeAny, {
268
281
  ingest: boolean;
282
+ project?: string | undefined;
269
283
  }, {
284
+ project?: string | undefined;
270
285
  ingest?: boolean | undefined;
271
286
  }>, zod.ZodObject<{
272
- project: zod.ZodString;
273
- task: zod.ZodString;
287
+ task: zod.ZodOptional<zod.ZodString>;
274
288
  }, "strip", zod.ZodTypeAny, {
275
- project: string;
276
- task: string;
289
+ task?: string | undefined;
277
290
  }, {
278
- project: string;
279
- task: string;
291
+ task?: string | undefined;
280
292
  }>>;
281
293
  readonly update: CommandDef<zod.ZodObject<{
282
294
  name: zod.ZodOptional<zod.ZodString>;
283
295
  description: zod.ZodOptional<zod.ZodString>;
284
- status: zod.ZodOptional<zod.ZodEnum<["pending", "in-progress", "ongoing", "done", "blocked"]>>;
285
- priority: zod.ZodOptional<zod.ZodEnum<["low", "medium", "high"]>>;
296
+ status: zod.ZodOptional<zod.ZodString>;
286
297
  assignee: zod.ZodOptional<zod.ZodString>;
298
+ project: zod.ZodOptional<zod.ZodString>;
287
299
  summary: zod.ZodOptional<zod.ZodString>;
288
300
  }, "strip", zod.ZodTypeAny, {
289
- status?: "pending" | "in-progress" | "ongoing" | "done" | "blocked" | undefined;
301
+ status?: string | undefined;
290
302
  description?: string | undefined;
291
303
  name?: string | undefined;
304
+ project?: string | undefined;
292
305
  assignee?: string | undefined;
293
306
  summary?: string | undefined;
294
- priority?: "low" | "medium" | "high" | undefined;
295
307
  }, {
296
- status?: "pending" | "in-progress" | "ongoing" | "done" | "blocked" | undefined;
308
+ status?: string | undefined;
297
309
  description?: string | undefined;
298
310
  name?: string | undefined;
311
+ project?: string | undefined;
299
312
  assignee?: string | undefined;
300
313
  summary?: string | undefined;
301
- priority?: "low" | "medium" | "high" | undefined;
302
314
  }>, zod.ZodObject<{
303
- project: zod.ZodOptional<zod.ZodString>;
304
315
  task: zod.ZodOptional<zod.ZodString>;
305
316
  }, "strip", zod.ZodTypeAny, {
306
- project?: string | undefined;
307
317
  task?: string | undefined;
308
318
  }, {
309
- project?: string | undefined;
310
319
  task?: string | undefined;
311
320
  }>>;
312
321
  };
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 {exec,spawn}from'child_process';import L from'fs/promises';import j from'lodash';import H from'moment';import N from'path';import {fileURLToPath}from'url';import {inspect}from'util';import Oe from'dotenv';import $e from'fs';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.2.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 L.mkdir(t,{recursive:true});},async write(t,e){await w.ensureDir(N.dirname(t)),await L.writeFile(t,e,"utf8");},async read(t){return L.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}
2
+ import {z as z$1}from'zod';import {parser}from'zod-opts';import {spawn,exec}from'child_process';import z from'fs/promises';import T from'lodash';import W from'moment';import _ from'path';import {fileURLToPath}from'url';import {inspect}from'util';import We from'dotenv';import Je from'fs';import Tt from'yaml';var Ue=Object.defineProperty;var f=(t,e)=>()=>(t&&(e=t(t=0)),e);var _e=(t,e)=>{for(var o in e)Ue(t,o,{get:e[o],enumerable:true});};var x,G=f(()=>{x={name:"ai-projects",version:"1.3.0",type:"module",description:"Useful CLI for AI agents to create and manage projects, tasks, skills and agents",main:"dist/index.js",types:"dist/index.d.ts",bin:{aip:"dist/index.js"},files:["dist/**/*","README.md","LICENSE"],scripts:{build:"npm run build:map && npm run build:code","build:map":"tsx bin/map-commands.ts","build:code":"tsup --no-dts","build:all":"npm run build:map && tsup","build:check":"tsc --noEmit","build:watch":"npm run build:code -- --watch","build:clean":"rimraf dist/*","build:incr":"tsup --no-dts",start:"dist/index.js",dev:'npm run build:watch -- --onSuccess "dist/index.js"',cli:"npm run build && npm start --",ts:"tsx",vitest:"VITE_CJS_IGNORE_WARNING=true vitest",test:"npm run test:types && npm run test:unit","test:unit":"npm run vitest -- run","test:types:test":"tsc -p tsconfig.test.json --incremental --tsBuildInfoFile dist/test.tsbuildinfo","test:types:bin":"tsc -p bin/tsconfig.json --incremental --tsBuildInfoFile dist/bin.tsbuildinfo","test:types":"npm run test:types:test && npm run test:types:bin","test:full":"npm run lint:full && npm run test",eslint:"eslint --cache",lint:"npm run eslint -- '{src,bin}/**/*.ts'","lint:fix":"npm run lint -- --fix","lint:full":"npm run build:incr && npm run test:types:bin && npm run lint:fix","lint:full:silent":"npm run -s lint:full && echo LINT OK",map:"npm run build:map",link:"npm link",unlink:"npm unlink",prepare:'[ "$CI" != "true" ] && [ -d node_modules/husky ] && husky || true',prepack:"npm run test:full && npm run build:all","publish:dry":"npm pack --dry-run","version:patch":"npm version patch","version:minor":"npm version minor","version:major":"npm version major"},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,c={};for(let[d,l]of Object.entries(i))c[d]={type:l};let u=parser().options(c);if(r){let d=r.shape,l=Object.entries(d).map(([k,w])=>({name:k,type:w}));l.length>0&&(u=u.args(l));}return e&&(u=u.description(e)),{description:e,options:o,args:r,parser:u,handler:n,cli:d=>n(u.parse(d))}}var g=f(()=>{});var P,s,b=f(()=>{P={REPO:fileURLToPath(import.meta.url.replace(/\/(dist|src)\/.*/,"/")),join:(...t)=>_.join(...t),onRepo:(...t)=>P.join(P.REPO,...t),async ensureDir(t){await z.mkdir(t,{recursive:true});},async write(t,e){await P.ensureDir(_.dirname(t)),await z.writeFile(t,e,"utf8");},async read(t){return z.readFile(t,"utf8")},async readRepo(...t){return P.read(P.onRepo(...t))},async readMany(...t){return (await Promise.all(t.map(async o=>{if(await P.fileExists(o)){let r=await P.read(o);return `# ${o}
3
3
 
4
- ${r}`}return ""}))).filter(Boolean)},async logFiles(...t){let e=await w.readMany(...t);console.log(e.join(`
4
+ ${r}`}return ""}))).filter(Boolean)},async logFiles(...t){let e=await P.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 w.entriesOf(o))r.push(`${n} {${Object.keys(i).join("|")}}`);return r},async fileExists(t){try{return await L.access(t),!0}catch{return false}},async listDir(t){try{return await L.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=>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=>w.oneLine(w.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 P.entriesOf(o))r.push(`${n} {${Object.keys(i).join("|")}}`);return r},async fileExists(t){try{return await z.access(t),!0}catch{return false}},async listDir(t){try{return await z.readdir(t)}catch{return []}},spawn:spawn,cd(t){process.chdir(t);},async exec(t,e){return new Promise(o=>{exec(t,{encoding:"utf8",...e},(r,n,i)=>{let 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=>P.omitByDeep(o,e)):T.isPlainObject(t)?T.mapValues(T.omitBy(t,e),o=>P.omitByDeep(o,e)):t,omitNilsDeep:t=>P.omitByDeep(t,T.isNil),omitUndefinedsDeep:t=>P.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)?P.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,P.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=>P.oneLine(P.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=>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"]};});var Ne,ut,$,Re,h,D=g(()=>{A();Ne=()=>{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=Ne(),$=process.env.AIP_HOME;$||(Oe.config({path:N.join(ut,".env"),quiet:true}),$=process.env.AIP_HOME);if(!$){$=process.cwd();let t=$.split(N.sep);for(let e of [c.dirs.PROJECTS,c.dirs.SKILLS,c.dirs.AGENTS]){let o=t.indexOf(e);if(o!==-1){$=t.slice(0,o).join(N.sep);break}}}Re={ROOT:ut,AIP_HOME:$},h=Re;});var ft,M,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},M=async(t,e,o="")=>{let n=`---
13
- ${gt.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=>P.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=P;});var a,A=f(()=>{a={dirs:{PROJECTS:"projects",SKILLS:"skills",AGENTS:"agents",TASKS:"tasks",INPUTS:"inputs",OUTPUTS:"outputs",HOOKS:"hooks",SCRIPTS:"scripts"},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"]};});var Ze,jt,N,Ve,h,D=f(()=>{A();Ze=()=>{let t=fileURLToPath(import.meta.url),e=_.dirname(t),o=10;for(let r=0;r<o;r++)try{if(Je.existsSync(_.join(e,"package.json")))return e;let n=_.dirname(e);if(n===e)break;e=n;}catch{break}return process.cwd()},jt=Ze(),N=process.env.AIP_HOME;N||(We.config({path:_.join(jt,".env"),quiet:true}),N=process.env.AIP_HOME);if(!N){N=process.cwd();let t=N.split(_.sep);for(let e of [a.dirs.PROJECTS,a.dirs.SKILLS,a.dirs.AGENTS]){let o=t.indexOf(e);if(o!==-1){N=t.slice(0,o).join(_.sep);break}}}Ve={ROOT:jt,AIP_HOME:N},h=Ve;});var Pt,J,ct,B,wt=f(()=>{b();Pt=t=>{let e=t.trim();if(!e.startsWith("---"))return null;let o=e.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);return o?{frontmatter:Tt.parse(o[1]),content:o[2].trim()}:null},J=async(t,e,o="")=>{let n=`---
13
+ ${Tt.stringify(e).trim()}
14
14
  ---
15
15
 
16
16
  ${o}`.trim();await s.write(t,n+`
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 M(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 Fe,d,P=g(()=>{A();D();ht();b();Fe={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 M(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 M(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 M(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=Fe;});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();D();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();D();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,He,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"},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 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(`
17
+ `);},ct=async(t,e)=>{let o=await s.read(t),r=Pt(o);if(!r)throw new Error(`No frontmatter found in ${t}`);let n={...r.frontmatter,...e};return await J(t,n,r.content),n},B=async t=>{let e=await s.read(t),o=Pt(e);if(!o)throw new Error(`No frontmatter found in ${t}`);return o.frontmatter};});var L,Y,bt,qe,Ye,Qe,m,S=f(()=>{A();D();wt();b();L=(c=>(c.BACKLOG="backlog",c.IN_PROGRESS="in-progress",c.ONGOING="ongoing",c.DONE="done",c.BLOCKED="blocked",c.TO_DO="to-do",c))(L||{}),Y=Object.values(L),bt=["backlog","in-progress","ongoing"],qe=[a.dirs.TASKS,a.dirs.HOOKS,a.dirs.INPUTS,a.dirs.OUTPUTS,a.dirs.SCRIPTS],Ye=[a.dirs.HOOKS,a.dirs.INPUTS,a.dirs.OUTPUTS,a.dirs.SCRIPTS],Qe={getProjectDir(t){return s.join(h.AIP_HOME,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(h.AIP_HOME,a.dirs.AGENTS,t)},async listProjects(){let t=s.join(h.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(h.AIP_HOME,a.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 Promise.all(qe.map(r=>s.ensureDir(s.join(o,r)))),await J(s.join(o,a.files.MAIN),e),await s.write(s.join(o,a.files.STATUS),""),o},async createTask(t,e,o){let r=this.getTaskDir(t,e);return await s.ensureDir(r),await Promise.all(Ye.map(n=>s.ensureDir(s.join(r,n)))),await J(s.join(r,a.files.MAIN),o),await s.write(s.join(r,a.files.STATUS),""),r},async createAgent(t,e){let o=this.getAgentDir(t);return await s.ensureDir(o),await J(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 B(e):null},async getTask(t,e){let o=s.join(this.getTaskDir(t,e),a.files.MAIN);return await s.fileExists(o)?await B(o):null},async getAgent(t){let e=s.join(this.getAgentDir(t),a.files.MAIN);return await s.fileExists(e)?await B(e):null},async updateProject(t,e){let o=s.join(this.getProjectDir(t),a.files.MAIN);return await ct(o,e)},async updateTask(t,e,o){let r=s.join(this.getTaskDir(t,e),a.files.MAIN);if((await B(r))?.status==="ongoing")throw new Error("Cannot update ongoing task. Should be done by user or update manually");return await ct(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.STATUS)];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.STATUS),...o.map(n=>s.join(this.getTaskDir(t,n),a.files.MAIN))];await s.logFiles(...r);},async ingestFiles(t){await s.logFiles(...t);}},m=Qe;});var St,xt=f(()=>{g();b();S();St=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 m.createAgent(r,{name:t,description:e,status:o,created:new Date().toISOString()}),console.log(`Agent created: ${r}`),console.log(` Path: ${m.getAgentDir(r)}`);}});});var Et,At=f(()=>{g();Et=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 vt,$t=f(()=>{g();S();vt=p({options:z$1.object({}),handler:async()=>{let t=await m.listAgents(),e=[];for(let o of t){let r=await m.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 Ot,Dt=f(()=>{A();g();D();b();Ot=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,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 Ct,It=f(()=>{A();g();D();b();Ct=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,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 Nt,Rt,oo,Ut,_t=f(()=>{g();Nt=t=>{let e=t.shape,o=[];for(let[r,n]of Object.entries(e)){let i=n._def,c="unknown",u,d;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=Rt(i.innerType):i.typeName==="ZodDefault"&&(c=Rt(i.innerType),d=i.defaultValue()),i.description&&(u=i.description);let l=i.typeName!=="ZodOptional"&&i.typeName!=="ZodDefault";o.push({name:r,type:c,required:l,description:u,defaultValue:d});}return o},Rt=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"},oo=(t,e,o)=>{let r=Nt(o.options),n=o.args?Nt(o.args):[],i=o.description,c=`\`${t} ${e}\``;if(i&&(c+=`: ${i}`),c+=`
20
+ `,r.length>0||n.length>0){let d=[];for(let l of n){let k=l.required?`<${l.name}>`:`[${l.name}]`,w=l.description||"";l.defaultValue!==void 0&&(w+=w?` (default: ${l.defaultValue})`:`(default: ${l.defaultValue})`),d.push(`\xB7 ${k}${w?": "+w:""}`);}for(let l of r){let k=l.description||"";l.defaultValue!==void 0&&(k+=k?` (default: ${l.defaultValue})`:`(default: ${l.defaultValue})`),d.push(`\xB7 --${l.name}${k?": "+k:""}`);}c+=d.join(`
21
21
  `)+`
22
- `;}return a+=`
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+=He(r,a,l);}}console.log(e);}});});var ze,Ot,$t=g(()=>{f();ze=`# AIP Hooks
22
+ `;}return c+=`
23
+ `,c},Ut=p({description:"Print generated CLI reference from command schemas",options:z$1.object({}),handler:async()=>{let{default:t}=await Promise.resolve().then(()=>(Q(),mt)),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 u=n[c];e+=oo(r,c,u);}}console.log(e);}});});var so,Lt,Ft=f(()=>{g();so=`# AIP Hooks
24
24
 
25
25
  Automated scripts that run before/after project/task actions.
26
26
 
@@ -200,7 +200,65 @@ 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
- `,Ot=p({description:"Hook types, env vars, and patterns",options:z$1.object({}),handler:async()=>{console.log(ze);}});});var We,It,Nt=g(()=>{f();We=`# AIP - Project Management Skill
203
+ `,Lt=p({description:"Hook types, env vars, and patterns",options:z$1.object({}),handler:async()=>{console.log(so);}});});var C,io,Ht,Mt=f(()=>{G();g();C=Object.keys(x.bin)[0],io=`# Quick Start
204
+
205
+ ## New Task/Project
206
+
207
+ \`\`\`bash
208
+ # 1. Create project (if needed)
209
+ ${C} project create "my-project" --description "What I'm building"
210
+
211
+ # 2. Create task
212
+ ${C} task create my-project "first-task" --description "Start here"
213
+
214
+ # 3. Navigate to task
215
+ cd $(${C} task path first-task)
216
+
217
+ # 4. Start working (implicit from PWD)
218
+ ${C} task start
219
+ # \u2192 sets status to in-progress
220
+
221
+ # 5. Work session
222
+ # Log: echo "[timestamp] did X" >> status.md
223
+ # Save: outputs/ to deliver, inputs/ for data
224
+ \`\`\`
225
+
226
+ ## Resuming
227
+
228
+ \`\`\`bash
229
+ # Find your tasks (searches all projects)
230
+ ${C} task list
231
+
232
+ # Navigate to task
233
+ cd $(${C} task path task-slug)
234
+
235
+ # All commands work implicitly from PWD:
236
+ ${C} task start # Start working (sets status to in-progress)
237
+ \`\`\`
238
+
239
+ ## Completing
240
+
241
+ \`\`\`bash
242
+ # Mark done (implicit from PWD)
243
+ ${C} task update --status done --summary "What I built"
244
+ \`\`\`
245
+
246
+ **Note:** All task commands accept an optional task slug, but use PWD if not provided. Navigate with \`cd\` first for smoother workflow.
247
+
248
+ ## Structure
249
+
250
+ \`\`\`
251
+ $AIP_HOME/projects/slug/
252
+ \u251C\u2500\u2500 main.md # Goals (read first)
253
+ \u251C\u2500\u2500 status.md # Log (append every session)
254
+ \u2514\u2500\u2500 tasks/task/
255
+ \u251C\u2500\u2500 main.md # Task definition
256
+ \u2514\u2500\u2500 status.md # Updates
257
+ \`\`\`
258
+
259
+ **Status format:** \`[YYYY-MM-DD HH:MM] message\`
260
+ **Example:** \`[2026-03-30 14:30] API integration complete\`
261
+ `,Ht=p({description:"Quick start guide for new users",options:z$1.object({}),handler:async()=>{console.log(io);}});});var ao,co,Gt,zt,Wt,Jt,Bt,X,tt,dt,Zt,Vt=f(()=>{g();G();S();A();ao=Object.values(L).join("|"),{PROJECTS:co,TASKS:Gt,HOOKS:zt,INPUTS:Wt,OUTPUTS:Jt,SCRIPTS:Bt}=a.dirs,{MAIN:X,STATUS:tt}=a.files,dt=`# AIP - Project Management Skill
204
262
 
205
263
  Automated project and task creation with proper structure, front-matter, and file organization.
206
264
 
@@ -213,21 +271,21 @@ Streamline creation of new projects and tasks with the correct directory structu
213
271
  Every project follows this structure:
214
272
 
215
273
  \`\`\`
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
274
+ $AIP_HOME/${co}/{project-slug}/
275
+ \u251C\u2500\u2500 ${X} # Primary context: goals, objectives, scope, data
276
+ \u251C\u2500\u2500 ${tt} # Chronological log of status updates
277
+ \u251C\u2500\u2500 ${zt}/ # pre|post-{create,start,update,complete}.*
278
+ \u251C\u2500\u2500 ${Jt}/ # Deliverables (reports, code, final files)
279
+ \u251C\u2500\u2500 ${Wt}/ # External data (API responses, downloads)
280
+ \u251C\u2500\u2500 ${Bt}/ # Automation (bash/python/js)
281
+ \u2514\u2500\u2500 ${Gt}/
282
+ \u2514\u2500\u2500 {task-slug}/
283
+ \u251C\u2500\u2500 ${X} # Task definition with front-matter
284
+ \u251C\u2500\u2500 ${tt} # Single-line updates per work session
285
+ \u251C\u2500\u2500 ${zt}/ # Task-level hooks
286
+ \u251C\u2500\u2500 ${Jt}/ # Task-specific deliverables
287
+ \u251C\u2500\u2500 ${Wt}/ # Task-specific data files
288
+ \u2514\u2500\u2500 ${Bt}/ # Task-specific automation
231
289
  \`\`\`
232
290
 
233
291
  ## File Purposes
@@ -246,7 +304,7 @@ $AIP_HOME/projects/{project-slug}/
246
304
  name: Clear Title
247
305
  description: One-line summary for search
248
306
  assignee: agent-name
249
- status: pending|in-progress|ongoing|done|blocked
307
+ status: ${ao}
250
308
  created: YYYY-MM-DD
251
309
  ---
252
310
  \`\`\`
@@ -256,73 +314,33 @@ created: YYYY-MM-DD
256
314
  **When to update:** Only when scope/goals change (rare)
257
315
 
258
316
  ### \`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
- \`\`\`
317
+ **What goes here:** Single-line timestamped entries
270
318
 
271
- **Status emojis:** \u{1F504} in-progress | \u2705 done | \u26A0\uFE0F blocked | \u274C failed
319
+ **Task examples:**
320
+ \`\`\`markdown
321
+ [2026-03-17 14:30] Task created: optimize-config
322
+ [2026-03-17 15:45] Updated: status=in-progress
323
+ [2026-03-17 16:20] API integration complete
324
+ \`\`\`
272
325
 
273
- **When to read:** To understand current state and recent activity
326
+ **Project example:**
327
+ \`\`\`markdown
328
+ [2026-03-17 16:00] Task completed: gather-requirements (details: tasks/gather-requirements/)
329
+ \`\`\`
274
330
 
275
- **When to update:**
276
- - **Tasks:** Every work session (append 1 line)
277
- - **Projects:** When task completes (append 1 packed line)
331
+ **When to update:** Every work session (tasks) or task completion (projects)
278
332
 
279
333
  ### \`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
334
+ **What:** Final deliverables (reports, code, data)
335
+ **Examples:** \`outputs/report.md\`, \`outputs/code.zip\`
293
336
 
294
337
  ### \`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
338
+ **What:** External data (API responses, downloads)
339
+ **Examples:** \`inputs/api.json\`, \`inputs/data.csv\`
307
340
 
308
341
  ### \`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
342
+ **What:** Automation scripts (bash, python, js)
343
+ **Examples:** \`scripts/deploy.sh\`, \`scripts/process.py\`
326
344
 
327
345
  ## Usage
328
346
 
@@ -332,374 +350,82 @@ created: YYYY-MM-DD
332
350
  # Via AIP CLI
333
351
  aip project create "optimize-hermes-config" \\
334
352
  --description "Analyze and optimize Hermes Agent configuration" \\
335
- --assignee basic \\
336
- --priority high
353
+ --assignee basic
337
354
  \`\`\`
338
355
 
339
356
  ### Create New Task in Existing Project
340
357
 
341
358
  \`\`\`bash
342
359
  aip task create "optimize-hermes-config" "apply-config-changes" \\
343
- --description "Implement safe optimizations with backups" \\
344
- --assignee basic \\
345
- --priority high
360
+ --description "Implement safe optimizations" \\
361
+ --assignee basic
346
362
  \`\`\`
347
363
 
348
364
  ### Navigate to Project/Task
349
365
 
350
366
  \`\`\`bash
351
367
  cd $(aip project path optimize-hermes-config)
352
- cd $(aip task path optimize-hermes-config apply-config-changes)
368
+ cd $(aip task path apply-config-changes)
353
369
  \`\`\`
354
370
 
355
- ### Update Task Status
371
+ ### Update Task Status (implicit from PWD)
356
372
 
357
373
  \`\`\`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"
374
+ aip task update --status done
375
+ aip task update --summary "Completed implementation"
360
376
  \`\`\`
361
377
 
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/\`
378
+ **Note:** All task commands accept optional task slug, but use PWD if not provided. Navigate with \`cd\` first for smoother workflow.
377
379
 
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
- \`\`\`
380
+ ## Work Session
383
381
 
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/\`
382
+ 1. **Read:** \`main.md\` + \`status.md\`
383
+ 2. **Work:** Save data to \`inputs/\`, deliverables to \`outputs/\`
384
+ 3. **Log:** Append to \`status.md\`: \`[timestamp] message\`
385
+ 4. **Complete:** Set status=\`done\`, summarize to project \`status.md\`
388
386
 
389
387
  ## Best Practices
390
388
 
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
- \`\`\`
389
+ **DO:** Concise status entries, update every session
390
+ **DON'T:** Long paragraphs, mix inputs/outputs
404
391
 
405
- **Use status emojis:** \u{1F504} in-progress | \u2705 done | \u26A0\uFE0F blocked | \u274C failed
392
+ **Front-matter:** \`name\`, \`description\`, \`assignee\`, \`status\`, \`created\`
406
393
 
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
394
+ ## Example
443
395
 
444
396
  \`\`\`
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
397
+ $AIP_HOME/projects/my-project/
398
+ \u251C\u2500\u2500 ${X} # Goals, context
399
+ \u251C\u2500\u2500 ${tt} # Activity log
400
+ \u2514\u2500\u2500 ${Gt}/
401
+ \u2514\u2500\u2500 task-1/
402
+ \u251C\u2500\u2500 ${X} # Task definition
403
+ \u2514\u2500\u2500 ${tt} # Updates
480
404
  \`\`\`
481
405
 
482
- ### Example Task Status Flow
483
-
406
+ **Status log:**
484
407
  \`\`\`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.
408
+ [2026-03-17 09:00] Task created: implement-api
409
+ [2026-03-17 10:30] Updated: status=in-progress
410
+ [2026-03-17 12:00] Tests passing
496
411
  \`\`\`
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(We);}});});var Je,Rt,Ft=g(()=>{f();Je=`# AIP Project Structure
509
-
510
- File organization for autonomous AI work.
511
-
512
- ## Directory Layout
513
-
514
- \`\`\`
515
- $AIP_HOME/
516
- \u251C\u2500\u2500 projects/
517
- \u2502 \u251C\u2500\u2500 {project-slug}/
518
- \u2502 \u2502 \u251C\u2500\u2500 main.md # Goals, scope, context
519
- \u2502 \u2502 \u251C\u2500\u2500 status.md # Chronological activity log
520
- \u2502 \u2502 \u251C\u2500\u2500 hooks/ # pre|post-{create,start,update,complete}.*
521
- \u2502 \u2502 \u251C\u2500\u2500 inputs/ # External data (API responses, downloads)
522
- \u2502 \u2502 \u251C\u2500\u2500 outputs/ # Deliverables (reports, code, final files)
523
- \u2502 \u2502 \u251C\u2500\u2500 scripts/ # Automation (bash, python, js)
524
- \u2502 \u2502 \u2514\u2500\u2500 tasks/
525
- \u2502 \u2502 \u2514\u2500\u2500 {task-slug}/
526
- \u2502 \u2502 \u251C\u2500\u2500 main.md # Task definition
527
- \u2502 \u2502 \u251C\u2500\u2500 status.md # Single-line updates
528
- \u2502 \u2502 \u251C\u2500\u2500 hooks/ # Task-level hooks
529
- \u2502 \u2502 \u251C\u2500\u2500 inputs/
530
- \u2502 \u2502 \u251C\u2500\u2500 outputs/
531
- \u2502 \u2502 \u2514\u2500\u2500 scripts/
532
- \u2514\u2500\u2500 agents/
533
- \u2514\u2500\u2500 {agent-slug}/
534
- \u2514\u2500\u2500 main.md # Agent profile
535
- \`\`\`
536
-
537
- ## File Purposes
538
-
539
- ### main.md (Context - Read First)
540
-
541
- **Project main.md:**
542
- - Objectives and success criteria
543
- - Scope and constraints
544
- - Background information
545
- - Requirements
546
-
547
- **Task main.md:**
548
- - Specific deliverable
549
- - Requirements
550
- - Acceptance criteria
551
-
552
- **Frontmatter:**
553
- \`\`\`yaml
554
- ---
555
- name: Clear Title
556
- description: One-line summary
557
- assignee: agent-name
558
- status: pending|in-progress|ongoing|done|blocked
559
- created: YYYY-MM-DD
560
- ---
561
- \`\`\`
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
-
570
- ### status.md (Activity Log - Append Only)
571
-
572
- **Task updates** (each work session):
573
- \`\`\`markdown
574
- ### 2026-03-24 14:30 - Implemented API integration
575
- \u2705 Completed REST API with error handling. Next: write tests.
576
- \`\`\`
577
-
578
- **Project updates** (when task completes):
579
- \`\`\`markdown
580
- ### 2026-03-24 18:00 - Task: api-integration \u2705
581
- Implemented 5 endpoints with validation. Details: tasks/api-integration/
582
- \`\`\`
583
-
584
- **Rules:**
585
- - One line per session
586
- - Include timestamp
587
- - State what's done + what's next
588
- - Use emojis: \u{1F504} in-progress | \u2705 done | \u26A0\uFE0F blocked | \u274C failed
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
-
592
- ### inputs/ (External Data)
593
-
594
- Store here:
595
- - API responses (JSON, XML)
596
- - Downloaded files
597
- - Web scrapes
598
- - Reference documents
599
-
600
- **Naming:** \`api-response-2026-03-24.json\`, \`scraped-docs.md\`
601
-
602
- ### outputs/ (Deliverables)
603
-
604
- Store here:
605
- - Final reports
606
- - Generated code
607
- - Processed data
608
- - Artifacts for external use
609
-
610
- **Naming:** \`final-report.md\`, \`optimized-config.yaml\`
611
-
612
- ### scripts/ (Automation)
613
-
614
- Create when:
615
- - Work is repetitive (3+ times)
616
- - Complex command sequences
617
- - Validation/checking needed
618
- - Data transformations
619
-
620
- **Languages:**
621
- - **Bash:** Simple ops, command chaining
622
- - **Python:** Data processing, API calls
623
- - **JavaScript:** Web scraping, Node.js tooling
624
-
625
- ## Workflow
626
-
627
- ### Starting Work
628
-
629
- 1. **Read context**
630
- \`\`\`bash
631
- cat projects/{project}/main.md
632
- cat projects/{project}/tasks/{task}/main.md
633
- cat projects/{project}/tasks/{task}/status.md
634
- \`\`\`
635
-
636
- 2. **Check recent activity** (status.md)
637
-
638
- 3. **Review inputs/** (existing data)
639
-
640
- ### During Work
641
-
642
- 1. **Create scripts/** if automation helps
643
- 2. **Save external data to inputs/**
644
- 3. **Place deliverables in outputs/**
645
-
646
- ### Completing Work
647
-
648
- 1. **Update task status.md** (final entry)
649
- 2. **Update task main.md** status \u2192 \`done\`
650
- 3. **Append to project status.md** (packed summary)
651
- 4. **Ensure outputs/** has all deliverables
652
-
653
- ## Commands
654
-
655
- \`\`\`bash
656
- # Create
657
- aip project create {name} --description "{desc}"
658
- aip task create {project} {name} --description "{desc}"
659
-
660
- # Navigate
661
- cd $(aip project path {name})
662
- cd $(aip task path {project} {task})
663
-
664
- # Task Lifecycle
665
- aip task start {project} {task} # Sets in-progress, outputs cd command
666
- aip task update {project} {task} --status done
667
- aip task update {project} {task} --status ongoing
668
- aip task update {project} {task} --summary "Completed X"
669
-
670
- # Context
671
- aip task ingest {project} {task} # Full context for AI
672
- \`\`\`
673
-
674
- **Note:** All status changes go through \`task update\`, which runs pre-update/post-update hooks automatically.
675
-
676
- ## Best Practices
677
-
678
- **DO:**
679
- - Keep main.md focused (update rarely)
680
- - Append to status.md religiously
681
- - Use inputs/outputs/ separation
682
- - Create scripts for repetitive work
683
- - Run hooks automatically
684
-
685
- **DON'T:**
686
- - Put status updates in main.md
687
- - Write paragraphs in status.md
688
- - Mix inputs and outputs
689
- - Create scripts for one-time tasks
690
- - Ignore hook failures
691
-
692
- ---
693
-
694
- *Structure enables autonomy. Clean files = clear context = better execution.*
695
- `,Rt=p({description:"Project and task directory layout for autonomous work",options:z$1.object({}),handler:async()=>{console.log(Je);}});});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,qe,T,v=g(()=>{A();D();b();ct=s.join(h.AIP_HOME,c.dirs.PROJECTS),qe={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=qe;});var Lt,Ht=g(()=>{f();b();v();A();Lt=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
698
- /** ${t} hook for ${a} */
412
+ `,Zt=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(x.bin)[0];if(t.mode==="md"){console.log(dt);return}if(t.mode==="claude"){console.log(`---
413
+ name: ${e}
414
+ description: ${x.description}
415
+ ---`),console.log(),console.log(dt);return}if(t.mode==="hermes"){console.log(`---
416
+ name: ${e}
417
+ description: ${x.description}
418
+ version: ${x.version}
419
+ author: ${x.author}
420
+ license: ${x.license}
421
+ ---`),console.log(),console.log(dt);return}}});});var qt,Yt=f(()=>{G();g();b();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(()=>(Q(),mt)),o=`${x.name} ${x.version} -`,r=s.dumpCommandMapLines(e,t);if(!t)console.log(o,"Usage: aip <noun> <verb> [options]"),console.log(r.map(n=>`-> ${n}`).join(`
422
+ `)),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 ft,po,y,$=f(()=>{A();D();b();ft=s.join(h.AIP_HOME,a.dirs.PROJECTS),po={getProjectFromPwd(t=process.cwd()){let e=_.relative(ft,t);if(!e||e.startsWith(".."))return null;let o=e.split(_.sep).filter(Boolean);return o.length===0?null:o[0]},getTaskFromPwd(t=process.cwd()){let e=_.relative(ft,t);if(!e||e.startsWith(".."))return null;let o=e.split(_.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: ${ft}`);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(`
423
+ `)},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,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.join(h.AIP_HOME,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.join(h.AIP_HOME,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.join(h.AIP_HOME,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.")}},y=po;});var Qt,Xt=f(()=>{g();b();$();A();Qt=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}=y.getTargetDir(o),u=s.join(i,a.dirs.HOOKS);await s.ensureDir(u);let d=s.join(u,`${t}${n}`);if(await s.fileExists(d))throw new Error(`Hook already exists: ${d}`);let k;if(r==="ts")k=`#!/usr/bin/env tsx
424
+ /** ${t} hook for ${c} */
699
425
 
700
426
  import { env } from 'node:process'
701
427
 
702
- console.log('Running ${t} hook for ${a}')
428
+ console.log('Running ${t} hook for ${c}')
703
429
  console.log('PROJECT_SLUG:', env.PROJECT_SLUG)
704
430
  if (env.TASK_SLUG) {
705
431
  console.log('TASK_SLUG:', env.TASK_SLUG)
@@ -707,10 +433,10 @@ if (env.TASK_SLUG) {
707
433
 
708
434
  // Exit with non-zero to prevent action (for pre-hooks)
709
435
  // process.exit(1)
710
- `;else if(r==="js")y=`#!/usr/bin/env node
711
- /** ${t} hook for ${a} */
436
+ `;else if(r==="js")k=`#!/usr/bin/env node
437
+ /** ${t} hook for ${c} */
712
438
 
713
- console.log('Running ${t} hook for ${a}')
439
+ console.log('Running ${t} hook for ${c}')
714
440
  console.log('PROJECT_SLUG:', process.env.PROJECT_SLUG)
715
441
  if (process.env.TASK_SLUG) {
716
442
  console.log('TASK_SLUG:', process.env.TASK_SLUG)
@@ -718,10 +444,10 @@ if (process.env.TASK_SLUG) {
718
444
 
719
445
  // Exit with non-zero to prevent action (for pre-hooks)
720
446
  // process.exit(1)
721
- `;else if(r==="sh")y=`#!/bin/bash
722
- # ${t} hook for ${a}
447
+ `;else if(r==="sh")k=`#!/bin/bash
448
+ # ${t} hook for ${c}
723
449
 
724
- echo "Running ${t} hook for ${a}"
450
+ echo "Running ${t} hook for ${c}"
725
451
  echo "PROJECT_SLUG: $PROJECT_SLUG"
726
452
  if [ -n "$TASK_SLUG" ]; then
727
453
  echo "TASK_SLUG: $TASK_SLUG"
@@ -729,24 +455,25 @@ fi
729
455
 
730
456
  # Exit with non-zero to prevent action (for pre-hooks)
731
457
  # exit 1
732
- `;else if(r==="py")y=`#!/usr/bin/env python3
733
- """${t} hook for ${a}"""
458
+ `;else if(r==="py")k=`#!/usr/bin/env python3
459
+ """${t} hook for ${c}"""
734
460
 
735
461
  import os
736
462
 
737
- print(f"Running ${t} hook for ${a}")
463
+ print(f"Running ${t} hook for ${c}")
738
464
  print(f"PROJECT_SLUG: {os.environ.get('PROJECT_SLUG')}")
739
465
  if os.environ.get('TASK_SLUG'):
740
466
  print(f"TASK_SLUG: {os.environ.get('TASK_SLUG')}")
741
467
 
742
468
  # Exit with non-zero to prevent action (for pre-hooks)
743
469
  # sys.exit(1)
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 Ze,x,R=g(()=>{A();D();b();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(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=Ze;});var zt,Kt=g(()=>{f();R();v();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 Ve,S,F=g(()=>{A();v();D();b();Ve={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=Ve;});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();v();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();v();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();D();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();v();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(()=>{v();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();v();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(`
470
+ `;else throw new Error(`Unsupported language: ${r}`);await s.write(d,k);let{chmod:w}=await import('fs/promises');await w(d,493),console.log(`Hook created: ${d}`);}});});var mo,E,F=f(()=>{A();D();b();mo={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.join(h.AIP_HOME,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(u=>{let d=spawn(t,[],{stdio:"inherit",env:c,cwd:_.dirname(t),shell:false});d.on("close",(l,k)=>{l===0?u(true):(console.error(`Hook ${_.basename(t)} failed (code=${l??k})`),u(false));}),d.on("error",l=>{console.error(`Failed to execute hook ${t}: ${l.message}`),u(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))}},E=mo;});var ee,oe=f(()=>{g();F();$();A();ee=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}=y.getTargetDir(e),n={action:t,entityType:r,project:y.getProjectFromPwd()||void 0,task:y.getTaskFromPwd()||void 0};await E.runHooks(o,t,n)||(console.error(`Hook ${t} failed`),process.exit(1)),console.log(`Hook ${t} completed successfully`);}});});var uo,v,H=f(()=>{A();$();D();b();uo={formatLogEntry(t,e){let o=new Date().toISOString().replace("T"," ").replace(/\.\d{3}Z$/,""),r=e?` | ${e}`:"";return `[${o}${r}] ${t}
471
+ `},async appendStatus(t,e,o){let r=s.join(t,a.files.STATUS),n=this.formatLogEntry(e,o);await s.write(r,n);},async appendStatusIfExists(t,e,o){let r=s.join(t,a.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,a.files.STATUS);return await s.fileExists(e)?await s.read(e):""},getCurrentAgent(){return process.env.CURRENT_AGENT},async logTask(t,e){let o=y.getCurrentContext();if(!o.project||!o.task)throw new Error("Not in a task directory");let r=s.join(h.AIP_HOME,a.dirs.PROJECTS,o.project,a.dirs.TASKS,o.task);await this.appendStatus(r,t,e||this.getCurrentAgent());},async logProject(t,e){let o=y.getProjectFromPwd();if(!o)throw new Error("Not in a project directory");let r=s.join(h.AIP_HOME,a.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(([c,u])=>`${c}=${u}`).join(", ");n=`${e}: ${i}`;}await this.appendStatus(t,n,r);}},v=uo;});var re,se=f(()=>{g();b();S();F();H();re=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=m.getProjectDir(n);if(!await E.runHooks(i,"pre-create",{action:"pre-create",entityType:"project"}))throw new Error("Pre-create hook failed, aborting project creation");await m.createProject(n,{name:t,description:e,status:o,assignee:r,created:new Date().toISOString()}),await v.appendStatus(i,`Project created: ${t}`),await E.runHooks(i,"post-create",{action:"post-create",entityType:"project"}),console.log(`Project created: ${n}`),console.log(` Path: ${i}`);}});});var ne,ie=f(()=>{g();$();ne=p({options:z$1.object({}),handler:async()=>{let t=y.getProjectFromPwd();t||(console.error("Not in a project directory"),process.exit(1)),console.log(t);}});});var ce,pe=f(()=>{g();S();ce=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 m.listProjects(),o=[];for(let r of e){let n=await m.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 le,me=f(()=>{g();S();le=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=m.getProjectDir(t);console.log(e);}});});var de,ue=f(()=>{g();S();F();H();$();de=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 c=t||y.getProjectFromPwd();if(!c)throw new Error("No project specified and not in a project directory");let u=m.getProjectDir(c);if(!await E.runHooks(u,"pre-update",{action:"pre-update",entityType:"project"}))throw new Error("Pre-update hook failed, aborting update");let l={};if(e&&(l.name=e),o&&(l.description=o),r&&(l.status=r),n&&(l.assignee=n),Object.keys(l).length===0){console.log("No updates provided");return}await m.updateProject(c,l);let k=Object.entries(l).map(([w,j])=>`${w}=${j}`).join(", ");await v.appendStatus(u,`Updated: ${k}`),i&&await v.appendStatus(u,i),await E.runHooks(u,"post-update",{action:"post-update",entityType:"project"}),console.log(`Project ${c} updated`);}});});var fe,ge=f(()=>{A();g();D();b();fe=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,a.dirs.SKILLS,t),o=s.join(e,a.files.SKILL);if(!await s.fileExists(o))throw new Error(`Skill not found: ${t}
472
+ Expected at: ${o}`);await s.logFiles(o);}});});var ke,he=f(()=>{g();F();b();S();H();ke=p({description:"Create a new task with assignee and initial status",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")}),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})=>{let i=s.slugify(e),c=m.getTaskDir(t,i);if(!await E.runHooksForContext(m.getProjectDir(t),c,"pre-create",{action:"pre-create",entityType:"task",project:t}))throw new Error("Pre-create hook failed, aborting task creation");await m.createTask(t,i,{name:e,description:o,assignee:r,status:n,created:new Date().toISOString()}),await v.appendStatus(c,`Task created: ${e}`),await E.runHooksForContext(m.getProjectDir(t),c,"post-create",{action:"post-create",entityType:"task",project:t}),console.log(`Task created: ${i}`),console.log(` Project: ${t}`),console.log(` Path: ${c}`);}});});var ye,je=f(()=>{g();$();ye=p({description:"Get the current task slug from PWD",options:z$1.object({}),handler:async()=>{let t=y.getTaskFromPwd();t||(console.error("Not in a task directory"),process.exit(1)),console.log(t);}});});var Te,Pe=f(()=>{$();g();S();Te=p({description:"Output full task context (main.md, status.md) 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=y.getCurrentContext(),r=e??o.task;if(!r)throw new Error("Need task slug (or cd into task dir)");let{project:n}=await m.findTask(r,t);await m.ingestTask(n,r);}});});var we,be=f(()=>{g();S();we=p({description:"List tasks, optionally filtered by project, status, or assignee",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)")}),handler:async({project:t,statuses:e,assignee:o,all:r})=>{if(e&&e.length>0){for(let d of e)if(!Y.includes(d))throw new Error(`Invalid status: ${d}. Valid values: ${Y.join(", ")}`)}let n;e&&e.length>0?n=e:r?n=Y:n=bt;let i=t?[t]:await m.listProjects(),c={};for(let d of i){let l=await m.listTasks(d),k=[];for(let w of l){let j=await m.getTask(d,w);j&&(n.length>0&&!n.includes(j.status||"")||o&&j.assignee!==o||k.push({slug:w,name:j.name||w,status:j.status,assignee:j.assignee}));}k.length>0&&(c[d]=k.sort((w,j)=>w.slug.localeCompare(j.slug)));}let u=Object.keys(c).sort();if(u.length===0){console.log("No tasks found");return}for(let d of u){console.log(`
473
+ ${d}:`),console.log("---");for(let l of c[d])console.log(`${l.slug.padEnd(20)} ${l.name?.padEnd(30)||""} ${l.status||""} ${l.assignee||""}`);}}});});var Se,xe=f(()=>{g();S();Se=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 m.findTask(e,t),n=m.getTaskDir(o,r);console.log(n);}});});var nt,ht=f(()=>{$();g();F();S();H();nt=p({description:"Update task 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"),project:z$1.string().optional().describe("Project slug (searches all projects if not provided)"),summary:z$1.string().optional().describe("Optional summary to append to status.md")}),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,summary:c})=>{let u=y.getCurrentContext(),d=e??u.task;if(!d)throw new Error("No task specified (use --task or cd into task dir)");let{project:l}=await m.findTask(d,t),k=m.getTaskDir(l,d);if(!await E.runHooksForContext(m.getProjectDir(l),k,"pre-update",{action:"pre-update",entityType:"task",project:l,task:d}))throw new Error("Pre-update hook failed, aborting update");let j={};if(o&&(j.name=o),r&&(j.description=r),n&&(j.status=n),i&&(j.assignee=i),Object.keys(j).length===0&&!c){console.log("No updates provided");return}if(Object.keys(j).length>0){await m.updateTask(l,d,j);let Ie=Object.entries(j).map(([Ne,Re])=>`${Ne}=${Re}`).join(", ");await v.appendStatus(k,`Updated: ${Ie}`);}c&&await v.appendStatus(k,c),await E.runHooksForContext(m.getProjectDir(l),k,"post-update",{action:"post-update",entityType:"task",project:l,task:d}),console.log(`Task ${d} updated`);}});});var Ee,Ae=f(()=>{$();g();S();ht();Ee=p({description:"Start a task: set status to in-progress, optionally print context",options:z$1.object({project:z$1.string().optional().describe("Project slug (searches all projects if not provided)"),ingest:z$1.boolean().default(false).describe("Also output context for this task")}),args:z$1.object({task:z$1.string().optional().describe("Task slug (default: from $PWD)")}),handler:async({project:t,task:e,ingest:o})=>{let r=y.getCurrentContext(),n=e??r.task;if(!n)throw new Error("No task specified (use --task or cd into task dir)");let{project:i}=await m.findTask(n,t);(await m.getTask(i,n))?.status!=="in-progress"&&await nt.handler({project:i,task:n,status:"in-progress"}),o&&await m.ingestTask(i,n);}});});var ve,$e=f(()=>{g();S();H();ve=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=m.getTaskDir(t,e),r=await m.getTask(t,e),i=(await v.readStatus(o)).split(`
474
+ `).filter(d=>d.startsWith("[")).length,c=[],u=r?.name||e;i>5&&c.push("High status update count - consider breaking into smaller tasks"),u.toLowerCase().includes("implement")&&c.push("Implementation task - check if similar patterns exist to reuse"),u.toLowerCase().includes("create")&&u.toLowerCase().includes("command")&&c.push("Command creation - check existing command patterns in src/commands/"),console.log(`
475
+ === Post-Mortem Analysis ===`),console.log(`Project: ${t}`),console.log(`Task: ${e}`),console.log(`Name: ${u}`),console.log(`Status: ${r?.status||"unknown"}`),console.log(`Status updates: ${i}`),c.length>0?(console.log(`
476
+ Suggestions:`),c.forEach(d=>console.log(` - ${d}`))):console.log(`
750
477
  No specific suggestions - task looks well-scoped`),console.log(`
751
478
  === End Post-Mortem ===
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 Qe,I,J=g(()=>{yt();wt();bt();xt();At();Ct();$t();Nt();Ft();_t();Ht();Kt();Gt();qt();Vt();Xt();te();oe();se();ie();ce();le();de();ge();mt();he();ye();Qe={agent:{create:kt,current:jt,list:Tt,path:Pt,start:St},help:{api:Dt,hooks:Ot,skill:It,structure:Rt,usage:Ut},hook:{create:Lt,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=Qe;});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 Wn=je,Gn=I;s.isMain()&&je(process.argv.slice(2));export{Gn as commands,Wn as default};
479
+ `);}});});var Oe,De=f(()=>{g();b();Oe=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 mt={};_e(mt,{default:()=>U});var ko,U,Q=f(()=>{xt();At();$t();Dt();It();_t();Ft();Mt();Vt();Yt();Xt();oe();se();ie();pe();me();ue();ge();he();je();Pe();be();xe();Ae();ht();$e();De();ko={agent:{create:St,current:Et,list:vt,path:Ot,start:Ct},help:{api:Ut,hooks:Lt,quickstart:Ht,skill:Zt,usage:qt},hook:{create:Qt,run:ee},project:{create:re,current:ne,list:ce,path:le,update:de},skill:{read:fe},task:{create:ke,current:ye,ingest:Te,list:we,path:Se,start:Ee,update:nt},util:{postmortem:ve,read:Oe}},U=ko;});G();Q();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 Ce(t){let[e,o,...r]=t;(e==="--version"||e==="-v")&&(console.log(x.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 mi=Ce,di=U;s.isMain()&&Ce(process.argv.slice(2));export{di as commands,mi as default};
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "ai-projects",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "type": "module",
5
- "description": "AI project management CLI - create and manage projects, tasks, and agents",
5
+ "description": "Useful CLI for AI agents to create and manage projects, tasks, skills and agents",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
8
8
  "bin": {