ai-projects 1.2.0 → 1.4.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 +53 -35
  2. package/dist/index.js +156 -426
  3. package/package.json +8 -6
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;
@@ -121,14 +127,17 @@ declare const commands: {
121
127
  description: zod.ZodString;
122
128
  status: zod.ZodDefault<zod.ZodString>;
123
129
  assignee: zod.ZodOptional<zod.ZodString>;
130
+ summary: zod.ZodOptional<zod.ZodString>;
124
131
  }, "strip", zod.ZodTypeAny, {
125
132
  status: string;
126
133
  description: string;
127
134
  assignee?: string | undefined;
135
+ summary?: string | undefined;
128
136
  }, {
129
137
  description: string;
130
138
  status?: string | undefined;
131
139
  assignee?: string | undefined;
140
+ summary?: string | undefined;
132
141
  }>, zod.ZodObject<{
133
142
  name: zod.ZodString;
134
143
  }, "strip", zod.ZodTypeAny, {
@@ -197,116 +206,125 @@ declare const commands: {
197
206
  readonly task: {
198
207
  readonly create: CommandDef<zod.ZodObject<{
199
208
  description: zod.ZodOptional<zod.ZodString>;
200
- priority: zod.ZodOptional<zod.ZodEnum<["low", "medium", "high"]>>;
201
209
  assignee: zod.ZodOptional<zod.ZodString>;
202
- status: zod.ZodDefault<zod.ZodEnum<["pending", "in-progress", "ongoing", "done"]>>;
210
+ status: zod.ZodDefault<zod.ZodString>;
211
+ summary: zod.ZodOptional<zod.ZodString>;
203
212
  }, "strip", zod.ZodTypeAny, {
204
- status: "pending" | "in-progress" | "ongoing" | "done";
213
+ status: string;
205
214
  description?: string | undefined;
206
215
  assignee?: string | undefined;
207
- priority?: "low" | "medium" | "high" | undefined;
216
+ summary?: string | undefined;
208
217
  }, {
209
- status?: "pending" | "in-progress" | "ongoing" | "done" | undefined;
218
+ status?: string | undefined;
210
219
  description?: string | undefined;
211
220
  assignee?: string | undefined;
212
- priority?: "low" | "medium" | "high" | undefined;
221
+ summary?: string | undefined;
213
222
  }>, zod.ZodObject<{
214
223
  project: zod.ZodString;
215
224
  name: zod.ZodString;
216
225
  }, "strip", zod.ZodTypeAny, {
217
- name: string;
218
226
  project: string;
219
- }, {
220
227
  name: string;
228
+ }, {
221
229
  project: string;
230
+ name: string;
222
231
  }>>;
223
232
  readonly current: CommandDef<zod.ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, zod.ZodObject<any, zod.UnknownKeysParam, zod.ZodTypeAny, {
224
233
  [x: string]: any;
225
234
  }, {
226
235
  [x: string]: any;
227
236
  }>>;
228
- readonly ingest: CommandDef<zod.ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, zod.ZodObject<{
237
+ readonly ingest: CommandDef<zod.ZodObject<{
229
238
  project: zod.ZodOptional<zod.ZodString>;
230
- task: zod.ZodOptional<zod.ZodString>;
231
239
  }, "strip", zod.ZodTypeAny, {
232
240
  project?: string | undefined;
233
- task?: string | undefined;
234
241
  }, {
235
242
  project?: string | undefined;
243
+ }>, zod.ZodObject<{
244
+ task: zod.ZodOptional<zod.ZodString>;
245
+ }, "strip", zod.ZodTypeAny, {
246
+ task?: string | undefined;
247
+ }, {
236
248
  task?: string | undefined;
237
249
  }>>;
238
250
  readonly list: CommandDef<zod.ZodObject<{
239
251
  project: zod.ZodOptional<zod.ZodString>;
240
- status: zod.ZodOptional<zod.ZodString>;
252
+ statuses: zod.ZodDefault<zod.ZodArray<zod.ZodString, "many">>;
241
253
  assignee: zod.ZodOptional<zod.ZodString>;
254
+ all: zod.ZodDefault<zod.ZodBoolean>;
255
+ search: zod.ZodOptional<zod.ZodString>;
242
256
  }, "strip", zod.ZodTypeAny, {
243
- status?: string | undefined;
257
+ statuses: string[];
258
+ all: boolean;
244
259
  project?: string | undefined;
245
260
  assignee?: string | undefined;
261
+ search?: string | undefined;
246
262
  }, {
247
- status?: string | undefined;
248
263
  project?: string | undefined;
249
264
  assignee?: string | undefined;
265
+ statuses?: string[] | undefined;
266
+ all?: boolean | undefined;
267
+ search?: string | undefined;
250
268
  }>, zod.ZodObject<any, zod.UnknownKeysParam, zod.ZodTypeAny, {
251
269
  [x: string]: any;
252
270
  }, {
253
271
  [x: string]: any;
254
272
  }>>;
255
- readonly path: CommandDef<zod.ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, zod.ZodObject<{
256
- project: zod.ZodString;
273
+ readonly path: CommandDef<zod.ZodObject<{
274
+ project: zod.ZodOptional<zod.ZodString>;
275
+ }, "strip", zod.ZodTypeAny, {
276
+ project?: string | undefined;
277
+ }, {
278
+ project?: string | undefined;
279
+ }>, zod.ZodObject<{
257
280
  task: zod.ZodString;
258
281
  }, "strip", zod.ZodTypeAny, {
259
- project: string;
260
282
  task: string;
261
283
  }, {
262
- project: string;
263
284
  task: string;
264
285
  }>>;
265
286
  readonly start: CommandDef<zod.ZodObject<{
287
+ project: zod.ZodOptional<zod.ZodString>;
266
288
  ingest: zod.ZodDefault<zod.ZodBoolean>;
267
289
  }, "strip", zod.ZodTypeAny, {
268
290
  ingest: boolean;
291
+ project?: string | undefined;
269
292
  }, {
293
+ project?: string | undefined;
270
294
  ingest?: boolean | undefined;
271
295
  }>, zod.ZodObject<{
272
- project: zod.ZodString;
273
- task: zod.ZodString;
296
+ task: zod.ZodOptional<zod.ZodString>;
274
297
  }, "strip", zod.ZodTypeAny, {
275
- project: string;
276
- task: string;
298
+ task?: string | undefined;
277
299
  }, {
278
- project: string;
279
- task: string;
300
+ task?: string | undefined;
280
301
  }>>;
281
302
  readonly update: CommandDef<zod.ZodObject<{
282
303
  name: zod.ZodOptional<zod.ZodString>;
283
304
  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"]>>;
305
+ status: zod.ZodOptional<zod.ZodString>;
286
306
  assignee: zod.ZodOptional<zod.ZodString>;
307
+ project: zod.ZodOptional<zod.ZodString>;
287
308
  summary: zod.ZodOptional<zod.ZodString>;
288
309
  }, "strip", zod.ZodTypeAny, {
289
- status?: "pending" | "in-progress" | "ongoing" | "done" | "blocked" | undefined;
310
+ project?: string | undefined;
311
+ status?: string | undefined;
290
312
  description?: string | undefined;
291
313
  name?: string | undefined;
292
314
  assignee?: string | undefined;
293
315
  summary?: string | undefined;
294
- priority?: "low" | "medium" | "high" | undefined;
295
316
  }, {
296
- status?: "pending" | "in-progress" | "ongoing" | "done" | "blocked" | undefined;
317
+ project?: string | undefined;
318
+ status?: string | undefined;
297
319
  description?: string | undefined;
298
320
  name?: string | undefined;
299
321
  assignee?: string | undefined;
300
322
  summary?: string | undefined;
301
- priority?: "low" | "medium" | "high" | undefined;
302
323
  }>, zod.ZodObject<{
303
- project: zod.ZodOptional<zod.ZodString>;
304
324
  task: zod.ZodOptional<zod.ZodString>;
305
325
  }, "strip", zod.ZodTypeAny, {
306
- project?: string | undefined;
307
326
  task?: string | undefined;
308
327
  }, {
309
- project?: string | undefined;
310
328
  task?: string | undefined;
311
329
  }>>;
312
330
  };
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 J from'fs/promises';import T from'lodash';import B from'moment';import M from'path';import {fileURLToPath}from'url';import {inspect}from'util';import Ze from'dotenv';import Ve from'fs';import St from'yaml';var Fe=Object.defineProperty;var f=(t,e)=>()=>(t&&(e=t(t=0)),e);var He=(t,e)=>{for(var o in e)Fe(t,o,{get:e[o],enumerable:true});};var S,W=f(()=>{S={name:"ai-projects",version:"1.4.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","aip","project","task","kanban","cli","agent","automation"],author:"Ariel Flesler <aflesler@gmail.com>",license:"MIT",repository:{type:"git",url:"git+https://github.com/flesler/ai-projects.git"},homepage:"https://github.com/flesler/ai-projects#readme",bugs:{url:"https://github.com/flesler/ai-projects/issues"},engines:{node:">=20.0.0"},dependencies:{dotenv:"^17.3.1",lodash:"^4.17.21",moment:"^2.30.1",tslib:"^2.8.1",yaml:"^2.8.0",zod:"^3.25.76","zod-opts":"^1.0.0"},devDependencies:{"@eslint/js":"^10.0.1","@stylistic/eslint-plugin":"^5.7.0","@types/dotenv":"^8.2.3","@types/eslint":"^9.6.1","@types/lodash":"^4.17.23","@types/moment":"^2.13.0","@types/node":"^25.0.9","@types/source-map-support":"^0.5.10","@typescript-eslint/eslint-plugin":"^8.53.0","@typescript-eslint/parser":"^8.53.0",eslint:"^10.0.3","eslint-plugin-import-x":"^4.16.2","eslint-plugin-unused-imports":"^4.4.1","fast-glob":"^3.3.3",husky:"^9.1.7",rimraf:"^6.0.1","source-map-support":"^0.5.21",tsup:"^8.5.1",tsx:"^4.20.3","types-package-json":"^2.0.39",typescript:"^5.8.3",vitest:"^4.0.17"}};});function p(t){let{description:e,options:o=z$1.object({}),args:r,handler:n}=t,i=o.shape,a={};for(let[u,l]of Object.entries(i))a[u]={type:l};let d=parser().options(a);if(r){let u=r.shape,l=Object.entries(u).map(([g,P])=>({name:g,type:P}));l.length>0&&(d=d.args(l));}return e&&(d=d.description(e)),{description:e,options:o,args:r,parser:d,handler:n,cli:u=>n(d.parse(u))}}var k=f(()=>{});var w,s,b=f(()=>{w={REPO:fileURLToPath(import.meta.url.replace(/\/(dist|src)\/.*/,"/")),join:(...t)=>M.join(...t),onRepo:(...t)=>w.join(w.REPO,...t),async ensureDir(t){await J.mkdir(t,{recursive:true});},async write(t,e){await w.ensureDir(M.dirname(t)),await J.writeFile(t,e,"utf8");},async read(t){return J.readFile(t,"utf8")},async readRepo(...t){return w.read(w.onRepo(...t))},async readMany(...t){return (await Promise.all(t.map(async o=>{if(await w.fileExists(o)){let r=await w.read(o);return `# ${o}
3
3
 
4
4
  ${r}`}return ""}))).filter(Boolean)},async logFiles(...t){let e=await w.readMany(...t);console.log(e.join(`
5
5
 
6
6
  ---
7
7
 
8
- `));},dumpCommandMapLines(t,e){let o=e?j.pick(t,e):t,r=[];for(let[n,i]of 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 w.entriesOf(o))r.push(`${n} {${Object.keys(i).join("|")}}`);return r},async fileExists(t){try{return await J.access(t),!0}catch{return false}},async listDir(t){try{return await J.readdir(t)}catch{return []}},spawn:spawn,cd(t){process.chdir(t);},async exec(t,e){return new Promise(o=>{exec(t,{encoding:"utf8",...e},(r,n,i)=>{let a=r?.code;o({stdout:n??"",stderr:i??"",code:r?typeof a=="number"?a:1:0});});})},noop:()=>{},omitByDeep:(t,e)=>T.isArray(t)?t.map(o=>w.omitByDeep(o,e)):T.isPlainObject(t)?T.mapValues(T.omitBy(t,e),o=>w.omitByDeep(o,e)):t,omitNilsDeep:t=>w.omitByDeep(t,T.isNil),omitUndefinedsDeep:t=>w.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)?w.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,w.memoizeKey),toMS:t=>B.duration(t).asMilliseconds(),toSecs:t=>B.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=>w.oneLine(w.stringify(t)),compactWhitespace:t=>t.replace(/\\n/g,`
9
9
  `).replace(/\r/g,"").replace(/[ \t]*\n[ \t]*/g,`
10
10
  `).replace(/\n{3,}/g,`
11
11
 
12
- `).replace(/ {2,}/g," ").trim(),oneLine:t=>t.replace(/\n/g,"\\n").replace(/\t/g,"\\t").replace(/ +/g," ").trim(),fuzzySearch:(t,e)=>j.includes(j.toLower(t||""),j.toLower(e||"")),elapsed:(t,e=Date.now())=>H.duration(H(e).diff(t||0)),iso:t=>H.utc(t).toISOString(),isoDate:t=>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())=>B.duration(B(e).diff(t||0)),iso:t=>B.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,$=f(()=>{c={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 Ye,bt,U,Qe,y,I=f(()=>{$();Ye=()=>{let t=fileURLToPath(import.meta.url),e=M.dirname(t),o=10;for(let r=0;r<o;r++)try{if(Ve.existsSync(M.join(e,"package.json")))return e;let n=M.dirname(e);if(n===e)break;e=n;}catch{break}return process.cwd()},bt=Ye(),U=process.env.AIP_HOME;U||(Ze.config({path:M.join(bt,".env"),quiet:true}),U=process.env.AIP_HOME);if(!U){U=process.cwd();let t=U.split(M.sep);for(let e of [c.dirs.PROJECTS,c.dirs.SKILLS,c.dirs.AGENTS]){let o=t.indexOf(e);if(o!==-1){U=t.slice(0,o).join(M.sep);break}}}Qe={ROOT:bt,AIP_HOME:U},y=Qe;});var xt,Z,dt,V,Et=f(()=>{b();xt=t=>{let e=t.trim();if(!e.startsWith("---"))return null;let o=e.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);return o?{frontmatter:St.parse(o[1]),content:o[2].trim()}:null},Z=async(t,e,o="")=>{let n=`---
13
+ ${St.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
+ `);},dt=async(t,e)=>{let o=await s.read(t),r=xt(o);if(!r)throw new Error(`No frontmatter found in ${t}`);let n={...r.frontmatter,...e};return await Z(t,n,r.content),n},V=async t=>{let e=await s.read(t),o=xt(e);if(!o)throw new Error(`No frontmatter found in ${t}`);return o.frontmatter};});var K,X,At,$t,Xe,to,m,x=f(()=>{$();I();Et();b();K=(a=>(a.BACKLOG="backlog",a.IN_PROGRESS="in-progress",a.ONGOING="ongoing",a.DONE="done",a.BLOCKED="blocked",a.TO_DO="to-do",a))(K||{}),X=Object.values(K),At=["backlog","in-progress","ongoing"],$t=[c.dirs.HOOKS,c.dirs.INPUTS,c.dirs.OUTPUTS,c.dirs.SCRIPTS],Xe=[c.dirs.TASKS,...$t],to={getProjectDir(t){return s.join(y.AIP_HOME,c.dirs.PROJECTS,t)},getTaskDir(t,e){return s.join(this.getProjectDir(t),c.dirs.TASKS,e)},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(y.AIP_HOME,c.dirs.AGENTS,t)},async listProjects(){let t=s.join(y.AIP_HOME,c.dirs.PROJECTS),e=await s.listDir(t);return (await s.promiseMap(e,async r=>{let n=this.getProjectDir(r);return await s.fileExists(n)&&r!==c.dirs.AGENTS?r:null})).filter(r=>r!==null).sort()},async listTasks(t){let e=s.join(this.getProjectDir(t),c.dirs.TASKS);return await s.fileExists(e)?await s.listDir(e):[]},async listAgents(){let t=s.join(y.AIP_HOME,c.dirs.AGENTS);return await s.fileExists(t)?await s.listDir(t):[]},async createProject(t,e){let o=this.getProjectDir(t);return await s.ensureDir(o),await Promise.all(Xe.map(r=>s.ensureDir(s.join(o,r)))),await Z(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 Promise.all($t.map(n=>s.ensureDir(s.join(r,n)))),await Z(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 Z(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 V(e):null},async getTask(t,e){let o=s.join(this.getTaskDir(t,e),c.files.MAIN);return await s.fileExists(o)?await V(o):null},async getAgent(t){let e=s.join(this.getAgentDir(t),c.files.MAIN);return await s.fileExists(e)?await V(e):null},async updateProject(t,e){let o=s.join(this.getProjectDir(t),c.files.MAIN);return await dt(o,e)},async updateTask(t,e,o){let r=s.join(this.getTaskDir(t,e),c.files.MAIN);if((await V(r))?.status==="ongoing")throw new Error("Cannot update ongoing task. Should be done by user or update manually");return await dt(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=await this.listTasks(t),r=[s.join(e,c.files.MAIN),s.join(e,c.files.STATUS),...o.map(n=>s.join(this.getTaskDir(t,n),c.files.MAIN))];await s.logFiles(...r);},async ingestFiles(t){await s.logFiles(...t);}},m=to;});var vt,Ot=f(()=>{k();b();x();vt=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 Dt,Ct=f(()=>{k();Dt=p({options:z$1.object({}),handler:async()=>{let t=process.env.CURRENT_AGENT;t||(console.error("CURRENT_AGENT not set"),process.exit(1)),console.log(t);}});});var It,Nt=f(()=>{k();x();It=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 Rt,Ut=f(()=>{$();k();I();b();Rt=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(y.AIP_HOME,c.dirs.AGENTS,t),o=s.join(e,c.files.MAIN);if(!await s.fileExists(o))throw new Error(`Agent not found: ${t}
18
+ Expected at: ${o}`);console.log(e);}});});var _t,Lt=f(()=>{$();k();I();b();_t=p({description:"Start an agent: read SOUL.md and AGENTS.md content",options:z$1.object({}),args:z$1.object({name:z$1.string().describe("Agent name (directory name)")}),handler:async({name:t})=>{let e=s.join(y.AIP_HOME,c.dirs.AGENTS,t),o=s.join(e,c.files.MAIN),r=s.join(e,"SOUL.md");if(!await s.fileExists(o))throw new Error(`Agent not found: ${t}
19
+ Expected at: ${o}`);let i=[r,o];await s.logFiles(...i);}});});var Ft,Ht,so,Mt,Kt=f(()=>{k();Ft=t=>{let e=t.shape,o=[];for(let[r,n]of Object.entries(e)){let i=n._def,a="unknown",d,u;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=Ht(i.innerType):i.typeName==="ZodDefault"&&(a=Ht(i.innerType),u=i.defaultValue()),i.description&&(d=i.description);let l=i.typeName!=="ZodOptional"&&i.typeName!=="ZodDefault";o.push({name:r,type:a,required:l,description:d,defaultValue:u});}return o},Ht=t=>{let e=t._def;return e.typeName==="ZodString"?"string":e.typeName==="ZodNumber"?"number":e.typeName==="ZodBoolean"?"boolean":e.typeName==="ZodEnum"?`enum: ${e.values.join(" | ")}`:"unknown"},so=(t,e,o)=>{let r=Ft(o.options),n=o.args?Ft(o.args):[],i=o.description,a=`\`${t} ${e}\``;if(i&&(a+=`: ${i}`),a+=`
20
+ `,r.length>0||n.length>0){let u=[];for(let l of n){let g=l.required?`<${l.name}>`:`[${l.name}]`,P=l.description||"";l.defaultValue!==void 0&&(P+=P?` (default: ${l.defaultValue})`:`(default: ${l.defaultValue})`),u.push(`\xB7 ${g}${P?": "+P:""}`);}for(let l of r){let g=l.description||"";l.defaultValue!==void 0&&(g+=g?` (default: ${l.defaultValue})`:`(default: ${l.defaultValue})`),u.push(`\xB7 --${l.name}${g?": "+g:""}`);}a+=u.join(`
21
21
  `)+`
22
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
23
+ `,a},Mt=p({description:"Print generated CLI reference from command schemas",options:z$1.object({}),handler:async()=>{let{default:t}=await Promise.resolve().then(()=>(tt(),gt)),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 d=n[a];e+=so(r,a,d);}}console.log(e);}});});var io,Gt,zt=f(()=>{k();io=`# 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
+ `,Gt=p({description:"Hook types, env vars, and patterns",options:z$1.object({}),handler:async()=>{console.log(io);}});});var D,co,Wt,Jt=f(()=>{W();k();D=Object.keys(S.bin)[0],co=`# Quick Start
204
+
205
+ ## New Task/Project
206
+
207
+ \`\`\`bash
208
+ # 1. Create project (if needed)
209
+ ${D} project create "my-project" --description "What I'm building"
210
+
211
+ # 2. Create task
212
+ ${D} task create my-project "first-task" --description "Start here"
213
+
214
+ # 3. Navigate to task
215
+ cd $(${D} task path first-task)
216
+
217
+ # 4. Start working (implicit from PWD)
218
+ ${D} task start
219
+ # \u2192 sets status to in-progress
220
+
221
+ # 5. Work session
222
+ # Log progress: ${D} task update --summary "API integration complete"
223
+ # Save: outputs/ to deliver, inputs/ for data
224
+ \`\`\`
225
+
226
+ ## Resuming
227
+
228
+ \`\`\`bash
229
+ # Find your tasks (searches all projects)
230
+ ${D} task list
231
+
232
+ # Navigate to task
233
+ cd $(${D} task path task-slug)
234
+
235
+ # All commands work implicitly from PWD:
236
+ ${D} task start # Start working (sets status to in-progress)
237
+ \`\`\`
238
+
239
+ ## Completing
240
+
241
+ \`\`\`bash
242
+ # Mark done (implicit from PWD)
243
+ ${D} 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
+ `,Wt=p({description:"Quick start guide for new users",options:z$1.object({}),handler:async()=>{console.log(co);}});});var po,lo,Zt,Vt,qt,Yt,Qt,et,ot,kt,Xt,te=f(()=>{W();$();k();x();po=Object.values(K).join("|"),{PROJECTS:lo,TASKS:Zt,HOOKS:Vt,INPUTS:qt,OUTPUTS:Yt,SCRIPTS:Qt}=c.dirs,{MAIN:et,STATUS:ot}=c.files,kt=`# 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/${lo}/{project-slug}/
275
+ \u251C\u2500\u2500 ${et} # Primary context: goals, objectives, scope, data
276
+ \u251C\u2500\u2500 ${ot} # Chronological log of status updates
277
+ \u251C\u2500\u2500 ${Vt}/ # pre|post-{create,start,update,complete}.*
278
+ \u251C\u2500\u2500 ${Yt}/ # Deliverables (reports, code, final files)
279
+ \u251C\u2500\u2500 ${qt}/ # External data (API responses, downloads)
280
+ \u251C\u2500\u2500 ${Qt}/ # Automation (bash/python/js)
281
+ \u2514\u2500\u2500 ${Zt}/
282
+ \u2514\u2500\u2500 {task-slug}/
283
+ \u251C\u2500\u2500 ${et} # Task definition with front-matter
284
+ \u251C\u2500\u2500 ${ot} # Single-line updates per work session
285
+ \u251C\u2500\u2500 ${Vt}/ # Task-level hooks
286
+ \u251C\u2500\u2500 ${Yt}/ # Task-specific deliverables
287
+ \u251C\u2500\u2500 ${qt}/ # Task-specific data files
288
+ \u2514\u2500\u2500 ${Qt}/ # 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: ${po}
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,369 +350,80 @@ 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 ${et} # Goals, context
399
+ \u251C\u2500\u2500 ${ot} # Activity log
400
+ \u2514\u2500\u2500 ${Zt}/
401
+ \u2514\u2500\u2500 task-1/
402
+ \u251C\u2500\u2500 ${et} # Task definition
403
+ \u2514\u2500\u2500 ${ot} # 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
412
+ `,Xt=p({description:"Project management skill for creating and managing projects/tasks",options:z$1.object({mode:z$1.enum(["md","claude","hermes"]).default("md").describe("Output format: md (no header), claude (name+description), hermes (full frontmatter)")}),handler:async t=>{let e=Object.keys(S.bin)[0];if(t.mode==="md"){console.log(kt);return}if(t.mode==="claude"){console.log(`---
413
+ name: ${e}
414
+ description: ${S.description}
415
+ ---`),console.log(),console.log(kt);return}if(t.mode==="hermes"){console.log(`---
416
+ name: ${e}
417
+ description: ${S.description}
418
+ version: ${S.version}
419
+ author: ${S.author}
420
+ license: ${S.license}
421
+ metadata:
422
+ hermes:
423
+ tags: [${S.keywords.join(", ")}]
424
+ ---`),console.log(),console.log(kt);return}}});});var ee,oe=f(()=>{W();k();b();ee=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(()=>(tt(),gt)),o=`${S.name} ${S.version} -`,r=s.dumpCommandMapLines(e,t);if(!t)console.log(o,"Usage: aip <noun> <verb> [options]"),console.log(r.map(n=>`-> ${n}`).join(`
425
+ `)),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 yt,mo,j,v=f(()=>{$();I();b();yt=s.join(y.AIP_HOME,c.dirs.PROJECTS),mo={getProjectFromPwd(t=process.cwd()){let e=M.relative(yt,t);if(!e||e.startsWith(".."))return null;let o=e.split(M.sep).filter(Boolean);return o.length===0?null:o[0]},getTaskFromPwd(t=process.cwd()){let e=M.relative(yt,t);if(!e||e.startsWith(".."))return null;let o=e.split(M.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: ${yt}`);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(`
426
+ `)},getTargetDir(t,e=process.cwd()){let o=this.getCurrentContext(e);if(t==="project"){let r=this.getProjectFromPwd(e);if(!r)throw new Error("Not in a project directory. Use --project flag or cd into a project.");let n=s.join(y.AIP_HOME,c.dirs.PROJECTS,r);return {targetDir:n,projectDir:n,entityType:"project"}}if(t==="task"){if(!o.project||!o.task)throw new Error("Not in a task directory. Use --project and --task flags or cd into a task.");let r=s.join(y.AIP_HOME,c.dirs.PROJECTS,o.project);return {targetDir:s.join(r,c.dirs.TASKS,o.task),projectDir:r,entityType:"task"}}if(o.task&&o.project){let r=s.join(y.AIP_HOME,c.dirs.PROJECTS,o.project);return {targetDir:s.join(r,c.dirs.TASKS,o.task),projectDir:r,entityType:"task"}}if(o.project){let r=s.join(y.AIP_HOME,c.dirs.PROJECTS,o.project);return {targetDir:r,projectDir:r,entityType:"project"}}throw new Error("Not in a project or task directory. Specify --target flag.")}},j=mo;});var re,se=f(()=>{k();b();v();$();re=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}=j.getTargetDir(o),d=s.join(i,c.dirs.HOOKS);await s.ensureDir(d);let u=s.join(d,`${t}${n}`);if(await s.fileExists(u))throw new Error(`Hook already exists: ${u}`);let g;if(r==="ts")g=`#!/usr/bin/env tsx
698
427
  /** ${t} hook for ${a} */
699
428
 
700
429
  import { env } from 'node:process'
@@ -707,7 +436,7 @@ if (env.TASK_SLUG) {
707
436
 
708
437
  // Exit with non-zero to prevent action (for pre-hooks)
709
438
  // process.exit(1)
710
- `;else if(r==="js")y=`#!/usr/bin/env node
439
+ `;else if(r==="js")g=`#!/usr/bin/env node
711
440
  /** ${t} hook for ${a} */
712
441
 
713
442
  console.log('Running ${t} hook for ${a}')
@@ -718,7 +447,7 @@ if (process.env.TASK_SLUG) {
718
447
 
719
448
  // Exit with non-zero to prevent action (for pre-hooks)
720
449
  // process.exit(1)
721
- `;else if(r==="sh")y=`#!/bin/bash
450
+ `;else if(r==="sh")g=`#!/bin/bash
722
451
  # ${t} hook for ${a}
723
452
 
724
453
  echo "Running ${t} hook for ${a}"
@@ -729,7 +458,7 @@ fi
729
458
 
730
459
  # Exit with non-zero to prevent action (for pre-hooks)
731
460
  # exit 1
732
- `;else if(r==="py")y=`#!/usr/bin/env python3
461
+ `;else if(r==="py")g=`#!/usr/bin/env python3
733
462
  """${t} hook for ${a}"""
734
463
 
735
464
  import os
@@ -741,12 +470,13 @@ if os.environ.get('TASK_SLUG'):
741
470
 
742
471
  # Exit with non-zero to prevent action (for pre-hooks)
743
472
  # 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(`
473
+ `;else throw new Error(`Unsupported language: ${r}`);await s.write(u,g);let{chmod:P}=await import('fs/promises');await P(u,493),console.log(`Hook created: ${u}`);}});});var fo,E,G=f(()=>{$();I();b();fo={async findHooks(t,e){let o=s.join(t,c.dirs.HOOKS);if(!await s.fileExists(o))return [];let n=await s.listDir(o),i=`${e}.`;return n.filter(a=>a.startsWith(i)).map(a=>s.join(o,a))},async executeHook(t,e,o){if(!await s.fileExists(t))return true;let n=e.project?s.join(y.AIP_HOME,c.dirs.PROJECTS,e.project):o,i=e.task?s.join(n,c.dirs.TASKS,e.task):"",a={...process.env,HOOK_TYPE:e.action,ENTITY_TYPE:e.entityType,TARGET_DIR:o,PROJECT_DIR:n,...e.project?{PROJECT_SLUG:e.project}:{},...e.task?{TASK_SLUG:e.task,TASK_DIR:i}:{}};return new Promise(d=>{let u=spawn(t,[],{stdio:"inherit",env:a,cwd:M.dirname(t),shell:false});u.on("close",(l,g)=>{l===0?d(true):(console.error(`Hook ${M.basename(t)} failed (code=${l??g})`),d(false));}),u.on("error",l=>{console.error(`Failed to execute hook ${t}: ${l.message}`),d(false);});})},async runHooks(t,e,o){let r=await this.findHooks(t,e),n=e.startsWith("pre-");for(let i of r)if(!await this.executeHook(i,o,t)&&n)return false;return true},async runHooksForContext(t,e,o,r){return !(!await this.runHooks(t,o,r)||e&&!await this.runHooks(e,o,r))}},E=fo;});var ie,ae=f(()=>{k();G();v();$();ie=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}=j.getTargetDir(e),n={action:t,entityType:r,project:j.getProjectFromPwd()||void 0,task:j.getTaskFromPwd()||void 0};await E.runHooks(o,t,n)||(console.error(`Hook ${t} failed`),process.exit(1)),console.log(`Hook ${t} completed successfully`);}});});var go,A,z=f(()=>{$();v();I();b();go={formatLogEntry(t,e){let o=new Date().toISOString().replace("T"," ").replace(/\.\d{3}Z$/,""),r=e?` | ${e}`:"";return `[${o}${r}] ${t}
474
+ `},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=j.getCurrentContext();if(!o.project||!o.task)throw new Error("Not in a task directory");let r=s.join(y.AIP_HOME,c.dirs.PROJECTS,o.project,c.dirs.TASKS,o.task);await this.appendStatus(r,t,e||this.getCurrentAgent());},async logProject(t,e){let o=j.getProjectFromPwd();if(!o)throw new Error("Not in a project directory");let r=s.join(y.AIP_HOME,c.dirs.PROJECTS,o);await this.appendStatus(r,t,e||this.getCurrentAgent());},async logStatusChange(t,e,o,r){let n=e;if(o&&Object.keys(o).length>0){let i=Object.entries(o).map(([a,d])=>`${a}=${d}`).join(", ");n=`${e}: ${i}`;}await this.appendStatus(t,n,r);}},A=go;});var ce,pe=f(()=>{k();G();b();x();z();ce=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"),summary:z$1.string().optional().describe("Override the default summary line to append to status.md")}),args:z$1.object({name:z$1.string().describe("Project name")}),handler:async({name:t,description:e,status:o,assignee:r,summary:n})=>{let i=s.slugify(t),a=m.getProjectDir(i);if(!await E.runHooks(a,"pre-create",{action:"pre-create",entityType:"project"}))throw new Error("Pre-create hook failed, aborting project creation");await m.createProject(i,{name:t,description:e,status:o,assignee:r,created:new Date().toISOString()}),await A.appendStatus(a,n||`Project created: ${t} > status is ${o}`),await E.runHooks(a,"post-create",{action:"post-create",entityType:"project"}),console.log(`Project created: ${i}`),console.log(` Path: ${a}`);}});});var le,me=f(()=>{k();v();le=p({options:z$1.object({}),handler:async()=>{let t=j.getProjectFromPwd();t||(console.error("Not in a project directory"),process.exit(1)),console.log(t);}});});var ue,fe=f(()=>{k();x();ue=p({description:"List all projects, optionally filtered by status",options:z$1.object({status:z$1.string().optional().describe("Filter by status")}),handler:async({status:t})=>{let e=await 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 ge,ke=f(()=>{k();x();ge=p({description:"Output project directory path (for cd)",options:z$1.object({}),args:z$1.object({name:z$1.string().describe("Project name (slug)")}),handler:async({name:t})=>{let e=m.getProjectDir(t);console.log(e);}});});var he,ye=f(()=>{k();x();G();z();v();he=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||j.getProjectFromPwd();if(!a)throw new Error("No project specified and not in a project directory");let d=m.getProjectDir(a);if(!await E.runHooks(d,"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(a,l);let g=Object.entries(l).map(([P,O])=>`${P}=${O}`).join(", ");await A.appendStatus(d,`Updated: ${g}`),i&&await A.appendStatus(d,i),await E.runHooks(d,"post-update",{action:"post-update",entityType:"project"}),console.log(`Project ${a} updated`);}});});var je,Te=f(()=>{$();k();I();b();je=p({description:"Read a skill's SKILL.md file into the console for agent context",options:z$1.object({}),args:z$1.object({name:z$1.string().describe("Skill name (directory name)")}),handler:async({name:t})=>{let e=s.join(y.AIP_HOME,c.dirs.SKILLS,t),o=s.join(e,c.files.SKILL);if(!await s.fileExists(o))throw new Error(`Skill not found: ${t}
475
+ Expected at: ${o}`);await s.logFiles(o);}});});var we,Pe=f(()=>{k();G();b();x();z();we=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"),summary:z$1.string().optional().describe("Override the default summary line to append to status.md")}),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,summary:i})=>{let a=s.slugify(e),d=m.getProjectDir(t),u=m.getTaskDir(t,a);if(!await E.runHooksForContext(d,u,"pre-create",{action:"pre-create",entityType:"task",project:t}))throw new Error("Pre-create hook failed, aborting task creation");await m.createTask(t,a,{name:e,description:o,assignee:r,status:n,created:new Date().toISOString()}),await A.appendStatus(u,i||`Created: ${e}`),await A.appendStatus(d,`Task created: ${a} > status is ${n}`),await E.runHooksForContext(d,u,"post-create",{action:"post-create",entityType:"task",project:t}),console.log(`Task created: ${a}`),console.log(` Project: ${t}`),console.log(` Path: ${u}`);}});});var be,Se=f(()=>{k();v();be=p({description:"Get the current task slug from PWD",options:z$1.object({}),handler:async()=>{let t=j.getTaskFromPwd();t||(console.error("Not in a task directory"),process.exit(1)),console.log(t);}});});var xe,Ee=f(()=>{v();k();x();xe=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=j.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 Ae,$e=f(()=>{k();x();Ae=p({description:"List tasks, optionally filtered by project, status, assignee, or search query",options:z$1.object({project:z$1.string().optional().describe("Project slug (searches all projects if not provided)"),statuses:z$1.array(z$1.string()).default([]).describe("Filter by statuses (multiple allowed)"),assignee:z$1.string().optional().describe("Filter by assignee"),all:z$1.boolean().default(false).describe("Include all tasks (including done/blocked)"),search:z$1.string().optional().describe("Search query (matches task slug or name, case-insensitive)")}),handler:async({project:t,statuses:e,assignee:o,all:r,search:n})=>{if(e&&e.length>0){for(let l of e)if(!X.includes(l))throw new Error(`Invalid status: ${l}. Valid values: ${X.join(", ")}`)}let i;e&&e.length>0?i=e:r?i=X:i=At;let a=t?[t]:await m.listProjects(),d={};for(let l of a){let g=await m.listTasks(l),P=[];for(let O of g){let h=await m.getTask(l,O);if(h&&!(i.length>0&&!i.includes(h.status||""))&&!(o&&h.assignee!==o)){if(n){let H=n.toLowerCase(),lt=O.toLowerCase().includes(H),mt=(h.name||"").toLowerCase().includes(H);if(!lt&&!mt)continue}P.push({slug:O,name:h.name||O,status:h.status,assignee:h.assignee});}}P.length>0&&(d[l]=P.sort((O,h)=>O.slug.localeCompare(h.slug)));}let u=Object.keys(d).sort();if(u.length===0){console.log("No tasks found");return}for(let l of u){console.log(`
476
+ ${l}:`),console.log("---");for(let g of d[l])console.log(`${g.slug.padEnd(20)} ${g.name?.padEnd(30)||""} ${g.status||""} ${g.assignee||""}`);}}});});var ve,Oe=f(()=>{k();x();ve=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 at,wt=f(()=>{v();k();G();x();z();at=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("Override the default summary line 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:a})=>{let d=j.getCurrentContext(),u=e??d.task;if(!u)throw new Error("No task specified (use --task or cd into task dir)");let{project:l}=await m.findTask(u,t),g=m.getTaskDir(l,u),P=m.getProjectDir(l);if(!await E.runHooksForContext(P,g,"pre-update",{action:"pre-update",entityType:"task",project:l,task:u}))throw new Error("Pre-update hook failed, aborting update");let h={};if(o&&(h.name=o),r&&(h.description=r),n&&(h.status=n),i&&(h.assignee=i),Object.keys(h).length===0&&!a){console.log("No updates provided");return}if(Object.keys(h).length>0){await m.updateTask(l,u,h);let lt=Object.entries(h).map(([mt,Le])=>`${mt}=${Le}`).join(", ");await A.appendStatus(g,`Updated: ${lt}`);}let H=a;!a&&(h.status||h.assignee)&&(H=`Updated: ${h.status?` status to ${h.status}`:""}${h.assignee?` assignee to ${h.assignee}`:""}`),H&&await A.appendStatus(g,H),h.status&&await A.appendStatus(P,`Task updated: ${u} > status to ${h.status}`),await E.runHooksForContext(m.getProjectDir(l),g,"post-update",{action:"post-update",entityType:"task",project:l,task:u}),console.log(`Task ${u} updated`);}});});var De,Ce=f(()=>{v();k();x();wt();De=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=j.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 at.handler({project:i,task:n,status:"in-progress"}),o&&await m.ingestTask(i,n);}});});var Ie,Ne=f(()=>{k();x();z();Ie=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 A.readStatus(o)).split(`
477
+ `).filter(u=>u.startsWith("[")).length,a=[],d=r?.name||e;i>5&&a.push("High status update count - consider breaking into smaller tasks"),d.toLowerCase().includes("implement")&&a.push("Implementation task - check if similar patterns exist to reuse"),d.toLowerCase().includes("create")&&d.toLowerCase().includes("command")&&a.push("Command creation - check existing command patterns in src/commands/"),console.log(`
478
+ === Post-Mortem Analysis ===`),console.log(`Project: ${t}`),console.log(`Task: ${e}`),console.log(`Name: ${d}`),console.log(`Status: ${r?.status||"unknown"}`),console.log(`Status updates: ${i}`),a.length>0?(console.log(`
479
+ Suggestions:`),a.forEach(u=>console.log(` - ${u}`))):console.log(`
750
480
  No specific suggestions - task looks well-scoped`),console.log(`
751
481
  === 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};
482
+ `);}});});var Re,Ue=f(()=>{k();b();Re=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 gt={};He(gt,{default:()=>F});var yo,F,tt=f(()=>{Ot();Ct();Nt();Ut();Lt();Kt();zt();Jt();te();oe();se();ae();pe();me();fe();ke();ye();Te();Pe();Se();Ee();$e();Oe();Ce();wt();Ne();Ue();yo={agent:{create:vt,current:Dt,list:It,path:Rt,start:_t},help:{api:Mt,hooks:Gt,quickstart:Wt,skill:Xt,usage:ee},hook:{create:re,run:ie},project:{create:ce,current:le,list:ue,path:ge,update:he},skill:{read:je},task:{create:we,current:be,ingest:xe,list:Ae,path:ve,start:De,update:at},util:{postmortem:Ie,read:Re}},F=yo;});W();tt();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 _e(t){let[e,o,...r]=t;(e==="--version"||e==="-v")&&(console.log(S.version),process.exit(0));try{(!e||!s.isKeyOf(e,F))&&(await F.help.usage.handler({}),process.exit(1));let n=F[e];(!o||!s.isKeyOf(o,n))&&(await F.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 ui=_e,fi=F;s.isMain()&&_e(process.argv.slice(2));export{fi as commands,ui 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.4.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": {
@@ -50,11 +50,13 @@
50
50
  },
51
51
  "keywords": [
52
52
  "ai",
53
- "project-management",
54
- "task-management",
53
+ "aip",
54
+ "project",
55
+ "task",
56
+ "kanban",
55
57
  "cli",
56
- "hermes-agent",
57
- "autonomous-agents"
58
+ "agent",
59
+ "automation"
58
60
  ],
59
61
  "author": "Ariel Flesler <aflesler@gmail.com>",
60
62
  "license": "MIT",