ai-projects 1.8.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -15,7 +15,7 @@ declare function cli(args: string[]): Promise<void>;
15
15
 
16
16
  declare const commands: {
17
17
  readonly agent: {
18
- readonly create: CommandDef<zod.ZodObject<{
18
+ readonly create: CommandDef<ZodObject<{
19
19
  description: zod.ZodString;
20
20
  status: zod.ZodDefault<zod.ZodString>;
21
21
  }, "strip", zod.ZodTypeAny, {
@@ -24,31 +24,31 @@ declare const commands: {
24
24
  }, {
25
25
  description: string;
26
26
  status?: string | undefined;
27
- }>, zod.ZodObject<{
27
+ }>, ZodObject<{
28
28
  name: zod.ZodString;
29
29
  }, "strip", zod.ZodTypeAny, {
30
30
  name: string;
31
31
  }, {
32
32
  name: string;
33
33
  }>>;
34
- readonly current: CommandDef<zod.ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, zod.ZodObject<any, zod.UnknownKeysParam, zod.ZodTypeAny, {
34
+ readonly current: CommandDef<ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, ZodObject<any, zod.UnknownKeysParam, zod.ZodTypeAny, {
35
35
  [x: string]: any;
36
36
  }, {
37
37
  [x: string]: any;
38
38
  }>>;
39
- readonly list: CommandDef<zod.ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, zod.ZodObject<any, zod.UnknownKeysParam, zod.ZodTypeAny, {
39
+ readonly list: CommandDef<ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, ZodObject<any, zod.UnknownKeysParam, zod.ZodTypeAny, {
40
40
  [x: string]: any;
41
41
  }, {
42
42
  [x: string]: any;
43
43
  }>>;
44
- readonly path: CommandDef<zod.ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, zod.ZodObject<{
44
+ readonly path: CommandDef<ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, ZodObject<{
45
45
  name: zod.ZodString;
46
46
  }, "strip", zod.ZodTypeAny, {
47
47
  name: string;
48
48
  }, {
49
49
  name: string;
50
50
  }>>;
51
- readonly start: CommandDef<zod.ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, zod.ZodObject<{
51
+ readonly start: CommandDef<ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, ZodObject<{
52
52
  name: zod.ZodString;
53
53
  }, "strip", zod.ZodTypeAny, {
54
54
  name: string;
@@ -57,33 +57,33 @@ declare const commands: {
57
57
  }>>;
58
58
  };
59
59
  readonly help: {
60
- readonly api: CommandDef<zod.ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, zod.ZodObject<any, zod.UnknownKeysParam, zod.ZodTypeAny, {
60
+ readonly api: CommandDef<ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, ZodObject<any, zod.UnknownKeysParam, zod.ZodTypeAny, {
61
61
  [x: string]: any;
62
62
  }, {
63
63
  [x: string]: any;
64
64
  }>>;
65
- readonly hooks: CommandDef<zod.ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, zod.ZodObject<any, zod.UnknownKeysParam, zod.ZodTypeAny, {
65
+ readonly hooks: CommandDef<ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, ZodObject<any, zod.UnknownKeysParam, zod.ZodTypeAny, {
66
66
  [x: string]: any;
67
67
  }, {
68
68
  [x: string]: any;
69
69
  }>>;
70
- readonly quickstart: CommandDef<zod.ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, zod.ZodObject<any, zod.UnknownKeysParam, zod.ZodTypeAny, {
70
+ readonly quickstart: CommandDef<ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, ZodObject<any, zod.UnknownKeysParam, zod.ZodTypeAny, {
71
71
  [x: string]: any;
72
72
  }, {
73
73
  [x: string]: any;
74
74
  }>>;
75
- readonly skill: CommandDef<zod.ZodObject<{
75
+ readonly skill: CommandDef<ZodObject<{
76
76
  mode: zod.ZodDefault<zod.ZodEnum<["md", "claude", "hermes"]>>;
77
77
  }, "strip", zod.ZodTypeAny, {
78
78
  mode: "md" | "claude" | "hermes";
79
79
  }, {
80
80
  mode?: "md" | "claude" | "hermes" | undefined;
81
- }>, zod.ZodObject<any, zod.UnknownKeysParam, zod.ZodTypeAny, {
81
+ }>, ZodObject<any, zod.UnknownKeysParam, zod.ZodTypeAny, {
82
82
  [x: string]: any;
83
83
  }, {
84
84
  [x: string]: any;
85
85
  }>>;
86
- readonly usage: CommandDef<zod.ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, zod.ZodObject<{
86
+ readonly usage: CommandDef<ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, ZodObject<{
87
87
  name: zod.ZodOptional<zod.ZodString>;
88
88
  }, "strip", zod.ZodTypeAny, {
89
89
  name?: string | undefined;
@@ -92,7 +92,7 @@ declare const commands: {
92
92
  }>>;
93
93
  };
94
94
  readonly hook: {
95
- readonly create: CommandDef<zod.ZodObject<{
95
+ readonly create: CommandDef<ZodObject<{
96
96
  lang: zod.ZodDefault<zod.ZodEnum<["ts", "js", "sh", "py"]>>;
97
97
  target: zod.ZodDefault<zod.ZodEnum<["project", "task"]>>;
98
98
  }, "strip", zod.ZodTypeAny, {
@@ -101,20 +101,20 @@ declare const commands: {
101
101
  }, {
102
102
  lang?: "ts" | "js" | "sh" | "py" | undefined;
103
103
  target?: "project" | "task" | undefined;
104
- }>, zod.ZodObject<{
104
+ }>, ZodObject<{
105
105
  type: zod.ZodEnum<["pre-create", "post-create", "pre-complete", "post-complete", "pre-start", "post-start", "pre-update", "post-update"]>;
106
106
  }, "strip", zod.ZodTypeAny, {
107
107
  type: "pre-create" | "post-create" | "pre-complete" | "post-complete" | "pre-start" | "post-start" | "pre-update" | "post-update";
108
108
  }, {
109
109
  type: "pre-create" | "post-create" | "pre-complete" | "post-complete" | "pre-start" | "post-start" | "pre-update" | "post-update";
110
110
  }>>;
111
- readonly run: CommandDef<zod.ZodObject<{
111
+ readonly run: CommandDef<ZodObject<{
112
112
  target: zod.ZodOptional<zod.ZodEnum<["project", "task"]>>;
113
113
  }, "strip", zod.ZodTypeAny, {
114
114
  target?: "project" | "task" | undefined;
115
115
  }, {
116
116
  target?: "project" | "task" | undefined;
117
- }>, zod.ZodObject<{
117
+ }>, ZodObject<{
118
118
  type: zod.ZodEnum<["pre-create", "post-create", "pre-complete", "post-complete", "pre-start", "post-start", "pre-update", "post-update"]>;
119
119
  }, "strip", zod.ZodTypeAny, {
120
120
  type: "pre-create" | "post-create" | "pre-complete" | "post-complete" | "pre-start" | "post-start" | "pre-update" | "post-update";
@@ -123,7 +123,7 @@ declare const commands: {
123
123
  }>>;
124
124
  };
125
125
  readonly log: {
126
- readonly append: CommandDef<zod.ZodObject<{
126
+ readonly append: CommandDef<ZodObject<{
127
127
  project: zod.ZodOptional<zod.ZodString>;
128
128
  task: zod.ZodOptional<zod.ZodString>;
129
129
  }, "strip", zod.ZodTypeAny, {
@@ -132,14 +132,14 @@ declare const commands: {
132
132
  }, {
133
133
  project?: string | undefined;
134
134
  task?: string | undefined;
135
- }>, zod.ZodObject<{
135
+ }>, ZodObject<{
136
136
  text: zod.ZodString;
137
137
  }, "strip", zod.ZodTypeAny, {
138
138
  text: string;
139
139
  }, {
140
140
  text: string;
141
141
  }>>;
142
- readonly read: CommandDef<zod.ZodObject<{
142
+ readonly read: CommandDef<ZodObject<{
143
143
  project: zod.ZodOptional<zod.ZodString>;
144
144
  task: zod.ZodOptional<zod.ZodString>;
145
145
  }, "strip", zod.ZodTypeAny, {
@@ -148,10 +148,10 @@ declare const commands: {
148
148
  }, {
149
149
  project?: string | undefined;
150
150
  task?: string | undefined;
151
- }>, zod.ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>>;
151
+ }>, ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>>;
152
152
  };
153
153
  readonly project: {
154
- readonly create: CommandDef<zod.ZodObject<{
154
+ readonly create: CommandDef<ZodObject<{
155
155
  description: zod.ZodString;
156
156
  status: zod.ZodDefault<zod.ZodString>;
157
157
  assignee: zod.ZodOptional<zod.ZodString>;
@@ -166,37 +166,37 @@ declare const commands: {
166
166
  status?: string | undefined;
167
167
  assignee?: string | undefined;
168
168
  body?: string | undefined;
169
- }>, zod.ZodObject<{
169
+ }>, ZodObject<{
170
170
  name: zod.ZodString;
171
171
  }, "strip", zod.ZodTypeAny, {
172
172
  name: string;
173
173
  }, {
174
174
  name: string;
175
175
  }>>;
176
- readonly current: CommandDef<zod.ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, zod.ZodObject<any, zod.UnknownKeysParam, zod.ZodTypeAny, {
176
+ readonly current: CommandDef<ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, ZodObject<any, zod.UnknownKeysParam, zod.ZodTypeAny, {
177
177
  [x: string]: any;
178
178
  }, {
179
179
  [x: string]: any;
180
180
  }>>;
181
- readonly list: CommandDef<zod.ZodObject<{
181
+ readonly list: CommandDef<ZodObject<{
182
182
  status: zod.ZodOptional<zod.ZodString>;
183
183
  }, "strip", zod.ZodTypeAny, {
184
184
  status?: string | undefined;
185
185
  }, {
186
186
  status?: string | undefined;
187
- }>, zod.ZodObject<any, zod.UnknownKeysParam, zod.ZodTypeAny, {
187
+ }>, ZodObject<any, zod.UnknownKeysParam, zod.ZodTypeAny, {
188
188
  [x: string]: any;
189
189
  }, {
190
190
  [x: string]: any;
191
191
  }>>;
192
- readonly path: CommandDef<zod.ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, zod.ZodObject<{
192
+ readonly path: CommandDef<ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, ZodObject<{
193
193
  name: zod.ZodString;
194
194
  }, "strip", zod.ZodTypeAny, {
195
195
  name: string;
196
196
  }, {
197
197
  name: string;
198
198
  }>>;
199
- readonly update: CommandDef<zod.ZodObject<{
199
+ readonly update: CommandDef<ZodObject<{
200
200
  name: zod.ZodOptional<zod.ZodString>;
201
201
  description: zod.ZodOptional<zod.ZodString>;
202
202
  status: zod.ZodOptional<zod.ZodString>;
@@ -214,7 +214,7 @@ declare const commands: {
214
214
  name?: string | undefined;
215
215
  assignee?: string | undefined;
216
216
  body?: string | undefined;
217
- }>, zod.ZodObject<{
217
+ }>, ZodObject<{
218
218
  project: zod.ZodOptional<zod.ZodString>;
219
219
  }, "strip", zod.ZodTypeAny, {
220
220
  project?: string | undefined;
@@ -223,7 +223,7 @@ declare const commands: {
223
223
  }>>;
224
224
  };
225
225
  readonly skill: {
226
- readonly read: CommandDef<zod.ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, zod.ZodObject<{
226
+ readonly read: CommandDef<ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, ZodObject<{
227
227
  name: zod.ZodString;
228
228
  }, "strip", zod.ZodTypeAny, {
229
229
  name: string;
@@ -232,7 +232,7 @@ declare const commands: {
232
232
  }>>;
233
233
  };
234
234
  readonly task: {
235
- readonly create: CommandDef<zod.ZodObject<{
235
+ readonly create: CommandDef<ZodObject<{
236
236
  description: zod.ZodOptional<zod.ZodString>;
237
237
  assignee: zod.ZodOptional<zod.ZodString>;
238
238
  status: zod.ZodDefault<zod.ZodString>;
@@ -247,7 +247,7 @@ declare const commands: {
247
247
  description?: string | undefined;
248
248
  assignee?: string | undefined;
249
249
  body?: string | undefined;
250
- }>, zod.ZodObject<{
250
+ }>, ZodObject<{
251
251
  project: zod.ZodString;
252
252
  name: zod.ZodString;
253
253
  }, "strip", zod.ZodTypeAny, {
@@ -257,25 +257,25 @@ declare const commands: {
257
257
  project: string;
258
258
  name: string;
259
259
  }>>;
260
- readonly current: CommandDef<zod.ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, zod.ZodObject<any, zod.UnknownKeysParam, zod.ZodTypeAny, {
260
+ readonly current: CommandDef<ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, ZodObject<any, zod.UnknownKeysParam, zod.ZodTypeAny, {
261
261
  [x: string]: any;
262
262
  }, {
263
263
  [x: string]: any;
264
264
  }>>;
265
- readonly ingest: CommandDef<zod.ZodObject<{
265
+ readonly ingest: CommandDef<ZodObject<{
266
266
  project: zod.ZodOptional<zod.ZodString>;
267
267
  }, "strip", zod.ZodTypeAny, {
268
268
  project?: string | undefined;
269
269
  }, {
270
270
  project?: string | undefined;
271
- }>, zod.ZodObject<{
271
+ }>, ZodObject<{
272
272
  task: zod.ZodOptional<zod.ZodString>;
273
273
  }, "strip", zod.ZodTypeAny, {
274
274
  task?: string | undefined;
275
275
  }, {
276
276
  task?: string | undefined;
277
277
  }>>;
278
- readonly list: CommandDef<zod.ZodObject<{
278
+ readonly list: CommandDef<ZodObject<{
279
279
  project: zod.ZodOptional<zod.ZodString>;
280
280
  statuses: zod.ZodDefault<zod.ZodArray<zod.ZodString, "many">>;
281
281
  assignee: zod.ZodOptional<zod.ZodString>;
@@ -293,25 +293,25 @@ declare const commands: {
293
293
  statuses?: string[] | undefined;
294
294
  all?: boolean | undefined;
295
295
  search?: string | undefined;
296
- }>, zod.ZodObject<any, zod.UnknownKeysParam, zod.ZodTypeAny, {
296
+ }>, ZodObject<any, zod.UnknownKeysParam, zod.ZodTypeAny, {
297
297
  [x: string]: any;
298
298
  }, {
299
299
  [x: string]: any;
300
300
  }>>;
301
- readonly path: CommandDef<zod.ZodObject<{
301
+ readonly path: CommandDef<ZodObject<{
302
302
  project: zod.ZodOptional<zod.ZodString>;
303
303
  }, "strip", zod.ZodTypeAny, {
304
304
  project?: string | undefined;
305
305
  }, {
306
306
  project?: string | undefined;
307
- }>, zod.ZodObject<{
307
+ }>, ZodObject<{
308
308
  task: zod.ZodString;
309
309
  }, "strip", zod.ZodTypeAny, {
310
310
  task: string;
311
311
  }, {
312
312
  task: string;
313
313
  }>>;
314
- readonly start: CommandDef<zod.ZodObject<{
314
+ readonly start: CommandDef<ZodObject<{
315
315
  project: zod.ZodOptional<zod.ZodString>;
316
316
  ingest: zod.ZodDefault<zod.ZodBoolean>;
317
317
  }, "strip", zod.ZodTypeAny, {
@@ -320,14 +320,14 @@ declare const commands: {
320
320
  }, {
321
321
  project?: string | undefined;
322
322
  ingest?: boolean | undefined;
323
- }>, zod.ZodObject<{
323
+ }>, ZodObject<{
324
324
  task: zod.ZodOptional<zod.ZodString>;
325
325
  }, "strip", zod.ZodTypeAny, {
326
326
  task?: string | undefined;
327
327
  }, {
328
328
  task?: string | undefined;
329
329
  }>>;
330
- readonly update: CommandDef<zod.ZodObject<{
330
+ readonly update: CommandDef<ZodObject<{
331
331
  name: zod.ZodOptional<zod.ZodString>;
332
332
  description: zod.ZodOptional<zod.ZodString>;
333
333
  status: zod.ZodOptional<zod.ZodString>;
@@ -348,7 +348,7 @@ declare const commands: {
348
348
  name?: string | undefined;
349
349
  assignee?: string | undefined;
350
350
  body?: string | undefined;
351
- }>, zod.ZodObject<{
351
+ }>, ZodObject<{
352
352
  task: zod.ZodOptional<zod.ZodString>;
353
353
  }, "strip", zod.ZodTypeAny, {
354
354
  task?: string | undefined;
@@ -357,7 +357,7 @@ declare const commands: {
357
357
  }>>;
358
358
  };
359
359
  readonly util: {
360
- readonly read: CommandDef<zod.ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, zod.ZodObject<{
360
+ readonly read: CommandDef<ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, ZodObject<{
361
361
  paths: zod.ZodArray<zod.ZodString, "many">;
362
362
  }, "strip", zod.ZodTypeAny, {
363
363
  paths: string[];
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'dotenv';import it from'path';import {spawn,exec}from'child_process';import G from'fs/promises';import w from'lodash';import Z from'moment';import {fileURLToPath}from'url';import {inspect}from'util';import Ot from'yaml';import ut from'fs';var Me=Object.defineProperty;var f=(t,e)=>()=>(t&&(e=t(t=0)),e);var ze=(t,e)=>{for(var o in e)Me(t,o,{get:e[o],enumerable:true});};var x,J=f(()=>{x={name:"ai-projects",version:"1.8.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:full":"npm run build:map && tsup","build:check":"tsc --noEmit","build:watch":"npm run build:code -- --watch","build:clean":"rimraf dist/*",start:"dist/index.js",dev:'npm run build:watch -- --onSuccess "dist/index.js"',cli:"npm run build && npm start --",ts:"tsx",vitest:"VITE_CJS_IGNORE_WARNING=true vitest",test:"npm run test:types && npm run test:unit","test:unit":"npm run vitest -- run","test:types:test":"tsc -p tsconfig.test.json --incremental --tsBuildInfoFile test.tsbuildinfo","test:types:bin":"tsc -p bin/tsconfig.json --incremental --tsBuildInfoFile bin.tsbuildinfo","test:types":"npm run test:types:test && npm run test:types:bin","test:full":"npm run lint:full && npm run test",eslint:"eslint --cache",lint:"npm run eslint -- '{src,bin}/**/*.ts'","lint:fix":"npm run lint -- --fix","lint:full":"npm run build:check && npm run test:types:bin && npm run lint:fix","lint:full:silent":"npm run -s lint:full && echo LINT OK",prepare:'[ "$CI" != "true" ] && [ -d node_modules/husky ] && husky || true',prepack:"npm run test:full && npm run build:full","publish:dry":"npm pack --dry-run","version:patch":"npm version patch","version:minor":"npm version minor","version:major":"npm version major","agent:stop":"npm run -s lint:full:silent"},keywords:["ai","aip","project","task","kanban","cli","agent","automation"],author:"Ariel Flesler <aflesler@gmail.com>",license:"MIT",repository:{type:"git",url:"git+https://github.com/flesler/ai-projects.git"},homepage:"https://github.com/flesler/ai-projects#readme",bugs:{url:"https://github.com/flesler/ai-projects/issues"},engines:{node:">=20.0.0"},dependencies:{dotenv:"^17.3.1",lodash:"^4.17.21",moment:"^2.30.1",tslib:"^2.8.1",yaml:"^2.8.0",zod:"^3.25.76","zod-opts":"^1.0.0"},devDependencies:{"@eslint/js":"^10.0.1","@stylistic/eslint-plugin":"^5.7.0","@types/dotenv":"^8.2.3","@types/eslint":"^9.6.1","@types/lodash":"^4.17.23","@types/moment":"^2.13.0","@types/node":"^25.0.9","@types/source-map-support":"^0.5.10","@typescript-eslint/eslint-plugin":"^8.53.0","@typescript-eslint/parser":"^8.53.0",eslint:"^10.0.3","eslint-plugin-import-x":"^4.16.2","eslint-plugin-unused-imports":"^4.4.1","fast-glob":"^3.3.3",husky:"^9.1.7",rimraf:"^6.0.1","source-map-support":"^0.5.21",tsup:"^8.5.1",tsx:"^4.20.3","types-package-json":"^2.0.39",typescript:"^5.8.3",vitest:"^4.0.17"}};});function l(t){let{description:e,options:o=z$1.object({}),args:r,handler:n}=t,i=o.shape,a={};for(let[d,m]of Object.entries(i))a[d]={type:m};let p=parser().options(a);if(r){let d=r.shape,m=Object.entries(d).map(([g,T])=>({name:g,type:T}));m.length>0&&(p=p.args(m));}return e&&(p=p.description(e)),{description:e,options:o,args:r,parser:p,handler:n,cli:d=>n(p.parse(d))}}var k=f(()=>{});var c,P=f(()=>{c={dirs:{PROJECTS:"projects",SKILLS:"skills",AGENTS:"agents",TASKS:"tasks",INPUTS:"inputs",OUTPUTS:"outputs",HOOKS:"hooks",SCRIPTS:"scripts"},files:{MAIN:"main.md",LOG:"log.tsv",SKILL:"SKILL.md"},hookTypes:["pre-create","post-create","pre-complete","post-complete","pre-start","post-start","pre-update","post-update"],languages:["ts","js","sh","py"],targets:["project","task"]};});var V,Ze,S,L=f(()=>{P();V=process.env.AIP_HOME;if(!V){V=process.cwd();let t=V.split(it.sep);for(let e of [c.dirs.PROJECTS,c.dirs.SKILLS,c.dirs.AGENTS]){let o=t.indexOf(e);if(o!==-1){V=t.slice(0,o).join(it.sep);break}}}Ze={AIP_HOME:V,ERROR_LOG:process.env.AIP_ERROR_LOG},S=Ze;});var j,s,y=f(()=>{L();j={REPO:fileURLToPath(import.meta.url.replace(/\/(dist|src)\/.*/,"/")),join:(...t)=>it.join(...t),onRepo:(...t)=>j.join(j.REPO,...t),joinHome:(...t)=>j.join(S.AIP_HOME,...t),async ensureDir(t){await G.mkdir(t,{recursive:true});},async write(t,e){await j.ensureDir(it.dirname(t)),await G.writeFile(t,e,"utf8");},async append(t,e){await j.ensureDir(it.dirname(t)),await G.appendFile(t,e,"utf8");},async read(t){return G.readFile(t,"utf8")},async readRepo(...t){return j.read(j.onRepo(...t))},async readMany(...t){return (await Promise.all(t.map(async o=>{let r=await j.fileExists(o)?await j.read(o):"ERROR: File not found";return `# ${o}
2
+ import {z as z$1}from'zod';import {parser}from'zod-opts';import'dotenv';import it from'path';import {spawn,exec}from'child_process';import G from'fs/promises';import w from'lodash';import Z from'moment';import {fileURLToPath}from'url';import {inspect}from'util';import Et from'yaml';import ut from'fs';var Me=Object.defineProperty;var f=(t,e)=>()=>(t&&(e=t(t=0)),e);var ze=(t,e)=>{for(var o in e)Me(t,o,{get:e[o],enumerable:true});};var x,J=f(()=>{x={name:"ai-projects",version:"1.9.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:full":"npm run build:map && tsup","build:check":"tsc --noEmit","build:watch":"npm run build:code -- --watch","build:clean":"rimraf dist/*",start:"dist/index.js",dev:'npm run build:watch -- --onSuccess "dist/index.js"',cli:"npm run build && npm start --",ts:"tsx",vitest:"VITE_CJS_IGNORE_WARNING=true vitest",test:"npm run test:types && npm run test:unit","test:unit":"npm run vitest -- run","test:types:test":"tsc -p tsconfig.test.json --incremental --tsBuildInfoFile test.tsbuildinfo","test:types:bin":"tsc -p bin/tsconfig.json --incremental --tsBuildInfoFile bin.tsbuildinfo","test:types":"npm run test:types:test && npm run test:types:bin","test:full":"npm run lint:full && npm run test",eslint:"eslint --cache",lint:"npm run eslint -- '{src,bin}/**/*.ts'","lint:fix":"npm run lint -- --fix","lint:full":"npm run build:check && npm run test:types:bin && npm run lint:fix","lint:full:silent":"npm run -s lint:full && echo LINT OK",prepare:'[ "$CI" != "true" ] && [ -d node_modules/husky ] && husky || true',prepack:"npm run test:full && npm run build:full","publish:dry":"npm pack --dry-run","version:patch":"npm version patch","version:minor":"npm version minor","version:major":"npm version major","agent:stop":"npm run -s lint:full:silent"},keywords:["ai","aip","project","task","kanban","cli","agent","automation"],author:"Ariel Flesler <aflesler@gmail.com>",license:"MIT",repository:{type:"git",url:"git+https://github.com/flesler/ai-projects.git"},homepage:"https://github.com/flesler/ai-projects#readme",bugs:{url:"https://github.com/flesler/ai-projects/issues"},engines:{node:">=20.0.0"},dependencies:{dotenv:"^17.3.1",lodash:"^4.17.21",moment:"^2.30.1",tslib:"^2.8.1",yaml:"^2.8.0",zod:"^3.25.76","zod-opts":"^1.0.0"},devDependencies:{"@eslint/js":"^10.0.1","@stylistic/eslint-plugin":"^5.7.0","@types/dotenv":"^8.2.3","@types/eslint":"^9.6.1","@types/lodash":"^4.17.23","@types/moment":"^2.13.0","@types/node":"^25.0.9","@types/source-map-support":"^0.5.10","@typescript-eslint/eslint-plugin":"^8.53.0","@typescript-eslint/parser":"^8.53.0",eslint:"^10.0.3","eslint-plugin-import-x":"^4.16.2","eslint-plugin-unused-imports":"^4.4.1","fast-glob":"^3.3.3",husky:"^9.1.7",rimraf:"^6.0.1","source-map-support":"^0.5.21",tsup:"^8.5.1",tsx:"^4.20.3","types-package-json":"^2.0.39",typescript:"^5.8.3",vitest:"^4.0.17"}};});function p(t){let{description:e,options:o=z$1.object({}),args:r,handler:s}=t,i=o.shape,a={};for(let[d,m]of Object.entries(i))a[d]={type:m};let l=parser().options(a);if(r){let d=r.shape,m=Object.entries(d).map(([g,T])=>({name:g,type:T}));m.length>0&&(l=l.args(m));}return e&&(l=l.description(e)),{description:e,options:o,args:r,parser:l,handler:s,cli:d=>s(l.parse(d))}}var k=f(()=>{});var c,P=f(()=>{c={dirs:{PROJECTS:"projects",SKILLS:"skills",AGENTS:"agents",TASKS:"tasks",INPUTS:"inputs",OUTPUTS:"outputs",HOOKS:"hooks",SCRIPTS:"scripts"},files:{MAIN:"main.md",LOG:"log.tsv",SKILL:"SKILL.md"},hookTypes:["pre-create","post-create","pre-complete","post-complete","pre-start","post-start","pre-update","post-update"],languages:["ts","js","sh","py"],targets:["project","task"]};});function Ze(t){return t.startsWith("~")?it.join(process.env.HOME??"",t.slice(1)):t}var W,Ve,S,L=f(()=>{P();W=process.env.AIP_HOME?Ze(process.env.AIP_HOME):void 0;if(!W){W=process.cwd();let t=W.split(it.sep);for(let e of [c.dirs.PROJECTS,c.dirs.SKILLS,c.dirs.AGENTS]){let o=t.indexOf(e);if(o!==-1){W=t.slice(0,o).join(it.sep);break}}}Ve={AIP_HOME:W,ERROR_LOG:process.env.AIP_ERROR_LOG},S=Ve;});var j,n,y=f(()=>{L();j={REPO:fileURLToPath(import.meta.url.replace(/\/(dist|src)\/.*/,"/")),join:(...t)=>it.join(...t),onRepo:(...t)=>j.join(j.REPO,...t),joinHome:(...t)=>j.join(S.AIP_HOME,...t),async ensureDir(t){await G.mkdir(t,{recursive:true});},async write(t,e){await j.ensureDir(it.dirname(t)),await G.writeFile(t,e,"utf8");},async append(t,e){await j.ensureDir(it.dirname(t)),await G.appendFile(t,e,"utf8");},async read(t){return G.readFile(t,"utf8")},async readRepo(...t){return j.read(j.onRepo(...t))},async readMany(...t){return (await Promise.all(t.map(async o=>{let r=await j.fileExists(o)?await j.read(o):"ERROR: File not found";return `# ${o}
3
3
 
4
4
  ${r}`}))).filter(Boolean)},async logFiles(...t){let e=await j.readMany(...t);console.log(e.join(`
5
5
 
6
6
  ---
7
7
 
8
- `));},dumpCommandMapLines(t,e){let o=e?w.pick(t,e):t,r=[];for(let[n,i]of j.entriesOf(o))r.push(`${n} {${Object.keys(i).join("|")}}`);return r},async fileExists(t){try{return await G.access(t),!0}catch{return false}},async listDir(t){try{return await G.readdir(t)}catch{return []}},spawn:spawn,cd(t){process.chdir(t);},async exec(t,e){return new Promise(o=>{exec(t,{encoding:"utf8",...e},(r,n,i)=>{let a=r?.code;o({stdout:n??"",stderr:i??"",code:r?typeof a=="number"?a:1:0});});})},noop:()=>{},omitByDeep:(t,e)=>w.isArray(t)?t.map(o=>j.omitByDeep(o,e)):w.isPlainObject(t)?w.mapValues(w.omitBy(t,e),o=>j.omitByDeep(o,e)):t,omitNilsDeep:t=>j.omitByDeep(t,w.isNil),omitUndefinedsDeep:t=>j.omitByDeep(t,w.isUndefined),cloneDeep:t=>w.cloneDeep(t),int:t=>Number.parseInt(t,10),keysOf:t=>Object.keys(t),entriesOf:t=>Object.entries(t),isKeyOf:(t,e)=>!w.isNil(t)&&t in e,typeOf:t=>typeof t,never:{},undef:t=>t??void 0,toNull:t=>t??null,same:t=>t,notNil:t=>{if(w.isNil(t))throw new Error(`Received unexpected ${t} value`);return t},randomInt:(t,e)=>Math.floor(Math.random()*(e-t+1))+t,promise:()=>{let t,e=new Promise((o,r)=>{t={resolve:o,reject:r};});return w.extend(e,t)},isPromise:t=>w.isObject(t)&&"catch"in t,delay:t=>{let e=w.isObject(t)?j.toMS(t):t;return new Promise(o=>setTimeout(o,e))},promiseMap:(t,e)=>Promise.all(t.map(e)),promiseEach:(t,e)=>Promise.all(t.map(e)).then(()=>{}),memoize:t=>w.memoize(t,j.memoizeKey),toMS:t=>Z.duration(t).asMilliseconds(),toSecs:t=>Z.duration(t).asSeconds(),inspect:(t,e)=>inspect(t,{colors:false,showHidden:false,depth:null,compact:true,breakLength:1/0,...e}),stringify(t,e,o){let r=new WeakSet;return JSON.stringify(t,(n,i)=>{if(w.isObject(i)){if(r.has(i))return "[Circular]";r.add(i);}return w.isFunction(e)?e(n,i):i},o)},dump:t=>j.oneLine(j.stringify(t)),compactWhitespace:t=>t.replace(/\\n/g,`
8
+ `));},dumpCommandMapLines(t,e){let o=e?w.pick(t,e):t,r=[];for(let[s,i]of j.entriesOf(o))r.push(`${s} {${Object.keys(i).join("|")}}`);return r},async fileExists(t){try{return await G.access(t),!0}catch{return false}},async listDir(t){try{return await G.readdir(t)}catch{return []}},spawn:spawn,cd(t){process.chdir(t);},async exec(t,e){return new Promise(o=>{exec(t,{encoding:"utf8",...e},(r,s,i)=>{let a=r?.code;o({stdout:s??"",stderr:i??"",code:r?typeof a=="number"?a:1:0});});})},noop:()=>{},omitByDeep:(t,e)=>w.isArray(t)?t.map(o=>j.omitByDeep(o,e)):w.isPlainObject(t)?w.mapValues(w.omitBy(t,e),o=>j.omitByDeep(o,e)):t,omitNilsDeep:t=>j.omitByDeep(t,w.isNil),omitUndefinedsDeep:t=>j.omitByDeep(t,w.isUndefined),cloneDeep:t=>w.cloneDeep(t),int:t=>Number.parseInt(t,10),keysOf:t=>Object.keys(t),entriesOf:t=>Object.entries(t),isKeyOf:(t,e)=>!w.isNil(t)&&t in e,typeOf:t=>typeof t,never:{},undef:t=>t??void 0,toNull:t=>t??null,same:t=>t,notNil:t=>{if(w.isNil(t))throw new Error(`Received unexpected ${t} value`);return t},randomInt:(t,e)=>Math.floor(Math.random()*(e-t+1))+t,promise:()=>{let t,e=new Promise((o,r)=>{t={resolve:o,reject:r};});return w.extend(e,t)},isPromise:t=>w.isObject(t)&&"catch"in t,delay:t=>{let e=w.isObject(t)?j.toMS(t):t;return new Promise(o=>setTimeout(o,e))},promiseMap:(t,e)=>Promise.all(t.map(e)),promiseEach:(t,e)=>Promise.all(t.map(e)).then(()=>{}),memoize:t=>w.memoize(t,j.memoizeKey),toMS:t=>Z.duration(t).asMilliseconds(),toSecs:t=>Z.duration(t).asSeconds(),inspect:(t,e)=>inspect(t,{colors:false,showHidden:false,depth:null,compact:true,breakLength:1/0,...e}),stringify(t,e,o){let r=new WeakSet;return JSON.stringify(t,(s,i)=>{if(w.isObject(i)){if(r.has(i))return "[Circular]";r.add(i);}return w.isFunction(e)?e(s,i):i},o)},dump:t=>j.oneLine(j.stringify(t)),compactWhitespace:t=>t.replace(/\\n/g,`
9
9
  `).replace(/\r/g,"").replace(/[ \t]*\n[ \t]*/g,`
10
10
  `).replace(/\n{3,}/g,`
11
11
 
12
- `).replace(/ {2,}/g," ").trim(),oneLine:t=>t.replace(/\n/g,"\\n").replace(/\t/g,"\\t").replace(/ +/g," ").trim(),fuzzySearch:(t,e)=>w.includes(w.toLower(t||""),w.toLower(e||"")),elapsed:(t,e=Date.now())=>Z.duration(Z(e).diff(t||0)),iso:t=>Z.utc(t).toISOString(),isoDate:t=>j.iso(t).slice(0,10),memoizeKey:(...t)=>t.join(""),exit:(t=0)=>{process.exit(t);},set:(t,e,o)=>(t[e]=o,t),run:async t=>{try{await t(),process.exit(0);}catch(e){console.error(e),process.exit(1);}},isMain:()=>{let t=process.argv[1]||"";return t.includes("/index.")||t.endsWith("/bin/aip")},errorMessage:t=>t instanceof Error?t.message:String(t),slugify:t=>t.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,""),matchesSearch:(t,e)=>{let o=e?.toLowerCase().split(/\s+/).filter(Boolean);if(!o?.length)return true;let r=t.toLowerCase();return o.every(n=>r.includes(n))}},s=j;});var Xe,rt,to,Et=f(()=>{y();Xe=" ",rt=class{filename;context;constructor(t){this.filename=t;}log=(t,e,...o)=>{this.filename&&!this.context&&(this.context=`<${to(this.filename)}>`),this.context&&o.unshift(this.context);let[r,n]=new Date().toISOString().split(/[T.]/);o.unshift(e,r,n);let i=o.map(this.stringify).map(this.sanitize).join(Xe);return t?console.error(i):console.log(i),i};stringify=t=>{if(!t)return "-";if(w.isNumber(t))return `${t}`;if(w.isError(t))return s.oneLine(t.message||"");if(w.isFunction(t))return s.oneLine(t.toString());if(w.isObject(t)||w.isArray(t))try{return s.dump(t)}catch(e){return `Failed to stringify: ${e.message}`}return w.toString(t)};sanitize=t=>t.replace(/ {2,}/g," ");debug=(...t)=>{this.log(false,"[DEBUG]",...t);};info=(...t)=>{this.log(false,"[INFO]",...t);};warn=(...t)=>{this.log(true,"[WARN]",...t);};error=(...t)=>{this.log(true,"[ERROR]",...t);}},to=t=>{let e=t.split(it.sep),[o,r,...n]=e.reverse();if(!n.length)return t;let i=it.basename(o,".js").replace(".ts","");if(i==="index")return r;let a=e.indexOf("commands");if(a!==-1&&a<e.length-1){let p=e.slice(a+1);if(p.length>=2){let[d,m]=p;return `<${d}/${m.replace(".js","").replace(".ts","")}>`}}return i};});var eo,st,M,gt,W,At=f(()=>{y();Et();eo=new rt,st=t=>{let e=t.trim();if(!e.startsWith("---"))return null;let o=e.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);return o?{frontmatter:Ot.parse(o[1]),content:o[2].trim()}:null},M=async(t,e,o="")=>{let n=`---
13
- ${Ot.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)=>w.includes(w.toLower(t||""),w.toLower(e||"")),elapsed:(t,e=Date.now())=>Z.duration(Z(e).diff(t||0)),iso:t=>Z.utc(t).toISOString(),isoDate:t=>j.iso(t).slice(0,10),memoizeKey:(...t)=>t.join(""),exit:(t=0)=>{process.exit(t);},set:(t,e,o)=>(t[e]=o,t),run:async t=>{try{await t(),process.exit(0);}catch(e){console.error(e),process.exit(1);}},isMain:()=>{let t=process.argv[1]||"";return t.includes("/index.")||t.endsWith("/bin/aip")},errorMessage:t=>t instanceof Error?t.message:String(t),slugify:t=>t.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,""),matchesSearch:(t,e)=>{let o=e?.toLowerCase().split(/\s+/).filter(Boolean);if(!o?.length)return true;let r=t.toLowerCase();return o.every(s=>r.includes(s))}},n=j;});var to,rt,eo,Ot=f(()=>{y();to=" ",rt=class{filename;context;constructor(t){this.filename=t;}log=(t,e,...o)=>{this.filename&&!this.context&&(this.context=`<${eo(this.filename)}>`),this.context&&o.unshift(this.context);let[r,s]=new Date().toISOString().split(/[T.]/);o.unshift(e,r,s);let i=o.map(this.stringify).map(this.sanitize).join(to);return t?console.error(i):console.log(i),i};stringify=t=>{if(!t)return "-";if(w.isNumber(t))return `${t}`;if(w.isError(t))return n.oneLine(t.message||"");if(w.isFunction(t))return n.oneLine(t.toString());if(w.isObject(t)||w.isArray(t))try{return n.dump(t)}catch(e){return `Failed to stringify: ${e.message}`}return w.toString(t)};sanitize=t=>t.replace(/ {2,}/g," ");debug=(...t)=>{this.log(false,"[DEBUG]",...t);};info=(...t)=>{this.log(false,"[INFO]",...t);};warn=(...t)=>{this.log(true,"[WARN]",...t);};error=(...t)=>{this.log(true,"[ERROR]",...t);}},eo=t=>{let e=t.split(it.sep),[o,r,...s]=e.reverse();if(!s.length)return t;let i=it.basename(o,".js").replace(".ts","");if(i==="index")return r;let a=e.indexOf("commands");if(a!==-1&&a<e.length-1){let l=e.slice(a+1);if(l.length>=2){let[d,m]=l;return `<${d}/${m.replace(".js","").replace(".ts","")}>`}}return i};});var oo,st,M,kt,V,At=f(()=>{y();Ot();oo=new rt,st=t=>{let e=t.trim();if(!e.startsWith("---"))return null;let o=e.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);return o?{frontmatter:Et.parse(o[1]),content:o[2].trim()}:null},M=async(t,e,o="")=>{let s=`---
13
+ ${Et.stringify(e).trim()}
14
14
  ---
15
15
 
16
- ${o}`.trim();await s.write(t,n+`
17
- `);},gt=async(t,e)=>{let o=await s.read(t),r=st(o);if(!r)throw new Error(`No frontmatter found in ${t}`);let n={...r.frontmatter,...e};return await M(t,n,r.content),n},W=async t=>{if(!await s.fileExists(t))return null;let o=await s.read(t),r=st(o);return r?r.frontmatter:(eo.warn(`No frontmatter found in ${t}`),null)};});var z,nt,Dt,Ct,oo,ro,u,v=f(()=>{P();L();At();y();z=(a=>(a.BACKLOG="backlog",a.IN_PROGRESS="in-progress",a.ONGOING="ongoing",a.DONE="done",a.BLOCKED="blocked",a.TO_DO="to-do",a))(z||{}),nt=Object.values(z),Dt=["backlog","in-progress","ongoing"],Ct=[c.dirs.HOOKS,c.dirs.INPUTS,c.dirs.OUTPUTS,c.dirs.SCRIPTS],oo=[c.dirs.TASKS,...Ct],ro={getProjectDir(t){return s.joinHome(c.dirs.PROJECTS,t)},getTaskDir(t,e){return s.join(this.getProjectDir(t),c.dirs.TASKS,e)},async findTask(t,e){if(e)return {project:e,task:t};let o=await this.listProjects(),r=[];if(await s.promiseEach(o,async n=>{(await this.listTasks(n)).includes(t)&&r.push(n);}),r.length===0)throw new Error(`Task '${t}' not found. Use --project to specify the project.`);if(r.length>1)throw new Error(`Task '${t}' found in multiple projects: ${r.join(", ")}. Use --project to specify which one.`);return {project:r[0],task:t}},getAgentDir(t){return s.join(S.AIP_HOME,c.dirs.AGENTS,t)},async listProjects(){let t=s.join(S.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(S.AIP_HOME,c.dirs.AGENTS);return await s.fileExists(t)?await s.listDir(t):[]},async createProject(t,e,o){let r=this.getProjectDir(t);return await s.ensureDir(r),await Promise.all(oo.map(n=>s.ensureDir(s.join(r,n)))),await M(s.join(r,c.files.MAIN),e,o),await s.write(s.join(r,c.files.LOG),""),r},async createTask(t,e,o,r){let n=this.getTaskDir(t,e);return await s.ensureDir(n),await Promise.all(Ct.map(i=>s.ensureDir(s.join(n,i)))),await M(s.join(n,c.files.MAIN),o,r),await s.write(s.join(n,c.files.LOG),""),n},async createAgent(t,e){let o=this.getAgentDir(t);return await s.ensureDir(o),await M(s.join(o,c.files.MAIN),e),o},async getProject(t){let e=s.join(this.getProjectDir(t),c.files.MAIN);return await W(e)},async getTask(t,e){let o=s.join(this.getTaskDir(t,e),c.files.MAIN);return await W(o)},async getAgent(t){let e=s.join(this.getAgentDir(t),c.files.MAIN);return await W(e)},async updateProject(t,e){let o=s.join(this.getProjectDir(t),c.files.MAIN);return await gt(o,e)},async updateBody(t,e){let o=await s.read(t),r=st(o);if(!r)throw new Error(`No frontmatter found in ${t}`);await M(t,r.frontmatter,e);},async updateTask(t,e,o){let r=s.join(this.getTaskDir(t,e),c.files.MAIN);if((await W(r))?.status==="ongoing")throw new Error("Cannot update ongoing task. Should be done by user or update manually");return await gt(r,o)},async ingestTask(t,e){let o=this.getTaskDir(t,e),r=this.getProjectDir(t),n=[s.join(r,c.files.MAIN),s.join(o,c.files.MAIN),s.join(o,c.files.LOG)];await s.logFiles(...n);},async ingestProject(t){let e=this.getProjectDir(t),o=await this.listTasks(t),r=[s.join(e,c.files.MAIN),s.join(e,c.files.LOG),...o.map(n=>s.join(this.getTaskDir(t,n),c.files.MAIN))];await s.logFiles(...r);},async ingestFiles(t){await s.logFiles(...t);}},u=ro;});var Rt,Nt=f(()=>{k();y();v();Rt=l({options:z$1.object({description:z$1.string().describe("Agent description"),status:z$1.string().default("active").describe("Initial status")}),args:z$1.object({name:z$1.string().describe("Agent name")}),handler:async({name:t,description:e,status:o})=>{let r=s.slugify(t);await u.createAgent(r,{name:t,description:e,status:o,created:new Date().toISOString()}),console.log(`Agent created: ${r}`),console.log(` Path: ${u.getAgentDir(r)}`);}});});var It,_t=f(()=>{k();It=l({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 Lt,Ft=f(()=>{k();v();Lt=l({options:z$1.object({}),handler:async()=>{let t=await u.listAgents(),e=[];for(let o of t){let r=await u.getAgent(o);r&&e.push({slug:o,description:r.description});}if(e.length===0)return console.log("No agents found");console.log("Agents:");for(let o of e)console.log(`- ${o.slug}: ${o.description||""}`);}});});var Ut,Ht=f(()=>{P();k();L();y();Ut=l({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(S.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 Gt,Kt=f(()=>{P();k();L();y();Gt=l({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(S.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 Mt,zt,ao,Bt,Jt=f(()=>{k();Mt=t=>{let e=t.shape,o=[];for(let[r,n]of Object.entries(e)){let i=n._def,a="unknown",p,d;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=zt(i.innerType):i.typeName==="ZodDefault"&&(a=zt(i.innerType),d=i.defaultValue()),i.description&&(p=i.description);let m=i.typeName!=="ZodOptional"&&i.typeName!=="ZodDefault";o.push({name:r,type:a,required:m,description:p,defaultValue:d});}return o},zt=t=>{let e=t._def;return e.typeName==="ZodString"?"string":e.typeName==="ZodNumber"?"number":e.typeName==="ZodBoolean"?"boolean":e.typeName==="ZodEnum"?`enum: ${e.values.join(" | ")}`:"unknown"},ao=(t,e,o)=>{let r=Mt(o.options),n=o.args?Mt(o.args):[],i=o.description,a=`\`${t} ${e}\``;if(i&&(a+=`: ${i}`),a+=`
20
- `,r.length>0||n.length>0){let d=[];for(let m of n){let g=m.required?`<${m.name}>`:`[${m.name}]`,T=m.description||"";m.defaultValue!==void 0&&(T+=T?` (default: ${m.defaultValue})`:`(default: ${m.defaultValue})`),d.push(`\xB7 ${g}${T?": "+T:""}`);}for(let m of r){let g=m.description||"";m.defaultValue!==void 0&&(g+=g?` (default: ${m.defaultValue})`:`(default: ${m.defaultValue})`),d.push(`\xB7 --${m.name}${g?": "+g:""}`);}a+=d.join(`
16
+ ${o}`.trim();await n.write(t,s+`
17
+ `);},kt=async(t,e)=>{let o=await n.read(t),r=st(o);if(!r)throw new Error(`No frontmatter found in ${t}`);let s={...r.frontmatter,...e};return await M(t,s,r.content),s},V=async t=>{if(!await n.fileExists(t))return null;let o=await n.read(t),r=st(o);return r?r.frontmatter:(oo.warn(`No frontmatter found in ${t}`),null)};});var z,nt,Dt,Ct,ro,so,u,v=f(()=>{P();L();At();y();z=(a=>(a.BACKLOG="backlog",a.IN_PROGRESS="in-progress",a.ONGOING="ongoing",a.DONE="done",a.BLOCKED="blocked",a.TO_DO="to-do",a))(z||{}),nt=Object.values(z),Dt=["backlog","in-progress","ongoing"],Ct=[c.dirs.HOOKS,c.dirs.INPUTS,c.dirs.OUTPUTS,c.dirs.SCRIPTS],ro=[c.dirs.TASKS,...Ct],so={getProjectDir(t){return n.joinHome(c.dirs.PROJECTS,t)},getTaskDir(t,e){return n.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 n.promiseEach(o,async s=>{(await this.listTasks(s)).includes(t)&&r.push(s);}),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 n.join(S.AIP_HOME,c.dirs.AGENTS,t)},async listProjects(){let t=n.join(S.AIP_HOME,c.dirs.PROJECTS),e=await n.listDir(t);return (await n.promiseMap(e,async r=>{let s=this.getProjectDir(r);return await n.fileExists(s)&&r!==c.dirs.AGENTS?r:null})).filter(r=>r!==null).sort()},async listTasks(t){let e=n.join(this.getProjectDir(t),c.dirs.TASKS);return await n.fileExists(e)?await n.listDir(e):[]},async listAgents(){let t=n.join(S.AIP_HOME,c.dirs.AGENTS);return await n.fileExists(t)?await n.listDir(t):[]},async createProject(t,e,o){let r=this.getProjectDir(t);return await n.ensureDir(r),await Promise.all(ro.map(s=>n.ensureDir(n.join(r,s)))),await M(n.join(r,c.files.MAIN),e,o),await n.write(n.join(r,c.files.LOG),""),r},async createTask(t,e,o,r){let s=this.getTaskDir(t,e);return await n.ensureDir(s),await Promise.all(Ct.map(i=>n.ensureDir(n.join(s,i)))),await M(n.join(s,c.files.MAIN),o,r),await n.write(n.join(s,c.files.LOG),""),s},async createAgent(t,e){let o=this.getAgentDir(t);return await n.ensureDir(o),await M(n.join(o,c.files.MAIN),e),o},async getProject(t){let e=n.join(this.getProjectDir(t),c.files.MAIN);return await V(e)},async getTask(t,e){let o=n.join(this.getTaskDir(t,e),c.files.MAIN);return await V(o)},async getAgent(t){let e=n.join(this.getAgentDir(t),c.files.MAIN);return await V(e)},async updateProject(t,e){let o=n.join(this.getProjectDir(t),c.files.MAIN);return await kt(o,e)},async updateBody(t,e){let o=await n.read(t),r=st(o);if(!r)throw new Error(`No frontmatter found in ${t}`);await M(t,r.frontmatter,e);},async updateTask(t,e,o){let r=n.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 kt(r,o)},async ingestTask(t,e){let o=this.getTaskDir(t,e),r=this.getProjectDir(t),s=[n.join(r,c.files.MAIN),n.join(o,c.files.MAIN),n.join(o,c.files.LOG)];await n.logFiles(...s);},async ingestProject(t){let e=this.getProjectDir(t),o=await this.listTasks(t),r=[n.join(e,c.files.MAIN),n.join(e,c.files.LOG),...o.map(s=>n.join(this.getTaskDir(t,s),c.files.MAIN))];await n.logFiles(...r);},async ingestFiles(t){await n.logFiles(...t);}},u=so;});var Rt,Nt=f(()=>{k();y();v();Rt=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=n.slugify(t);await u.createAgent(r,{name:t,description:e,status:o,created:new Date().toISOString()}),console.log(`Agent created: ${r}`),console.log(` Path: ${u.getAgentDir(r)}`);}});});var It,_t=f(()=>{k();It=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 Lt,Ft=f(()=>{k();v();Lt=p({options:z$1.object({}),handler:async()=>{let t=await u.listAgents(),e=[];for(let o of t){let r=await u.getAgent(o);r&&e.push({slug:o,description:r.description});}if(e.length===0)return console.log("No agents found");console.log("Agents:");for(let o of e)console.log(`- ${o.slug}: ${o.description||""}`);}});});var Ut,Ht=f(()=>{P();k();L();y();Ut=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=n.join(S.AIP_HOME,c.dirs.AGENTS,t),o=n.join(e,c.files.MAIN);if(!await n.fileExists(o))throw new Error(`Agent not found: ${t}
18
+ Expected at: ${o}`);console.log(e);}});});var Gt,Kt=f(()=>{P();k();L();y();Gt=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=n.join(S.AIP_HOME,c.dirs.AGENTS,t),o=n.join(e,c.files.MAIN),r=n.join(e,"SOUL.md");if(!await n.fileExists(o))throw new Error(`Agent not found: ${t}
19
+ Expected at: ${o}`);let i=[r,o];await n.logFiles(...i);}});});var Mt,zt,co,Bt,Jt=f(()=>{k();Mt=t=>{let e=t.shape,o=[];for(let[r,s]of Object.entries(e)){let i=s._def,a="unknown",l,d;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=zt(i.innerType):i.typeName==="ZodDefault"&&(a=zt(i.innerType),d=i.defaultValue()),i.description&&(l=i.description);let m=i.typeName!=="ZodOptional"&&i.typeName!=="ZodDefault";o.push({name:r,type:a,required:m,description:l,defaultValue:d});}return o},zt=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"},co=(t,e,o)=>{let r=Mt(o.options),s=o.args?Mt(o.args):[],i=o.description,a=`\`${t} ${e}\``;if(i&&(a+=`: ${i}`),a+=`
20
+ `,r.length>0||s.length>0){let d=[];for(let m of s){let g=m.required?`<${m.name}>`:`[${m.name}]`,T=m.description||"";m.defaultValue!==void 0&&(T+=T?` (default: ${m.defaultValue})`:`(default: ${m.defaultValue})`),d.push(`\xB7 ${g}${T?": "+T:""}`);}for(let m of r){let g=m.description||"";m.defaultValue!==void 0&&(g+=g?` (default: ${m.defaultValue})`:`(default: ${m.defaultValue})`),d.push(`\xB7 --${m.name}${g?": "+g:""}`);}a+=d.join(`
21
21
  `)+`
22
22
  `;}return a+=`
23
- `,a},Bt=l({description:"Print generated CLI reference from command schemas",options:z$1.object({}),handler:async()=>{let{default:t}=await Promise.resolve().then(()=>(Y(),yt)),e="Prepend `aip` to each command\n\n",o=Object.keys(t).sort();for(let r of o){let n=t[r],i=Object.keys(n).sort();for(let a of i){let p=n[a];e+=ao(r,a,p);}}console.log(e);}});});var po,Vt,Zt=f(()=>{k();po=`# AIP Hooks
23
+ `,a},Bt=p({description:"Print generated CLI reference from command schemas",options:z$1.object({}),handler:async()=>{let{default:t}=await Promise.resolve().then(()=>(Y(),jt)),e="Prepend `aip` to each command\n\n",o=Object.keys(t).sort();for(let r of o){let s=t[r],i=Object.keys(s).sort();for(let a of i){let l=s[a];e+=co(r,a,l);}}console.log(e);}});});var lo,Wt,Zt=f(()=>{k();lo=`# AIP Hooks
24
24
 
25
25
  Automated scripts that run before/after project/task actions.
26
26
 
@@ -200,7 +200,7 @@ DEBUG=1 aip task update --status done
200
200
  ---
201
201
 
202
202
  *Hooks automate workflow enforcement. Pre-hooks guard quality, post-hooks handle cleanup.*
203
- `,Vt=l({description:"Hook types, env vars, and patterns",options:z$1.object({}),handler:async()=>{console.log(po);}});});var $,Wt,mo,qt,Yt=f(()=>{J();P();k();$=Object.keys(x.bin)[0],{LOG:Wt}=c.files,mo=`# Quick Start
203
+ `,Wt=p({description:"Hook types, env vars, and patterns",options:z$1.object({}),handler:async()=>{console.log(lo);}});});var $,Vt,uo,qt,Yt=f(()=>{J();P();k();$=Object.keys(x.bin)[0],{LOG:Vt}=c.files,uo=`# Quick Start
204
204
 
205
205
  ## New Task/Project
206
206
 
@@ -261,10 +261,10 @@ ${$} task current
261
261
 
262
262
  $AIP_HOME/projects/slug/
263
263
  \u251C\u2500\u2500 main.md # Definition + body
264
- \u251C\u2500\u2500 ${Wt} # Log (auto-appended, has key task updates too)
264
+ \u251C\u2500\u2500 ${Vt} # Log (auto-appended, has key task updates too)
265
265
  \u2514\u2500\u2500 tasks/task/
266
266
  \u251C\u2500\u2500 main.md # Task definition + body
267
- \u2514\u2500\u2500 ${Wt} # Updates
267
+ \u2514\u2500\u2500 ${Vt} # Updates
268
268
 
269
269
  **Log format:** TSV with columns: date, time, entityType, slug, action, text
270
270
  **Example:** \`2026-03-30<TAB>14:30:00<TAB>task<TAB>api-integration<TAB>log<TAB>API integration complete\`
@@ -281,7 +281,7 @@ ${$} <noun> --help
281
281
  # All parameters and --options for a command
282
282
  ${$} <noun> <verb> --help
283
283
  \`\`\`
284
- `,qt=l({description:"Quick start guide for new users",options:z$1.object({}),handler:async()=>{console.log(mo);}});});var uo,fo,go,ko,ho,yo,jo,Xt,jt,Q,Tt,te,ee=f(()=>{J();P();k();v();uo=Object.values(z).join("|"),{PROJECTS:fo,TASKS:go,HOOKS:ko,INPUTS:ho,OUTPUTS:yo,SCRIPTS:jo}=c.dirs,{MAIN:Xt,LOG:jt}=c.files,Q=Object.keys(x.bin)[0],Tt=`# AIP - Project Management Skill
284
+ `,qt=p({description:"Quick start guide for new users",options:z$1.object({}),handler:async()=>{console.log(uo);}});});var fo,go,ko,ho,yo,jo,To,Xt,Tt,Q,wt,te,ee=f(()=>{J();P();k();v();fo=Object.values(z).join("|"),{PROJECTS:go,TASKS:ko,HOOKS:ho,INPUTS:yo,OUTPUTS:jo,SCRIPTS:To}=c.dirs,{MAIN:Xt,LOG:Tt}=c.files,Q=Object.keys(x.bin)[0],wt=`# AIP - Project Management Skill
285
285
 
286
286
  Automated project and task creation with proper structure, front-matter, and file organization.
287
287
 
@@ -299,17 +299,17 @@ Streamline creation of new projects and tasks with the correct directory structu
299
299
  ## File Structure Overview
300
300
 
301
301
  \`\`\`
302
- $AIP_HOME/${fo}/{project-slug}/
302
+ $AIP_HOME/${go}/{project-slug}/
303
303
  \u251C\u2500\u2500 ${Xt} # Goals + body (YAML frontmatter + markdown content)
304
- \u251C\u2500\u2500 ${jt} # Chronological log (TSV: date, time, entityType, slug, action, text)
305
- \u251C\u2500\u2500 ${ko}/ # pre|post-{create,start,update,complete}.*
306
- \u251C\u2500\u2500 ${ho}/ # Intermediate/raw data (e.g. API responses, downloads)
307
- \u251C\u2500\u2500 ${yo}/ # Deliverables (e.g. reports, leads, etc.)
308
- \u251C\u2500\u2500 ${jo}/ # Automation
309
- \u2514\u2500\u2500 ${go}/
304
+ \u251C\u2500\u2500 ${Tt} # Chronological log (TSV: date, time, entityType, slug, action, text)
305
+ \u251C\u2500\u2500 ${ho}/ # pre|post-{create,start,update,complete}.*
306
+ \u251C\u2500\u2500 ${yo}/ # Intermediate/raw data (e.g. API responses, downloads)
307
+ \u251C\u2500\u2500 ${jo}/ # Deliverables (e.g. reports, leads, etc.)
308
+ \u251C\u2500\u2500 ${To}/ # Automation
309
+ \u2514\u2500\u2500 ${ko}/
310
310
  \u2514\u2500\u2500 {task-slug}/
311
311
  \u251C\u2500\u2500 ${Xt} # Task definition + body
312
- \u251C\u2500\u2500 ${jt} # Activity log
312
+ \u251C\u2500\u2500 ${Tt} # Activity log
313
313
  \u2514\u2500\u2500 ... (same structure)
314
314
  \`\`\`
315
315
 
@@ -320,7 +320,7 @@ $AIP_HOME/${fo}/{project-slug}/
320
320
  name: Clear Title
321
321
  description: One-line summary
322
322
  assignee: agent-name
323
- status: ${uo}
323
+ status: ${fo}
324
324
  created: YYYY-MM-DD
325
325
  ---
326
326
  \`\`\`
@@ -336,11 +336,11 @@ Markdown content after frontmatter. See \`aip help quickstart\` for examples of
336
336
 
337
337
  ## For Agents
338
338
 
339
- Typical workflow: read \`main.md\` for context, check \`${jt}\` for history, work, and log progress with \`aip log append\`.
340
- `,te=l({description:"Project management skill for creating and managing projects/tasks",options:z$1.object({mode:z$1.enum(["md","claude","hermes"]).default("md").describe("Output format: md (no header), claude (name+description), hermes (full frontmatter)")}),handler:async t=>{let e=Object.keys(x.bin)[0];if(t.mode==="md"){console.log(Tt);return}if(t.mode==="claude"){console.log(`---
339
+ Typical workflow: read \`main.md\` for context, check \`${Tt}\` for history, work, and log progress with \`aip log append\`.
340
+ `,te=p({description:"Project management skill for creating and managing projects/tasks",options:z$1.object({mode:z$1.enum(["md","claude","hermes"]).default("md").describe("Output format: md (no header), claude (name+description), hermes (full frontmatter)")}),handler:async t=>{let e=Object.keys(x.bin)[0];if(t.mode==="md"){console.log(wt);return}if(t.mode==="claude"){console.log(`---
341
341
  name: ${e}
342
342
  description: ${x.description}
343
- ---`),console.log(),console.log(Tt);return}if(t.mode==="hermes"){console.log(`---
343
+ ---`),console.log(),console.log(wt);return}if(t.mode==="hermes"){console.log(`---
344
344
  name: ${e}
345
345
  description: ${x.description}
346
346
  version: ${x.version}
@@ -349,9 +349,9 @@ license: ${x.license}
349
349
  metadata:
350
350
  hermes:
351
351
  tags: [${x.keywords.join(", ")}]
352
- ---`),console.log(),console.log(Tt);return}}});});var oe,re=f(()=>{J();k();y();oe=l({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(()=>(Y(),yt)),o=`${x.name} ${x.version} -`,r=s.dumpCommandMapLines(e,t);if(!t)console.log(o,"Usage: aip <noun> <verb> [options]"),console.log(r.map(n=>`-> ${n}`).join(`
353
- `)),console.log(),console.log("Run `aip help quickstart` for a quick start guide"),console.log("Run `aip help skill` for a broader overview");else {let n=r[0]??`${t} {?}`;console.log(o,`Usage: aip ${n} [options]`);}}});});var bt,To,h,A=f(()=>{P();y();bt=s.joinHome(c.dirs.PROJECTS),To={getProjectFromPwd(t=process.cwd()){let e=it.relative(bt,t);if(!e||e.startsWith(".."))return null;let o=e.split(it.sep).filter(Boolean);return o.length===0?null:o[0]},getTaskFromPwd(t=process.cwd()){let e=it.relative(bt,t);if(!e||e.startsWith(".."))return null;let o=e.split(it.sep).filter(Boolean);return o.length<3||o[1]!==c.dirs.TASKS?null:o[2]},getCurrentContext(t=process.cwd()){return {project:this.getProjectFromPwd(t),task:this.getTaskFromPwd(t)}},requireProject(t=process.cwd()){let e=this.getProjectFromPwd(t);if(!e)throw new Error(`Not in a project directory. PWD: ${t}, projects: ${bt}`);return e},requireTask(t=process.cwd()){let e=this.getCurrentContext(t);if(!e.project||!e.task)throw new Error(`Not in a task directory. PWD: ${t}`);return {project:e.project,task:e.task}},exportContext(t=process.cwd()){let e=this.getCurrentContext(t),o=[];return e.project&&o.push(`export CURRENT_PROJECT="${e.project}"`),e.task&&o.push(`export CURRENT_TASK="${e.task}"`),process.env.CURRENT_AGENT&&o.push(`export CURRENT_AGENT="${process.env.CURRENT_AGENT}"`),o.join(`
354
- `)},getTargetDir(t,e=process.cwd()){let o=this.getCurrentContext(e);if(t==="project"){let r=this.getProjectFromPwd(e);if(!r)throw new Error("Not in a project directory. Use --project flag or cd into a project.");let n=s.joinHome(c.dirs.PROJECTS,r);return {targetDir:n,projectDir:n,entityType:"project"}}if(t==="task"){if(!o.project||!o.task)throw new Error("Not in a task directory. Use --project and --task flags or cd into a task.");let r=s.joinHome(c.dirs.PROJECTS,o.project);return {targetDir:s.join(r,c.dirs.TASKS,o.task),projectDir:r,entityType:"task"}}if(o.task&&o.project){let r=s.joinHome(c.dirs.PROJECTS,o.project);return {targetDir:s.join(r,c.dirs.TASKS,o.task),projectDir:r,entityType:"task"}}if(o.project){let r=s.joinHome(c.dirs.PROJECTS,o.project);return {targetDir:r,projectDir:r,entityType:"project"}}throw new Error("Not in a project or task directory. Specify --target flag.")}},h=To;});var se,ne=f(()=>{k();y();A();P();se=l({options:z$1.object({lang:z$1.enum(c.languages).default("ts").describe("Language"),target:z$1.enum(c.targets).default("project").describe("Target level")}),args:z$1.object({type:z$1.enum(c.hookTypes).describe("Hook type (e.g., pre-create, post-complete)")}),handler:async({type:t,lang:e,target:o})=>{let r=e,n=`.${r}`,{targetDir:i,entityType:a}=h.getTargetDir(o),p=s.join(i,c.dirs.HOOKS);await s.ensureDir(p);let d=s.join(p,`${t}${n}`);if(await s.fileExists(d))throw new Error(`Hook already exists: ${d}`);let g;if(r==="ts")g=`#!/usr/bin/env tsx
352
+ ---`),console.log(),console.log(wt);return}}});});var oe,re=f(()=>{J();k();y();oe=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(()=>(Y(),jt)),o=`${x.name} ${x.version} -`,r=n.dumpCommandMapLines(e,t);if(!t)console.log(o,"Usage: aip <noun> <verb> [options]"),console.log(r.map(s=>`-> ${s}`).join(`
353
+ `)),console.log(),console.log("Run `aip help quickstart` for a quick start guide"),console.log("Run `aip help skill` for a broader overview");else {let s=r[0]??`${t} {?}`;console.log(o,`Usage: aip ${s} [options]`);}}});});var Pt,wo,h,A=f(()=>{P();y();Pt=n.joinHome(c.dirs.PROJECTS),wo={getProjectFromPwd(t=process.cwd()){let e=it.relative(Pt,t);if(!e||e.startsWith(".."))return null;let o=e.split(it.sep).filter(Boolean);return o.length===0?null:o[0]},getTaskFromPwd(t=process.cwd()){let e=it.relative(Pt,t);if(!e||e.startsWith(".."))return null;let o=e.split(it.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: ${Pt}`);return e},requireTask(t=process.cwd()){let e=this.getCurrentContext(t);if(!e.project||!e.task)throw new Error(`Not in a task directory. PWD: ${t}`);return {project:e.project,task:e.task}},exportContext(t=process.cwd()){let e=this.getCurrentContext(t),o=[];return e.project&&o.push(`export CURRENT_PROJECT="${e.project}"`),e.task&&o.push(`export CURRENT_TASK="${e.task}"`),process.env.CURRENT_AGENT&&o.push(`export CURRENT_AGENT="${process.env.CURRENT_AGENT}"`),o.join(`
354
+ `)},getTargetDir(t,e=process.cwd()){let o=this.getCurrentContext(e);if(t==="project"){let r=this.getProjectFromPwd(e);if(!r)throw new Error("Not in a project directory. Use --project flag or cd into a project.");let s=n.joinHome(c.dirs.PROJECTS,r);return {targetDir:s,projectDir:s,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=n.joinHome(c.dirs.PROJECTS,o.project);return {targetDir:n.join(r,c.dirs.TASKS,o.task),projectDir:r,entityType:"task"}}if(o.task&&o.project){let r=n.joinHome(c.dirs.PROJECTS,o.project);return {targetDir:n.join(r,c.dirs.TASKS,o.task),projectDir:r,entityType:"task"}}if(o.project){let r=n.joinHome(c.dirs.PROJECTS,o.project);return {targetDir:r,projectDir:r,entityType:"project"}}throw new Error("Not in a project or task directory. Specify --target flag.")}},h=wo;});var se,ne=f(()=>{k();y();A();P();se=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,s=`.${r}`,{targetDir:i,entityType:a}=h.getTargetDir(o),l=n.join(i,c.dirs.HOOKS);await n.ensureDir(l);let d=n.join(l,`${t}${s}`);if(await n.fileExists(d))throw new Error(`Hook already exists: ${d}`);let g;if(r==="ts")g=`#!/usr/bin/env tsx
355
355
  /** ${t} hook for ${a} */
356
356
 
357
357
  import { env } from 'node:process'
@@ -398,8 +398,8 @@ if os.environ.get('TASK_SLUG'):
398
398
 
399
399
  # Exit with non-zero to prevent action (for pre-hooks)
400
400
  # sys.exit(1)
401
- `;else throw new Error(`Unsupported language: ${r}`);await s.write(d,g);let{chmod:T}=await import('fs/promises');await T(d,493),console.log(`Hook created: ${d}`);}});});var Po,E,B=f(()=>{P();y();Po={async findHooks(t,e){let o=s.join(t,c.dirs.HOOKS);if(!await s.fileExists(o))return [];let n=await s.listDir(o),i=`${e}.`;return n.filter(a=>a.startsWith(i)).map(a=>s.join(o,a))},async executeHook(t,e,o){if(!await s.fileExists(t))return true;let n=e.project?s.joinHome(c.dirs.PROJECTS,e.project):o,i=e.task?s.join(n,c.dirs.TASKS,e.task):"",a={...process.env,HOOK_TYPE:e.action,ENTITY_TYPE:e.entityType,TARGET_DIR:o,PROJECT_DIR:n,...e.project?{PROJECT_SLUG:e.project}:{},...e.task?{TASK_SLUG:e.task,TASK_DIR:i}:{}};return new Promise(p=>{let d=spawn(t,[],{stdio:"inherit",env:a,cwd:o,shell:false});d.on("close",(m,g)=>{m===0?p(true):(console.error(`Hook ${it.basename(t)} failed (code=${m??g})`),p(false));}),d.on("error",m=>{console.error(`Failed to execute hook ${t}: ${m.message}`),p(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=Po;});var ie,ae=f(()=>{k();B();A();P();ie=l({options:z$1.object({target:z$1.enum(c.targets).optional().describe("Target level")}),args:z$1.object({type:z$1.enum(c.hookTypes).describe("Hook type to run")}),handler:async({type:t,target:e})=>{let{targetDir:o,entityType:r}=h.getTargetDir(e),n={action:t,entityType:r,project:h.getProjectFromPwd()||void 0,task:h.getTaskFromPwd()||void 0};await E.runHooks(o,t,n)||(console.error(`Hook ${t} failed`),process.exit(1)),console.log(`Hook ${t} completed successfully`);}});});var So,b,F=f(()=>{P();A();y();So={formatEntry(t,e,o,r){let n=new Date,i=n.getFullYear(),a=String(n.getMonth()+1).padStart(2,"0"),p=String(n.getDate()).padStart(2,"0"),d=n.toLocaleTimeString("en-US",{hour12:false,hour:"2-digit",minute:"2-digit",second:"2-digit"});return `${`${i}-${a}-${p}`} ${d} ${t} ${e} ${o} ${r}
402
- `},async append(t,e,o,r,n){let i=s.join(t,c.files.LOG),a=this.formatEntry(e,o,r,n);await s.append(i,a);},async read(t){let e=s.join(t,c.files.LOG);return await s.fileExists(e)?await s.read(e):""},async task(t,e,o){let r=h.getCurrentContext();if(!r.project||!r.task)throw new Error("Not in a task directory");let n=s.joinHome(c.dirs.PROJECTS,r.project,c.dirs.TASKS,r.task);await this.append(n,"task",t,"log",o?`${o}: ${e}`:e);},async project(t,e,o){let r=h.getProjectFromPwd();if(!r)throw new Error("Not in a project directory");let n=s.joinHome(c.dirs.PROJECTS,r);await this.append(n,"project",t,"log",o?`${o}: ${e}`:e);}},b=So;});var ce,pe=f(()=>{P();A();k();y();F();ce=l({description:"Append a custom entry to log.tsv",options:z$1.object({project:z$1.string().optional().describe("Project slug (uses current project from $PWD if not provided)"),task:z$1.string().optional().describe("Task slug (uses current task from $PWD if not provided)")}),args:z$1.object({text:z$1.string().describe("Text to append")}),handler:async({project:t,task:e,text:o})=>{let r=h.getCurrentContext(),n=t||r.project;if(!n)throw new Error("No project specified. Use --project or run from a project/task directory");let i=s.joinHome(c.dirs.PROJECTS,n);if(e||r.task){let a=e||r.task;if(!a)throw new Error("No task specified");let p=s.join(i,c.dirs.TASKS,a);await b.append(p,"task",a,"log",o),console.log(`Appended to task ${a} log.tsv`);}else await b.append(i,"project",n,"log",o),console.log(`Appended to project ${n} log.tsv`);}});});var le,de=f(()=>{P();A();k();y();F();le=l({description:"Read log.tsv history",options:z$1.object({project:z$1.string().optional().describe("Project slug (uses current project from $PWD if not provided)"),task:z$1.string().optional().describe("Task slug (uses current task from $PWD if not provided)")}),args:z$1.object({}),handler:async({project:t,task:e})=>{let o=h.getCurrentContext(),r=t||o.project;if(!r)throw new Error("No project specified. Use --project or run from a project/task directory");let n=s.joinHome(c.dirs.PROJECTS,r);if(e||o.task){let i=e||o.task;if(!i)throw new Error("No task specified");let a=s.join(n,c.dirs.TASKS,i),p=await b.read(a);console.log(p||`No log.tsv found for task ${i}`);}else {let i=await b.read(n);console.log(i||`No log.tsv found for project ${r}`);}}});});var me,ue=f(()=>{k();y();F();v();me=l({description:"Create a new project with name, description, optional status, assignee and body",options:z$1.object({description:z$1.string().describe("Project description"),status:z$1.string().default("active").describe("Initial status"),assignee:z$1.string().optional().describe("Assignee agent slug"),body:z$1.string().optional().describe("Initial body/content (markdown)")}),args:z$1.object({name:z$1.string().describe("Project name")}),handler:async({name:t,description:e,status:o,assignee:r,body:n})=>{let i=s.slugify(t),a=u.getProjectDir(i);await u.createProject(i,{name:t,description:e,status:o,assignee:r,created:new Date().toISOString()},n),await b.append(a,"project",i,"created",`${t} > status is ${o}`),console.log(`Project created: ${i}. Path: ${a}`);}});});var fe,ge=f(()=>{k();A();fe=l({options:z$1.object({}),handler:async()=>{let t=h.getProjectFromPwd();t||(console.error("Not in a project directory"),process.exit(1)),console.log(t);}});});var he,ye=f(()=>{k();v();he=l({description:"List all projects, optionally filtered by status",options:z$1.object({status:z$1.string().optional().describe("Filter by status")}),handler:async({status:t})=>{let e=await u.listProjects(),o=[];for(let r of e){let n=await u.getProject(r);n&&(t&&n.status!==t||o.push({slug:r,status:n.status,assignee:n.assignee}));}if(o.length===0)return console.log("No projects found");console.log("Projects:");for(let r of o)console.log(`- ${r.slug}: ${r.status||""} ${r.assignee||""}`);}});});var je,Te=f(()=>{k();v();je=l({description:"Output project directory path (for cd)",options:z$1.object({}),args:z$1.object({name:z$1.string().describe("Project name (slug)")}),handler:async({name:t})=>{let e=u.getProjectDir(t);console.log(e);}});});var we,be=f(()=>{P();A();k();B();y();v();F();we=l({description:"Update project properties: name, description, status, assignee, or replace body",options:z$1.object({name:z$1.string().optional().describe("New name"),description:z$1.string().optional().describe("New description"),status:z$1.string().optional().describe("New status"),assignee:z$1.string().optional().describe("New assignee"),body:z$1.string().optional().describe("Replace entire body/content (markdown)")}),args:z$1.object({project:z$1.string().optional().describe("Project slug (defaults to current project from $PWD)")}),handler:async({project:t,name:e,description:o,status:r,assignee:n,body:i})=>{let a=t||h.getProjectFromPwd();if(!a)throw new Error("No project specified and not in a project directory");let p=u.getProjectDir(a),d=s.join(p,c.files.MAIN);if(!await E.runHooks(p,"pre-update",{action:"pre-update",entityType:"project"}))throw new Error("Pre-update hook failed, aborting update");let g={};if(e&&(g.name=e),o&&(g.description=o),r&&(g.status=r),n&&(g.assignee=n),Object.keys(g).length===0&&!i){console.log("No updates provided");return}if(Object.keys(g).length>0){await u.updateProject(a,g);let T=Object.entries(g).map(([O,D])=>`${O}=${D}`).join(", ");await b.append(p,"project",a,"updated",T);}i!==void 0&&(await u.updateBody(d,i),await b.append(p,"project",a,"updated",`body replaced (${i.length} chars)`)),await E.runHooks(p,"post-update",{action:"post-update",entityType:"project"}),console.log(`Project ${a} updated`);}});});var Pe,Se=f(()=>{P();k();L();y();Pe=l({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(S.AIP_HOME,c.dirs.SKILLS,t),o=s.join(e,c.files.SKILL);if(!await s.fileExists(o))throw new Error(`Skill not found: ${t}
403
- Expected at: ${o}`);await s.logFiles(o);}});});var xe,ve=f(()=>{k();B();y();v();F();xe=l({description:"Create a new task with assignee, initial status and optional body",options:z$1.object({description:z$1.string().optional().describe("Task description"),assignee:z$1.string().optional().describe("Assignee agent slug"),status:z$1.string().default("backlog").describe("Initial status"),body:z$1.string().optional().describe("Initial body/content (markdown)")}),args:z$1.object({project:z$1.string().describe("Project slug"),name:z$1.string().describe("Task name")}),handler:async({project:t,name:e,description:o,assignee:r,status:n,body:i})=>{let a=s.slugify(e),p=u.getProjectDir(t),d=u.getTaskDir(t,a);if(!await E.runHooksForContext(p,d,"pre-create",{action:"pre-create",entityType:"task",project:t}))throw new Error("Pre-create hook failed, aborting task creation");await u.createTask(t,a,{name:e,description:o,assignee:r,status:n,created:new Date().toISOString()},i),await b.append(d,"task",a,"created",e),await b.append(p,"task",a,"created",`${a} > status is ${n}`),await E.runHooksForContext(p,d,"post-create",{action:"post-create",entityType:"task",project:t}),console.log(`Task created: ${a}`),console.log(` Project: ${t}`),console.log(` Path: ${d}`);}});});var $e,Ee=f(()=>{k();A();$e=l({description:"Get the current task slug from PWD",options:z$1.object({}),handler:async()=>{let t=h.getTaskFromPwd();t||(console.error("Not in a task directory"),process.exit(1)),console.log(t);}});});var Oe,Ae=f(()=>{A();k();v();Oe=l({description:"Output full task context (main.md, log.tsv) for ingestion by agents",options:z$1.object({project:z$1.string().optional().describe("Project slug (searches all projects if not provided)")}),args:z$1.object({task:z$1.string().optional().describe("Task slug (default: from $PWD)")}),handler:async({project:t,task:e})=>{let o=h.getCurrentContext(),r=e??o.task;if(!r)throw new Error("Need task slug (or cd into task dir)");let{project:n}=await u.findTask(r,t);await u.ingestTask(n,r);}});});var De,Ce=f(()=>{k();y();v();De=l({description:"List tasks, optionally filtered by project, status, assignee, or search query",options:z$1.object({project:z$1.string().optional().describe("Project slug (searches all projects if not provided)"),statuses:z$1.array(z$1.string()).default([]).describe("Filter by statuses (multiple allowed)"),assignee:z$1.string().optional().describe("Filter by assignee"),all:z$1.boolean().default(false).describe("Include all tasks (including done/blocked)"),search:z$1.string().optional().describe("Search query (matches task slug, case-insensitive, multi-part AND, any order)")}),handler:async({project:t,statuses:e,assignee:o,all:r,search:n})=>{if(e&&e.length>0){for(let m of e)if(!nt.includes(m))throw new Error(`Invalid status: ${m}. Valid values: ${nt.join(", ")}`)}let i;e&&e.length>0?i=e:r?i=nt:i=Dt;let a=t?[t]:await u.listProjects(),p={};await s.promiseEach(a,async m=>{let g=await u.listTasks(m),T=[];await s.promiseEach(g,async O=>{let D=await u.getTask(m,O);D&&(i.length>0&&!i.includes(D.status||"")||o&&D.assignee!==o||s.matchesSearch(O,n)&&T.push({slug:O,description:D.description}));}),T.length>0&&(p[m]=T.sort((O,D)=>O.slug.localeCompare(D.slug)));});let d=Object.keys(p).sort();if(d.length===0)return console.log("No tasks found");for(let m of d){console.log(`${m}:`);for(let g of p[m])console.log(`- ${g.slug}: ${g.description||""}`);}}});});var Re,Ne=f(()=>{k();v();Re=l({description:"Output task directory path (for cd)",options:z$1.object({project:z$1.string().optional().describe("Project slug (searches all projects if not provided)")}),args:z$1.object({task:z$1.string().describe("Task slug")}),handler:async({project:t,task:e})=>{let{project:o,task:r}=await u.findTask(e,t),n=u.getTaskDir(o,r);console.log(n);}});});var dt,xt=f(()=>{P();A();k();B();y();v();F();dt=l({description:"Update task properties: name, description, status, assignee, or replace body",options:z$1.object({name:z$1.string().optional().describe("New name"),description:z$1.string().optional().describe("New description"),status:z$1.string().optional().describe("New status"),assignee:z$1.string().optional().describe("New assignee"),project:z$1.string().optional().describe("Project slug (searches all projects if not provided)"),body:z$1.string().optional().describe("Replace entire body/content (markdown)")}),args:z$1.object({task:z$1.string().optional().describe("Task slug (default: from $PWD)")}),handler:async({project:t,task:e,name:o,description:r,status:n,assignee:i,body:a})=>{let p=h.getCurrentContext(),d=e??p.task;if(!d)throw new Error("No task specified (use --task or cd into task dir)");let{project:m}=await u.findTask(d,t),g=u.getTaskDir(m,d),T=u.getProjectDir(m),O=s.join(g,c.files.MAIN);if(!await E.runHooksForContext(T,g,"pre-update",{action:"pre-update",entityType:"task",project:m,task:d}))throw new Error("Pre-update hook failed, aborting update");let C={};if(o&&(C.name=o),r&&(C.description=r),n&&(C.status=n),i&&(C.assignee=i),Object.keys(C).length===0&&!a){console.log("No updates provided");return}if(Object.keys(C).length>0){await u.updateTask(m,d,C);let He=Object.entries(C).map(([Ge,Ke])=>`${Ge}=${Ke}`).join(", ");await b.append(g,"task",d,"updated",He);}a!==void 0&&(await u.updateBody(O,a),await b.append(g,"task",d,"updated",`body replaced (${a.length} chars)`)),C.status&&await b.append(T,"task",d,"updated",`status to ${C.status}`),await E.runHooksForContext(u.getProjectDir(m),g,"post-update",{action:"post-update",entityType:"task",project:m,task:d}),console.log(`Task ${d} updated`);}});});var Ie,_e=f(()=>{A();k();B();v();xt();Ie=l({description:"Start a task: set status to in-progress, optionally print context",options:z$1.object({project:z$1.string().optional().describe("Project slug (searches all projects if not provided)"),ingest:z$1.boolean().default(true).describe("Also output context for this task")}),args:z$1.object({task:z$1.string().optional().describe("Task slug (default: from $PWD)")}),handler:async({project:t,task:e,ingest:o})=>{let r=h.getCurrentContext(),n=e??r.task;if(!n)throw new Error("No task specified (use --task or cd into task dir)");let{project:i}=await u.findTask(n,t),a=u.getProjectDir(i),p=u.getTaskDir(i,n);if(!await E.runHooksForContext(a,p,"pre-start",{action:"pre-start",entityType:"task",project:i,task:n}))throw new Error("Pre-start hook failed, aborting task start");(await u.getTask(i,n))?.status!=="in-progress"&&await dt.handler({project:i,task:n,status:"in-progress"}),o&&await u.ingestTask(i,n),await E.runHooksForContext(a,p,"post-start",{action:"post-start",entityType:"task",project:i,task:n});}});});var Le,Fe=f(()=>{k();y();Le=l({description:"Read one or more files into the console",options:z$1.object({}),args:z$1.object({paths:z$1.array(z$1.string()).describe("File paths to read")}),handler:async({paths:t})=>{await s.logFiles(...t);}});});var yt={};ze(yt,{default:()=>R});var $o,R,Y=f(()=>{Nt();_t();Ft();Ht();Kt();Jt();Zt();Yt();ee();re();ne();ae();pe();de();ue();ge();ye();Te();be();Se();ve();Ee();Ae();Ce();Ne();_e();xt();Fe();$o={agent:{create:Rt,current:It,list:Lt,path:Ut,start:Gt},help:{api:Bt,hooks:Vt,quickstart:qt,skill:te,usage:oe},hook:{create:se,run:ie},log:{append:ce,read:le},project:{create:me,current:fe,list:he,path:je,update:we},skill:{read:Pe},task:{create:xe,current:$e,ingest:Oe,list:De,path:Re,start:Ie,update:dt},util:{read:Le}},R=$o;});J();Y();y();Y();L();y();var Oo="date time noun verb extra_args error";function ot(t,e){if(!S.ERROR_LOG)return;let r=new Date().toISOString(),[n,i]=r.split("T"),a=i.replace(/\.\d+Z$/,""),p="",d="";s.isKeyOf(t[0],R)&&(p=t[0],s.isKeyOf(t[1],R[p])&&(d=t[1]));let m=(p?1:0)+(d?1:0),g=t.slice(m).join(" "),T=[n,a,p,d,g,s.errorMessage(e)].map(Ao).join(" "),O=it.dirname(S.ERROR_LOG);ut.existsSync(O)||ut.mkdirSync(O,{recursive:true});let D=ut.existsSync(S.ERROR_LOG);ut.appendFileSync(S.ERROR_LOG,(D?"":Oo+`
401
+ `;else throw new Error(`Unsupported language: ${r}`);await n.write(d,g);let{chmod:T}=await import('fs/promises');await T(d,493),console.log(`Hook created: ${d}`);}});});var So,O,B=f(()=>{P();y();So={async findHooks(t,e){let o=n.join(t,c.dirs.HOOKS);if(!await n.fileExists(o))return [];let s=await n.listDir(o),i=`${e}.`;return s.filter(a=>a.startsWith(i)).map(a=>n.join(o,a))},async executeHook(t,e,o){if(!await n.fileExists(t))return true;let s=e.project?n.joinHome(c.dirs.PROJECTS,e.project):o,i=e.task?n.join(s,c.dirs.TASKS,e.task):"",a={...process.env,HOOK_TYPE:e.action,ENTITY_TYPE:e.entityType,TARGET_DIR:o,PROJECT_DIR:s,...e.project?{PROJECT_SLUG:e.project}:{},...e.task?{TASK_SLUG:e.task,TASK_DIR:i}:{}};return new Promise(l=>{let d=spawn(t,[],{stdio:"inherit",env:a,cwd:o,shell:false});d.on("close",(m,g)=>{m===0?l(true):(console.error(`Hook ${it.basename(t)} failed (code=${m??g})`),l(false));}),d.on("error",m=>{console.error(`Failed to execute hook ${t}: ${m.message}`),l(false);});})},async runHooks(t,e,o){let r=await this.findHooks(t,e),s=e.startsWith("pre-");for(let i of r)if(!await this.executeHook(i,o,t)&&s)return false;return true},async runHooksForContext(t,e,o,r){return !(!await this.runHooks(t,o,r)||e&&!await this.runHooks(e,o,r))}},O=So;});var ie,ae=f(()=>{k();B();A();P();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}=h.getTargetDir(e),s={action:t,entityType:r,project:h.getProjectFromPwd()||void 0,task:h.getTaskFromPwd()||void 0};await O.runHooks(o,t,s)||(console.error(`Hook ${t} failed`),process.exit(1)),console.log(`Hook ${t} completed successfully`);}});});var xo,b,F=f(()=>{P();A();y();xo={formatEntry(t,e,o,r){let s=new Date,i=s.getFullYear(),a=String(s.getMonth()+1).padStart(2,"0"),l=String(s.getDate()).padStart(2,"0"),d=s.toLocaleTimeString("en-US",{hour12:false,hour:"2-digit",minute:"2-digit",second:"2-digit"});return `${`${i}-${a}-${l}`} ${d} ${t} ${e} ${o} ${r}
402
+ `},async append(t,e,o,r,s){let i=n.join(t,c.files.LOG),a=this.formatEntry(e,o,r,s);await n.append(i,a);},async read(t){let e=n.join(t,c.files.LOG);return await n.fileExists(e)?await n.read(e):""},async task(t,e,o){let r=h.getCurrentContext();if(!r.project||!r.task)throw new Error("Not in a task directory");let s=n.joinHome(c.dirs.PROJECTS,r.project,c.dirs.TASKS,r.task);await this.append(s,"task",t,"log",o?`${o}: ${e}`:e);},async project(t,e,o){let r=h.getProjectFromPwd();if(!r)throw new Error("Not in a project directory");let s=n.joinHome(c.dirs.PROJECTS,r);await this.append(s,"project",t,"log",o?`${o}: ${e}`:e);}},b=xo;});var ce,pe=f(()=>{P();A();k();y();F();ce=p({description:"Append a custom entry to log.tsv",options:z$1.object({project:z$1.string().optional().describe("Project slug (uses current project from $PWD if not provided)"),task:z$1.string().optional().describe("Task slug (uses current task from $PWD if not provided)")}),args:z$1.object({text:z$1.string().describe("Text to append")}),handler:async({project:t,task:e,text:o})=>{let r=h.getCurrentContext(),s=t||r.project;if(!s)throw new Error("No project specified. Use --project or run from a project/task directory");let i=n.joinHome(c.dirs.PROJECTS,s);if(e||r.task){let a=e||r.task;if(!a)throw new Error("No task specified");let l=n.join(i,c.dirs.TASKS,a);await b.append(l,"task",a,"log",o),console.log(`Appended to task ${a} log.tsv`);}else await b.append(i,"project",s,"log",o),console.log(`Appended to project ${s} log.tsv`);}});});var le,de=f(()=>{P();A();k();y();F();le=p({description:"Read log.tsv history",options:z$1.object({project:z$1.string().optional().describe("Project slug (uses current project from $PWD if not provided)"),task:z$1.string().optional().describe("Task slug (uses current task from $PWD if not provided)")}),args:z$1.object({}),handler:async({project:t,task:e})=>{let o=h.getCurrentContext(),r=t||o.project;if(!r)throw new Error("No project specified. Use --project or run from a project/task directory");let s=n.joinHome(c.dirs.PROJECTS,r);if(e||o.task){let i=e||o.task;if(!i)throw new Error("No task specified");let a=n.join(s,c.dirs.TASKS,i),l=await b.read(a);console.log(l||`No log.tsv found for task ${i}`);}else {let i=await b.read(s);console.log(i||`No log.tsv found for project ${r}`);}}});});var me,ue=f(()=>{k();y();F();v();me=p({description:"Create a new project with name, description, optional status, assignee and body",options:z$1.object({description:z$1.string().describe("Project description"),status:z$1.string().default("active").describe("Initial status"),assignee:z$1.string().optional().describe("Assignee agent slug"),body:z$1.string().optional().describe("Initial body/content (markdown)")}),args:z$1.object({name:z$1.string().describe("Project name")}),handler:async({name:t,description:e,status:o,assignee:r,body:s})=>{let i=n.slugify(t),a=u.getProjectDir(i);await u.createProject(i,{name:t,description:e,status:o,assignee:r,created:new Date().toISOString()},s),await b.append(a,"project",i,"created",`${t} > status is ${o}`),console.log(`Project created: ${i}. Path: ${a}`);}});});var fe,ge=f(()=>{k();A();fe=p({options:z$1.object({}),handler:async()=>{let t=h.getProjectFromPwd();t||(console.error("Not in a project directory"),process.exit(1)),console.log(t);}});});var he,ye=f(()=>{k();v();he=p({description:"List all projects, optionally filtered by status",options:z$1.object({status:z$1.string().optional().describe("Filter by status")}),handler:async({status:t})=>{let e=await u.listProjects(),o=[];for(let r of e){let s=await u.getProject(r);s&&(t&&s.status!==t||o.push({slug:r,status:s.status,assignee:s.assignee}));}if(o.length===0)return console.log("No projects found");console.log("Projects:");for(let r of o)console.log(`- ${r.slug}: ${r.status||""} ${r.assignee||""}`);}});});var je,Te=f(()=>{k();v();je=p({description:"Output project directory path (for cd)",options:z$1.object({}),args:z$1.object({name:z$1.string().describe("Project name (slug)")}),handler:async({name:t})=>{let e=u.getProjectDir(t);console.log(e);}});});var we,be=f(()=>{P();A();k();B();y();v();F();we=p({description:"Update project properties: name, description, status, assignee, or replace body",options:z$1.object({name:z$1.string().optional().describe("New name"),description:z$1.string().optional().describe("New description"),status:z$1.string().optional().describe("New status"),assignee:z$1.string().optional().describe("New assignee"),body:z$1.string().optional().describe("Replace entire body/content (markdown)")}),args:z$1.object({project:z$1.string().optional().describe("Project slug (defaults to current project from $PWD)")}),handler:async({project:t,name:e,description:o,status:r,assignee:s,body:i})=>{let a=t||h.getProjectFromPwd();if(!a)throw new Error("No project specified and not in a project directory");let l=u.getProjectDir(a),d=n.join(l,c.files.MAIN);if(!await O.runHooks(l,"pre-update",{action:"pre-update",entityType:"project"}))throw new Error("Pre-update hook failed, aborting update");let g={};if(e&&(g.name=e),o&&(g.description=o),r&&(g.status=r),s&&(g.assignee=s),Object.keys(g).length===0&&!i){console.log("No updates provided");return}if(Object.keys(g).length>0){await u.updateProject(a,g);let T=Object.entries(g).map(([E,D])=>`${E}=${D}`).join(", ");await b.append(l,"project",a,"updated",T);}i!==void 0&&(await u.updateBody(d,i),await b.append(l,"project",a,"updated",`body replaced (${i.length} chars)`)),await O.runHooks(l,"post-update",{action:"post-update",entityType:"project"}),console.log(`Project ${a} updated`);}});});var Pe,Se=f(()=>{P();k();L();y();Pe=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=n.join(S.AIP_HOME,c.dirs.SKILLS,t),o=n.join(e,c.files.SKILL);if(!await n.fileExists(o))throw new Error(`Skill not found: ${t}
403
+ Expected at: ${o}`);await n.logFiles(o);}});});var xe,ve=f(()=>{k();B();y();v();F();xe=p({description:"Create a new task with assignee, initial status and optional body",options:z$1.object({description:z$1.string().optional().describe("Task description"),assignee:z$1.string().optional().describe("Assignee agent slug"),status:z$1.string().default("backlog").describe("Initial status"),body:z$1.string().optional().describe("Initial body/content (markdown)")}),args:z$1.object({project:z$1.string().describe("Project slug"),name:z$1.string().describe("Task name")}),handler:async({project:t,name:e,description:o,assignee:r,status:s,body:i})=>{let a=n.slugify(e),l=u.getProjectDir(t),d=u.getTaskDir(t,a);if(!await O.runHooksForContext(l,d,"pre-create",{action:"pre-create",entityType:"task",project:t}))throw new Error("Pre-create hook failed, aborting task creation");await u.createTask(t,a,{name:e,description:o,assignee:r,status:s,created:new Date().toISOString()},i),await b.append(d,"task",a,"created",e),await b.append(l,"task",a,"created",`${a} > status is ${s}`),await O.runHooksForContext(l,d,"post-create",{action:"post-create",entityType:"task",project:t}),console.log(`Task created: ${a}`),console.log(` Project: ${t}`),console.log(` Path: ${d}`);}});});var $e,Oe=f(()=>{k();A();$e=p({description:"Get the current task slug from PWD",options:z$1.object({}),handler:async()=>{let t=h.getTaskFromPwd();t||(console.error("Not in a task directory"),process.exit(1)),console.log(t);}});});var Ee,Ae=f(()=>{A();k();v();Ee=p({description:"Output full task context (main.md, log.tsv) for ingestion by agents",options:z$1.object({project:z$1.string().optional().describe("Project slug (searches all projects if not provided)")}),args:z$1.object({task:z$1.string().optional().describe("Task slug (default: from $PWD)")}),handler:async({project:t,task:e})=>{let o=h.getCurrentContext(),r=e??o.task;if(!r)throw new Error('No task specified (provide task slug as argument, e.g. "aip task ingest my-task", or cd into task dir)');let{project:s}=await u.findTask(r,t);await u.ingestTask(s,r);}});});var De,Ce=f(()=>{k();y();v();De=p({description:"List tasks, optionally filtered by project, status, assignee, or search query",options:z$1.object({project:z$1.string().optional().describe("Project slug (searches all projects if not provided)"),statuses:z$1.array(z$1.string()).default([]).describe("Filter by statuses (multiple allowed)"),assignee:z$1.string().optional().describe("Filter by assignee"),all:z$1.boolean().default(false).describe("Include all tasks (including done/blocked)"),search:z$1.string().optional().describe("Search query (matches task slug, case-insensitive, multi-part AND, any order)")}),handler:async({project:t,statuses:e,assignee:o,all:r,search:s})=>{if(e&&e.length>0){for(let m of e)if(!nt.includes(m))throw new Error(`Invalid status: ${m}. Valid values: ${nt.join(", ")}`)}let i;e&&e.length>0?i=e:r?i=nt:i=Dt;let a=t?[t]:await u.listProjects(),l={};await n.promiseEach(a,async m=>{let g=await u.listTasks(m),T=[];await n.promiseEach(g,async E=>{let D=await u.getTask(m,E);D&&(i.length>0&&!i.includes(D.status||"")||o&&D.assignee!==o||n.matchesSearch(E,s)&&T.push({slug:E,description:D.description}));}),T.length>0&&(l[m]=T.sort((E,D)=>E.slug.localeCompare(D.slug)));});let d=Object.keys(l).sort();if(d.length===0)return console.log("No tasks found");for(let m of d){console.log(`${m}:`);for(let g of l[m])console.log(`- ${g.slug}: ${g.description||""}`);}}});});var Re,Ne=f(()=>{k();v();Re=p({description:"Output task directory path (for cd)",options:z$1.object({project:z$1.string().optional().describe("Project slug (searches all projects if not provided)")}),args:z$1.object({task:z$1.string().describe("Task slug")}),handler:async({project:t,task:e})=>{let{project:o,task:r}=await u.findTask(e,t),s=u.getTaskDir(o,r);console.log(s);}});});var dt,vt=f(()=>{P();A();k();B();y();v();F();dt=p({description:"Update task properties: name, description, status, assignee, or replace body",options:z$1.object({name:z$1.string().optional().describe("New name"),description:z$1.string().optional().describe("New description"),status:z$1.string().optional().describe("New status"),assignee:z$1.string().optional().describe("New assignee"),project:z$1.string().optional().describe("Project slug (searches all projects if not provided)"),body:z$1.string().optional().describe("Replace entire body/content (markdown)")}),args:z$1.object({task:z$1.string().optional().describe("Task slug (default: from $PWD)")}),handler:async({project:t,task:e,name:o,description:r,status:s,assignee:i,body:a})=>{let l=h.getCurrentContext(),d=e??l.task;if(!d)throw new Error('No task specified (provide task slug as argument, e.g. "aip task update my-task", or cd into task dir)');let{project:m}=await u.findTask(d,t),g=u.getTaskDir(m,d),T=u.getProjectDir(m),E=n.join(g,c.files.MAIN);if(!await O.runHooksForContext(T,g,"pre-update",{action:"pre-update",entityType:"task",project:m,task:d}))throw new Error("Pre-update hook failed, aborting update");let C={};if(o&&(C.name=o),r&&(C.description=r),s&&(C.status=s),i&&(C.assignee=i),Object.keys(C).length===0&&!a){console.log("No updates provided");return}if(Object.keys(C).length>0){await u.updateTask(m,d,C);let He=Object.entries(C).map(([Ge,Ke])=>`${Ge}=${Ke}`).join(", ");await b.append(g,"task",d,"updated",He);}a!==void 0&&(await u.updateBody(E,a),await b.append(g,"task",d,"updated",`body replaced (${a.length} chars)`)),C.status&&await b.append(T,"task",d,"updated",`status to ${C.status}`),await O.runHooksForContext(u.getProjectDir(m),g,"post-update",{action:"post-update",entityType:"task",project:m,task:d}),console.log(`Task ${d} updated`);}});});var Ie,_e=f(()=>{A();k();B();v();vt();Ie=p({description:"Start a task: set status to in-progress, optionally print context",options:z$1.object({project:z$1.string().optional().describe("Project slug (searches all projects if not provided)"),ingest:z$1.boolean().default(true).describe("Also output context for this task")}),args:z$1.object({task:z$1.string().optional().describe("Task slug (default: from $PWD)")}),handler:async({project:t,task:e,ingest:o})=>{let r=h.getCurrentContext(),s=e??r.task;if(!s)throw new Error('No task specified (provide task slug as argument, e.g. "aip task start my-task", or cd into task dir)');let{project:i}=await u.findTask(s,t),a=u.getProjectDir(i),l=u.getTaskDir(i,s);if(!await O.runHooksForContext(a,l,"pre-start",{action:"pre-start",entityType:"task",project:i,task:s}))throw new Error("Pre-start hook failed, aborting task start");(await u.getTask(i,s))?.status!=="in-progress"&&await dt.handler({project:i,task:s,status:"in-progress"}),o&&await u.ingestTask(i,s),await O.runHooksForContext(a,l,"post-start",{action:"post-start",entityType:"task",project:i,task:s});}});});var Le,Fe=f(()=>{k();y();Le=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 n.logFiles(...t);}});});var jt={};ze(jt,{default:()=>R});var Oo,R,Y=f(()=>{Nt();_t();Ft();Ht();Kt();Jt();Zt();Yt();ee();re();ne();ae();pe();de();ue();ge();ye();Te();be();Se();ve();Oe();Ae();Ce();Ne();_e();vt();Fe();Oo={agent:{create:Rt,current:It,list:Lt,path:Ut,start:Gt},help:{api:Bt,hooks:Wt,quickstart:qt,skill:te,usage:oe},hook:{create:se,run:ie},log:{append:ce,read:le},project:{create:me,current:fe,list:he,path:je,update:we},skill:{read:Pe},task:{create:xe,current:$e,ingest:Ee,list:De,path:Re,start:Ie,update:dt},util:{read:Le}},R=Oo;});J();Y();y();Y();L();y();var Ao="date time noun verb extra_args error";function ot(t,e){if(!S.ERROR_LOG)return;let r=new Date().toISOString(),[s,i]=r.split("T"),a=i.replace(/\.\d+Z$/,""),l="",d="";n.isKeyOf(t[0],R)&&(l=t[0],n.isKeyOf(t[1],R[l])&&(d=t[1]));let m=(l?1:0)+(d?1:0),g=t.slice(m).join(" "),T=[s,a,l,d,g,n.errorMessage(e)].map(Do).join(" "),E=it.dirname(S.ERROR_LOG);ut.existsSync(E)||ut.mkdirSync(E,{recursive:true});let D=ut.existsSync(S.ERROR_LOG);ut.appendFileSync(S.ERROR_LOG,(D?"":Ao+`
404
404
  `)+T+`
405
- `);}function Ao(t){return t.replace(/\\/g,"\\\\").replace(/\t/g,"\\t").replace(/\n/g,"\\n").replace(/\r/g,"\\r")}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 Ue(t){let[e,o,...r]=t;(e==="--version"||e==="-v")&&(console.log(x.version),process.exit(0));try{let n=!e||e==="--help"||e==="-h";(n||!s.isKeyOf(e,R))&&(await R.help.usage.handler({}),n||ot(t,`Unknown command: ${e}`),process.exit(1));let i=R[e];n=!o||o==="--help"||o==="-h",(n||!s.isKeyOf(o,i))&&(n||ot(t,`Unknown command: ${e} ${o}`),await R.help.usage.handler({name:e}),process.exit(1));let a=i[o];a.parser._internalHandler(p=>{p.type==="error"&&ot(t,p.error||"parse error");}),await a.handler(a.parser.name(`${e} ${o}`).parse(r));}catch(n){console.error("Error:",s.errorMessage(n)),ot(t,n),process.exit(1);}}var Yi=Ue,Qi=R;s.isMain()&&Ue(process.argv.slice(2));export{Qi as commands,Yi as default};
405
+ `);}function Do(t){return (t||"-").replace(/\\/g,"\\\\").replace(/\t/g,"\\t").replace(/\n/g,"\\n").replace(/\r/g,"")}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 Ue(t){let[e,o,...r]=t;(e==="--version"||e==="-v")&&(console.log(x.version),process.exit(0));try{let s=!e||e==="--help"||e==="-h";(s||!n.isKeyOf(e,R))&&(await R.help.usage.handler({}),s||ot(t,`Unknown command: ${e}`),process.exit(1));let i=R[e];s=!o||o==="--help"||o==="-h",(s||!n.isKeyOf(o,i))&&(s||ot(t,`Unknown command: ${e} ${o}`),await R.help.usage.handler({name:e}),process.exit(1));let a=i[o];a.parser._internalHandler(d=>{d.type==="error"&&ot(t,d.error||"parse error");});let l=Co(r,a.args);await a.handler(a.parser.name(`${e} ${o}`).parse(l));}catch(s){console.error("Error:",n.errorMessage(s)),ot(t,s),process.exit(1);}}var Xi=Ue,ta=R;n.isMain()&&Ue(process.argv.slice(2));function Co(t,e){if(!e)return t;let o=new Set(Object.keys(e.shape)),r=[],s=0;for(;s<t.length;){if(t[s].startsWith("--")){let i=t[s].slice(2);if(o.has(i)&&s+1<t.length&&!t[s+1].startsWith("--")){r.push(t[s+1]),s+=2;continue}}r.push(t[s]),s++;}return r}export{ta as commands,Xi as default};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-projects",
3
- "version": "1.8.0",
3
+ "version": "1.9.0",
4
4
  "type": "module",
5
5
  "description": "Useful CLI for AI agents to create and manage projects, tasks, skills and agents",
6
6
  "main": "dist/index.js",