ai-projects 1.5.1 → 1.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +146 -10
- package/dist/index.d.ts +12 -10
- package/dist/index.js +87 -92
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,25 +1,161 @@
|
|
|
1
|
-
# AIP - AI Project Management CLI
|
|
1
|
+
# AIP - AI Project Management CLI 🤖
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Built for AI agents. Polished by AI agents.**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
A command-line tool for managing AI agent projects, tasks, and agents with structured workflows, activity logging, and automation hooks.
|
|
6
|
+
|
|
7
|
+
## 📚 Help System
|
|
8
|
+
|
|
9
|
+
AIP has a comprehensive built-in help system for every level:
|
|
6
10
|
|
|
7
11
|
```bash
|
|
8
|
-
|
|
12
|
+
# 🚀 New here? Start with the quick guide
|
|
13
|
+
aip help quickstart
|
|
14
|
+
|
|
15
|
+
# 📋 Read list of verbs by all nouns
|
|
16
|
+
aip --help # Same as `aip help usage`
|
|
17
|
+
|
|
18
|
+
# 🎯 List of verbs by noun (same as `aip <noun> --help`)
|
|
19
|
+
aip task --help # Same as `aip help usage task`
|
|
20
|
+
|
|
21
|
+
# 📋 Get all parameters and --options for a command
|
|
22
|
+
aip task create --help
|
|
23
|
+
|
|
24
|
+
# 📖 Complete API reference (comprehensive!)
|
|
25
|
+
aip help api
|
|
26
|
+
|
|
27
|
+
# 🛠️ Project management skill documentation (can be piped to a SKILL.md)
|
|
28
|
+
aip help skill
|
|
29
|
+
|
|
30
|
+
# 🔗 Hook system documentation
|
|
31
|
+
aip help hooks
|
|
9
32
|
```
|
|
10
33
|
|
|
11
|
-
|
|
34
|
+
## ✨ Features
|
|
35
|
+
|
|
36
|
+
- **Structured Projects**: YAML frontmatter + markdown body
|
|
37
|
+
- **Activity Logging**: TSV-based status tracking (date, time, type, action, text)
|
|
38
|
+
- **Automation Hooks**: Pre/post hooks for create, start, update, complete
|
|
39
|
+
- **Multi-line Support**: Heredoc syntax for complex content
|
|
40
|
+
- **Agent-Ready**: Designed for autonomous AI workflows
|
|
12
41
|
|
|
13
|
-
##
|
|
42
|
+
## 🚀 Quick Start
|
|
14
43
|
|
|
15
44
|
```bash
|
|
16
|
-
|
|
45
|
+
# Create project with body (inline - cleanest)
|
|
46
|
+
aip project create "my-project" --description "..." --body $'# Goals\n- Build X\n- Solve Y'
|
|
47
|
+
|
|
48
|
+
# Create project with body (here-string for multi-line)
|
|
49
|
+
aip project create "my-project" --description "..." --body "$(cat <<< '# Goals
|
|
50
|
+
- Build X
|
|
51
|
+
- Solve Y')"
|
|
52
|
+
|
|
53
|
+
# Create a task in the project
|
|
54
|
+
aip task create my-project "first-task" --description "Get started"
|
|
55
|
+
|
|
56
|
+
# Navigate and work
|
|
57
|
+
cd $(aip task path first-task)
|
|
58
|
+
|
|
59
|
+
# Start working (and read in all context to stdout)
|
|
60
|
+
aip task start
|
|
61
|
+
|
|
62
|
+
# Log your progress
|
|
63
|
+
aip log append "API integration complete"
|
|
64
|
+
|
|
65
|
+
# View activity history
|
|
66
|
+
aip log read
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## 🏠 AIP_HOME - Project Root Directory
|
|
70
|
+
|
|
71
|
+
AIP stores all projects, tasks, and agents under `$AIP_HOME`.
|
|
72
|
+
|
|
73
|
+
**Set it in your `~/.bashrc` (or `~/.zshrc`):**
|
|
74
|
+
```bash
|
|
75
|
+
export AIP_HOME=/path/to/your/aip-root
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Auto-detection (if `AIP_HOME` is not set):**
|
|
79
|
+
AIP automatically detects the root by traversing up from your current directory looking for standard folders (`projects/`, `skills/`, `agents/`). This means you can `cd` anywhere in your project structure and AIP will find the root.
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# No setup needed - just run from anywhere in your project
|
|
83
|
+
cd /path/to/aip-root/projects/my-project/tasks/some-task
|
|
84
|
+
aip task list # Works! AIP detected the root
|
|
17
85
|
```
|
|
18
86
|
|
|
19
|
-
##
|
|
87
|
+
## 📁 Project Structure
|
|
88
|
+
|
|
89
|
+
Once AIP_HOME is determined, the structure is:
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
$AIP_HOME/projects/{project}/
|
|
93
|
+
├── main.md # Goals + body (YAML frontmatter + markdown)
|
|
94
|
+
├── log.tsv # Activity log (tab-separated: date, time, type, slug, action, text)
|
|
95
|
+
├── hooks/ # Automation: pre|post-{create,start,update,complete}
|
|
96
|
+
├── outputs/ # Deliverables go here
|
|
97
|
+
├── inputs/ # External data (API responses, downloads)
|
|
98
|
+
├── scripts/ # Automation scripts
|
|
99
|
+
└── tasks/{task}/
|
|
100
|
+
├── main.md # Task definition + body
|
|
101
|
+
├── log.tsv # Task activity log
|
|
102
|
+
└── ... # Same substructure
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## 🔧 Key Commands
|
|
106
|
+
|
|
107
|
+
### Projects
|
|
108
|
+
```bash
|
|
109
|
+
aip project create "name" --description "..." --body "..."
|
|
110
|
+
aip project update --status done --body "$(cat final-report.md)"
|
|
111
|
+
aip project list
|
|
112
|
+
aip project path my-project # Get absolute path
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Tasks
|
|
116
|
+
```bash
|
|
117
|
+
aip task create my-project "task-name" --description "..."
|
|
118
|
+
aip task update --status in-progress
|
|
119
|
+
aip task list
|
|
120
|
+
aip task path task-name # Get absolute path
|
|
121
|
+
aip task start # Start working (and read in all context to stdout)
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Logging
|
|
125
|
+
```bash
|
|
126
|
+
aip log append "Completed the implementation"
|
|
127
|
+
aip log append --task my-task "Fixed the bug"
|
|
128
|
+
aip log read # View status history
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Utilities
|
|
132
|
+
```bash
|
|
133
|
+
aip help quickstart # Get started guide
|
|
134
|
+
aip help skill --mode claude > ~/.claude/skills/aip/SKILL.md
|
|
135
|
+
aip help skill --mode hermes > ~/.hermes/skills/some_toolset/aip/SKILL.md
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## 💡 Pro Tips
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
# Chain commands
|
|
142
|
+
cd $(aip task path my-task) && aip task start
|
|
143
|
+
|
|
144
|
+
# Use here-string for complex body content
|
|
145
|
+
aip project update --body "$(cat <<< '# Updated Goals
|
|
146
|
+
- New goal 1
|
|
147
|
+
- New goal 2')"
|
|
148
|
+
|
|
149
|
+
# Quick status check
|
|
150
|
+
aip log read | tail -5
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## 🛠️ Development
|
|
154
|
+
|
|
155
|
+
This tool is **meant for AI agents** and will be **automatically polished by AI agents** based on their usage.
|
|
20
156
|
|
|
21
|
-
|
|
157
|
+
**Suggestions and PRs welcome!** 🎉
|
|
22
158
|
|
|
23
|
-
## License
|
|
159
|
+
## 📄 License
|
|
24
160
|
|
|
25
161
|
MIT
|
package/dist/index.d.ts
CHANGED
|
@@ -155,14 +155,17 @@ declare const commands: {
|
|
|
155
155
|
description: zod.ZodString;
|
|
156
156
|
status: zod.ZodDefault<zod.ZodString>;
|
|
157
157
|
assignee: zod.ZodOptional<zod.ZodString>;
|
|
158
|
+
body: zod.ZodOptional<zod.ZodString>;
|
|
158
159
|
}, "strip", zod.ZodTypeAny, {
|
|
159
160
|
status: string;
|
|
160
161
|
description: string;
|
|
161
162
|
assignee?: string | undefined;
|
|
163
|
+
body?: string | undefined;
|
|
162
164
|
}, {
|
|
163
165
|
description: string;
|
|
164
166
|
status?: string | undefined;
|
|
165
167
|
assignee?: string | undefined;
|
|
168
|
+
body?: string | undefined;
|
|
166
169
|
}>, zod.ZodObject<{
|
|
167
170
|
name: zod.ZodString;
|
|
168
171
|
}, "strip", zod.ZodTypeAny, {
|
|
@@ -198,16 +201,19 @@ declare const commands: {
|
|
|
198
201
|
description: zod.ZodOptional<zod.ZodString>;
|
|
199
202
|
status: zod.ZodOptional<zod.ZodString>;
|
|
200
203
|
assignee: zod.ZodOptional<zod.ZodString>;
|
|
204
|
+
body: zod.ZodOptional<zod.ZodString>;
|
|
201
205
|
}, "strip", zod.ZodTypeAny, {
|
|
202
206
|
status?: string | undefined;
|
|
203
207
|
description?: string | undefined;
|
|
204
208
|
name?: string | undefined;
|
|
205
209
|
assignee?: string | undefined;
|
|
210
|
+
body?: string | undefined;
|
|
206
211
|
}, {
|
|
207
212
|
status?: string | undefined;
|
|
208
213
|
description?: string | undefined;
|
|
209
214
|
name?: string | undefined;
|
|
210
215
|
assignee?: string | undefined;
|
|
216
|
+
body?: string | undefined;
|
|
211
217
|
}>, zod.ZodObject<{
|
|
212
218
|
project: zod.ZodOptional<zod.ZodString>;
|
|
213
219
|
}, "strip", zod.ZodTypeAny, {
|
|
@@ -230,14 +236,17 @@ declare const commands: {
|
|
|
230
236
|
description: zod.ZodOptional<zod.ZodString>;
|
|
231
237
|
assignee: zod.ZodOptional<zod.ZodString>;
|
|
232
238
|
status: zod.ZodDefault<zod.ZodString>;
|
|
239
|
+
body: zod.ZodOptional<zod.ZodString>;
|
|
233
240
|
}, "strip", zod.ZodTypeAny, {
|
|
234
241
|
status: string;
|
|
235
242
|
description?: string | undefined;
|
|
236
243
|
assignee?: string | undefined;
|
|
244
|
+
body?: string | undefined;
|
|
237
245
|
}, {
|
|
238
246
|
status?: string | undefined;
|
|
239
247
|
description?: string | undefined;
|
|
240
248
|
assignee?: string | undefined;
|
|
249
|
+
body?: string | undefined;
|
|
241
250
|
}>, zod.ZodObject<{
|
|
242
251
|
project: zod.ZodString;
|
|
243
252
|
name: zod.ZodString;
|
|
@@ -324,18 +333,21 @@ declare const commands: {
|
|
|
324
333
|
status: zod.ZodOptional<zod.ZodString>;
|
|
325
334
|
assignee: zod.ZodOptional<zod.ZodString>;
|
|
326
335
|
project: zod.ZodOptional<zod.ZodString>;
|
|
336
|
+
body: zod.ZodOptional<zod.ZodString>;
|
|
327
337
|
}, "strip", zod.ZodTypeAny, {
|
|
328
338
|
project?: string | undefined;
|
|
329
339
|
status?: string | undefined;
|
|
330
340
|
description?: string | undefined;
|
|
331
341
|
name?: string | undefined;
|
|
332
342
|
assignee?: string | undefined;
|
|
343
|
+
body?: string | undefined;
|
|
333
344
|
}, {
|
|
334
345
|
project?: string | undefined;
|
|
335
346
|
status?: string | undefined;
|
|
336
347
|
description?: string | undefined;
|
|
337
348
|
name?: string | undefined;
|
|
338
349
|
assignee?: string | undefined;
|
|
350
|
+
body?: string | undefined;
|
|
339
351
|
}>, zod.ZodObject<{
|
|
340
352
|
task: zod.ZodOptional<zod.ZodString>;
|
|
341
353
|
}, "strip", zod.ZodTypeAny, {
|
|
@@ -345,16 +357,6 @@ declare const commands: {
|
|
|
345
357
|
}>>;
|
|
346
358
|
};
|
|
347
359
|
readonly util: {
|
|
348
|
-
readonly postmortem: CommandDef<zod.ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, zod.ZodObject<{
|
|
349
|
-
project: zod.ZodString;
|
|
350
|
-
task: zod.ZodString;
|
|
351
|
-
}, "strip", zod.ZodTypeAny, {
|
|
352
|
-
project: string;
|
|
353
|
-
task: string;
|
|
354
|
-
}, {
|
|
355
|
-
project: string;
|
|
356
|
-
task: string;
|
|
357
|
-
}>>;
|
|
358
360
|
readonly read: CommandDef<zod.ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, zod.ZodObject<{
|
|
359
361
|
paths: zod.ZodArray<zod.ZodString, "many">;
|
|
360
362
|
}, "strip", zod.ZodTypeAny, {
|
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
|
|
2
|
+
import {z as z$1}from'zod';import {parser}from'zod-opts';import rt from'path';import {spawn,exec}from'child_process';import K from'fs/promises';import T from'lodash';import V from'moment';import {fileURLToPath}from'url';import {inspect}from'util';import xt from'yaml';var _e=Object.defineProperty;var f=(t,e)=>()=>(t&&(e=t(t=0)),e);var Ue=(t,e)=>{for(var o in e)_e(t,o,{get:e[o],enumerable:true});};var S,B=f(()=>{S={name:"ai-projects",version:"1.6.1",type:"module",description:"Useful CLI for AI agents to create and manage projects, tasks, skills and agents",main:"dist/index.js",types:"dist/index.d.ts",bin:{aip:"dist/index.js"},files:["dist/**/*","README.md","LICENSE"],scripts:{build:"npm run build:map && npm run build:code","build:map":"tsx bin/map-commands.ts","build:code":"tsup --no-dts","build:all":"npm run build:map && tsup","build:check":"tsc --noEmit","build:watch":"npm run build:code -- --watch","build:clean":"rimraf dist/*","build:incr":"tsup --no-dts",start:"dist/index.js",dev:'npm run build:watch -- --onSuccess "dist/index.js"',cli:"npm run build && npm start --",ts:"tsx",vitest:"VITE_CJS_IGNORE_WARNING=true vitest",test:"npm run test:types && npm run test:unit","test:unit":"npm run vitest -- run","test:types:test":"tsc -p tsconfig.test.json --incremental --tsBuildInfoFile dist/test.tsbuildinfo","test:types:bin":"tsc -p bin/tsconfig.json --incremental --tsBuildInfoFile dist/bin.tsbuildinfo","test:types":"npm run test:types:test && npm run test:types:bin","test:full":"npm run lint:full && npm run test",eslint:"eslint --cache",lint:"npm run eslint -- '{src,bin}/**/*.ts'","lint:fix":"npm run lint -- --fix","lint:full":"npm run build:incr && npm run test:types:bin && npm run lint:fix","lint:full:silent":"npm run -s lint:full && echo LINT OK",map:"npm run build:map",link:"npm link",unlink:"npm unlink",prepare:'[ "$CI" != "true" ] && [ -d node_modules/husky ] && husky || true',prepack:"npm run test:full && npm run build:all","publish:dry":"npm pack --dry-run","version:patch":"npm version patch","version:minor":"npm version minor","version:major":"npm version major","agent:stop":"npm run -s lint:full:silent"},keywords:["ai","aip","project","task","kanban","cli","agent","automation"],author:"Ariel Flesler <aflesler@gmail.com>",license:"MIT",repository:{type:"git",url:"git+https://github.com/flesler/ai-projects.git"},homepage:"https://github.com/flesler/ai-projects#readme",bugs:{url:"https://github.com/flesler/ai-projects/issues"},engines:{node:">=20.0.0"},dependencies:{dotenv:"^17.3.1",lodash:"^4.17.21",moment:"^2.30.1",tslib:"^2.8.1",yaml:"^2.8.0",zod:"^3.25.76","zod-opts":"^1.0.0"},devDependencies:{"@eslint/js":"^10.0.1","@stylistic/eslint-plugin":"^5.7.0","@types/dotenv":"^8.2.3","@types/eslint":"^9.6.1","@types/lodash":"^4.17.23","@types/moment":"^2.13.0","@types/node":"^25.0.9","@types/source-map-support":"^0.5.10","@typescript-eslint/eslint-plugin":"^8.53.0","@typescript-eslint/parser":"^8.53.0",eslint:"^10.0.3","eslint-plugin-import-x":"^4.16.2","eslint-plugin-unused-imports":"^4.4.1","fast-glob":"^3.3.3",husky:"^9.1.7",rimraf:"^6.0.1","source-map-support":"^0.5.21",tsup:"^8.5.1",tsx:"^4.20.3","types-package-json":"^2.0.39",typescript:"^5.8.3",vitest:"^4.0.17"}};});function p(t){let{description:e,options:o=z$1.object({}),args:r,handler:n}=t,i=o.shape,c={};for(let[m,l]of Object.entries(i))c[m]={type:l};let d=parser().options(c);if(r){let m=r.shape,l=Object.entries(m).map(([g,b])=>({name:g,type:b}));l.length>0&&(d=d.args(l));}return e&&(d=d.description(e)),{description:e,options:o,args:r,parser:d,handler:n,cli:m=>n(d.parse(m))}}var k=f(()=>{});var a,P=f(()=>{a={dirs:{PROJECTS:"projects",SKILLS:"skills",AGENTS:"agents",TASKS:"tasks",INPUTS:"inputs",OUTPUTS:"outputs",HOOKS:"hooks",SCRIPTS:"scripts"},files:{MAIN:"main.md",LOG:"log.tsv",SKILL:"SKILL.md"},hookTypes:["pre-create","post-create","pre-complete","post-complete","pre-start","post-start","pre-update","post-update"],languages:["ts","js","sh","py"],targets:["project","task"]};});var J,Me,A,H=f(()=>{P();J=process.env.AIP_HOME;if(!J){J=process.cwd();let t=J.split(rt.sep);for(let e of [a.dirs.PROJECTS,a.dirs.SKILLS,a.dirs.AGENTS]){let o=t.indexOf(e);if(o!==-1){J=t.slice(0,o).join(rt.sep);break}}}Me={AIP_HOME:J},A=Me;});var h,s,j=f(()=>{H();h={REPO:fileURLToPath(import.meta.url.replace(/\/(dist|src)\/.*/,"/")),join:(...t)=>rt.join(...t),onRepo:(...t)=>h.join(h.REPO,...t),joinHome:(...t)=>h.join(A.AIP_HOME,...t),async ensureDir(t){await K.mkdir(t,{recursive:true});},async write(t,e){await h.ensureDir(rt.dirname(t)),await K.writeFile(t,e,"utf8");},async append(t,e){await h.ensureDir(rt.dirname(t)),await K.appendFile(t,e,"utf8");},async read(t){return K.readFile(t,"utf8")},async readRepo(...t){return h.read(h.onRepo(...t))},async readMany(...t){return (await Promise.all(t.map(async o=>{if(await h.fileExists(o)){let r=await h.read(o);return `# ${o}
|
|
3
3
|
|
|
4
|
-
${r}`}return ""}))).filter(Boolean)},async logFiles(...t){let e=await
|
|
4
|
+
${r}`}return ""}))).filter(Boolean)},async logFiles(...t){let e=await h.readMany(...t);console.log(e.join(`
|
|
5
5
|
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
`));},dumpCommandMapLines(t,e){let o=e?
|
|
8
|
+
`));},dumpCommandMapLines(t,e){let o=e?T.pick(t,e):t,r=[];for(let[n,i]of h.entriesOf(o))r.push(`${n} {${Object.keys(i).join("|")}}`);return r},async fileExists(t){try{return await K.access(t),!0}catch{return false}},async listDir(t){try{return await K.readdir(t)}catch{return []}},spawn:spawn,cd(t){process.chdir(t);},async exec(t,e){return new Promise(o=>{exec(t,{encoding:"utf8",...e},(r,n,i)=>{let c=r?.code;o({stdout:n??"",stderr:i??"",code:r?typeof c=="number"?c:1:0});});})},noop:()=>{},omitByDeep:(t,e)=>T.isArray(t)?t.map(o=>h.omitByDeep(o,e)):T.isPlainObject(t)?T.mapValues(T.omitBy(t,e),o=>h.omitByDeep(o,e)):t,omitNilsDeep:t=>h.omitByDeep(t,T.isNil),omitUndefinedsDeep:t=>h.omitByDeep(t,T.isUndefined),cloneDeep:t=>T.cloneDeep(t),int:t=>Number.parseInt(t,10),keysOf:t=>Object.keys(t),entriesOf:t=>Object.entries(t),isKeyOf:(t,e)=>!T.isNil(t)&&t in e,typeOf:t=>typeof t,never:{},undef:t=>t??void 0,toNull:t=>t??null,same:t=>t,notNil:t=>{if(T.isNil(t))throw new Error(`Received unexpected ${t} value`);return t},randomInt:(t,e)=>Math.floor(Math.random()*(e-t+1))+t,promise:()=>{let t,e=new Promise((o,r)=>{t={resolve:o,reject:r};});return T.extend(e,t)},isPromise:t=>T.isObject(t)&&"catch"in t,delay:t=>{let e=T.isObject(t)?h.toMS(t):t;return new Promise(o=>setTimeout(o,e))},promiseMap:(t,e)=>Promise.all(t.map(e)),promiseEach:(t,e)=>Promise.all(t.map(e)).then(()=>{}),memoize:t=>T.memoize(t,h.memoizeKey),toMS:t=>V.duration(t).asMilliseconds(),toSecs:t=>V.duration(t).asSeconds(),inspect:(t,e)=>inspect(t,{colors:false,showHidden:false,depth:null,compact:true,breakLength:1/0,...e}),stringify(t,e,o){let r=new WeakSet;return JSON.stringify(t,(n,i)=>{if(T.isObject(i)){if(r.has(i))return "[Circular]";r.add(i);}return T.isFunction(e)?e(n,i):i},o)},dump:t=>h.oneLine(h.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)=>
|
|
13
|
-
${
|
|
12
|
+
`).replace(/ {2,}/g," ").trim(),oneLine:t=>t.replace(/\n/g,"\\n").replace(/\t/g,"\\t").replace(/ +/g," ").trim(),fuzzySearch:(t,e)=>T.includes(T.toLower(t||""),T.toLower(e||"")),elapsed:(t,e=Date.now())=>V.duration(V(e).diff(t||0)),iso:t=>V.utc(t).toISOString(),isoDate:t=>h.iso(t).slice(0,10),memoizeKey:(...t)=>t.join(""),exit:(t=0)=>{process.exit(t);},set:(t,e,o)=>(t[e]=o,t),run:async t=>{try{await t(),process.exit(0);}catch(e){console.error(e),process.exit(1);}},isMain:()=>{let t=process.argv[1]||"";return t.includes("/index.")||t.endsWith("/bin/aip")},errorMessage:t=>t instanceof Error?t.message:String(t),slugify:t=>t.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")},s=h;});var tt,G,ut,Z,$t=f(()=>{j();tt=t=>{let e=t.trim();if(!e.startsWith("---"))return null;let o=e.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);return o?{frontmatter:xt.parse(o[1]),content:o[2].trim()}:null},G=async(t,e,o="")=>{let n=`---
|
|
13
|
+
${xt.stringify(e).trim()}
|
|
14
14
|
---
|
|
15
15
|
|
|
16
|
-
${o}`.trim();await
|
|
17
|
-
`);},ut=async(t,e)=>{let o=await
|
|
18
|
-
Expected at: ${o}`);console.log(e);}});});var _t
|
|
19
|
-
Expected at: ${o}`);let i=[r,o];await
|
|
20
|
-
`,r.length>0||
|
|
16
|
+
${o}`.trim();await s.write(t,n+`
|
|
17
|
+
`);},ut=async(t,e)=>{let o=await s.read(t),r=tt(o);if(!r)throw new Error(`No frontmatter found in ${t}`);let n={...r.frontmatter,...e};return await G(t,n,r.content),n},Z=async t=>{let e=await s.read(t),o=tt(e);if(!o)throw new Error(`No frontmatter found in ${t}`);return o.frontmatter};});var M,et,vt,Et,Ze,We,u,x=f(()=>{P();H();$t();j();M=(c=>(c.BACKLOG="backlog",c.IN_PROGRESS="in-progress",c.ONGOING="ongoing",c.DONE="done",c.BLOCKED="blocked",c.TO_DO="to-do",c))(M||{}),et=Object.values(M),vt=["backlog","in-progress","ongoing"],Et=[a.dirs.HOOKS,a.dirs.INPUTS,a.dirs.OUTPUTS,a.dirs.SCRIPTS],Ze=[a.dirs.TASKS,...Et],We={getProjectDir(t){return s.joinHome(a.dirs.PROJECTS,t)},getTaskDir(t,e){return s.join(this.getProjectDir(t),a.dirs.TASKS,e)},async findTask(t,e){if(e)return {project:e,task:t};let o=await this.listProjects(),r=[];if(await s.promiseEach(o,async n=>{(await this.listTasks(n)).includes(t)&&r.push(n);}),r.length===0)throw new Error(`Task '${t}' not found. Use --project to specify the project.`);if(r.length>1)throw new Error(`Task '${t}' found in multiple projects: ${r.join(", ")}. Use --project to specify which one.`);return {project:r[0],task:t}},getAgentDir(t){return s.join(A.AIP_HOME,a.dirs.AGENTS,t)},async listProjects(){let t=s.join(A.AIP_HOME,a.dirs.PROJECTS),e=await s.listDir(t);return (await s.promiseMap(e,async r=>{let n=this.getProjectDir(r);return await s.fileExists(n)&&r!==a.dirs.AGENTS?r:null})).filter(r=>r!==null).sort()},async listTasks(t){let e=s.join(this.getProjectDir(t),a.dirs.TASKS);return await s.fileExists(e)?await s.listDir(e):[]},async listAgents(){let t=s.join(A.AIP_HOME,a.dirs.AGENTS);return await s.fileExists(t)?await s.listDir(t):[]},async createProject(t,e,o){let r=this.getProjectDir(t);return await s.ensureDir(r),await Promise.all(Ze.map(n=>s.ensureDir(s.join(r,n)))),await G(s.join(r,a.files.MAIN),e,o),await s.write(s.join(r,a.files.LOG),""),r},async createTask(t,e,o,r){let n=this.getTaskDir(t,e);return await s.ensureDir(n),await Promise.all(Et.map(i=>s.ensureDir(s.join(n,i)))),await G(s.join(n,a.files.MAIN),o,r),await s.write(s.join(n,a.files.LOG),""),n},async createAgent(t,e){let o=this.getAgentDir(t);return await s.ensureDir(o),await G(s.join(o,a.files.MAIN),e),o},async getProject(t){let e=s.join(this.getProjectDir(t),a.files.MAIN);return await s.fileExists(e)?await Z(e):null},async getTask(t,e){let o=s.join(this.getTaskDir(t,e),a.files.MAIN);return await s.fileExists(o)?await Z(o):null},async getAgent(t){let e=s.join(this.getAgentDir(t),a.files.MAIN);return await s.fileExists(e)?await Z(e):null},async updateProject(t,e){let o=s.join(this.getProjectDir(t),a.files.MAIN);return await ut(o,e)},async updateBody(t,e){let o=await s.read(t),r=tt(o);if(!r)throw new Error(`No frontmatter found in ${t}`);await G(t,r.frontmatter,e);},async updateTask(t,e,o){let r=s.join(this.getTaskDir(t,e),a.files.MAIN);if((await Z(r))?.status==="ongoing")throw new Error("Cannot update ongoing task. Should be done by user or update manually");return await ut(r,o)},async ingestTask(t,e){let o=this.getTaskDir(t,e),r=this.getProjectDir(t),n=[s.join(r,a.files.MAIN),s.join(o,a.files.MAIN),s.join(o,a.files.LOG)];await s.logFiles(...n);},async ingestProject(t){let e=this.getProjectDir(t),o=await this.listTasks(t),r=[s.join(e,a.files.MAIN),s.join(e,a.files.LOG),...o.map(n=>s.join(this.getTaskDir(t,n),a.files.MAIN))];await s.logFiles(...r);},async ingestFiles(t){await s.logFiles(...t);}},u=We;});var At,Ot=f(()=>{k();j();x();At=p({options:z$1.object({description:z$1.string().describe("Agent description"),status:z$1.string().default("active").describe("Initial status")}),args:z$1.object({name:z$1.string().describe("Agent name")}),handler:async({name:t,description:e,status:o})=>{let r=s.slugify(t);await u.createAgent(r,{name:t,description:e,status:o,created:new Date().toISOString()}),console.log(`Agent created: ${r}`),console.log(` Path: ${u.getAgentDir(r)}`);}});});var Dt,Ct=f(()=>{k();Dt=p({options:z$1.object({}),handler:async()=>{let t=process.env.CURRENT_AGENT;t||(console.error("CURRENT_AGENT not set"),process.exit(1)),console.log(t);}});});var Nt,Rt=f(()=>{k();x();Nt=p({options:z$1.object({}),handler:async()=>{let t=await u.listAgents(),e=[];for(let o of t){let r=await u.getAgent(o);r&&e.push({slug:o,name:r.name||o,status:r.status,description:r.description});}if(e.length===0){console.log("No agents found");return}console.log("Agents:"),console.log("---");for(let o of e)console.log(`${o.slug.padEnd(20)} ${o.name?.padEnd(30)||""} ${o.status||""} ${o.description||""}`);}});});var It,Lt=f(()=>{P();k();H();j();It=p({description:"Output agent directory path (for cd)",options:z$1.object({}),args:z$1.object({name:z$1.string().describe("Agent name (directory name)")}),handler:async({name:t})=>{let e=s.join(A.AIP_HOME,a.dirs.AGENTS,t),o=s.join(e,a.files.MAIN);if(!await s.fileExists(o))throw new Error(`Agent not found: ${t}
|
|
18
|
+
Expected at: ${o}`);console.log(e);}});});var Ft,_t=f(()=>{P();k();H();j();Ft=p({description:"Start an agent: read SOUL.md and AGENTS.md content",options:z$1.object({}),args:z$1.object({name:z$1.string().describe("Agent name (directory name)")}),handler:async({name:t})=>{let e=s.join(A.AIP_HOME,a.dirs.AGENTS,t),o=s.join(e,a.files.MAIN),r=s.join(e,"SOUL.md");if(!await s.fileExists(o))throw new Error(`Agent not found: ${t}
|
|
19
|
+
Expected at: ${o}`);let i=[r,o];await s.logFiles(...i);}});});var Ut,Ht,Xe,Kt,Gt=f(()=>{k();Ut=t=>{let e=t.shape,o=[];for(let[r,n]of Object.entries(e)){let i=n._def,c="unknown",d,m;i.typeName==="ZodString"?c="string":i.typeName==="ZodNumber"?c="number":i.typeName==="ZodBoolean"?c="boolean":i.typeName==="ZodEnum"?c=`enum: ${i.values.join(" | ")}`:i.typeName==="ZodOptional"?c=Ht(i.innerType):i.typeName==="ZodDefault"&&(c=Ht(i.innerType),m=i.defaultValue()),i.description&&(d=i.description);let l=i.typeName!=="ZodOptional"&&i.typeName!=="ZodDefault";o.push({name:r,type:c,required:l,description:d,defaultValue:m});}return o},Ht=t=>{let e=t._def;return e.typeName==="ZodString"?"string":e.typeName==="ZodNumber"?"number":e.typeName==="ZodBoolean"?"boolean":e.typeName==="ZodEnum"?`enum: ${e.values.join(" | ")}`:"unknown"},Xe=(t,e,o)=>{let r=Ut(o.options),n=o.args?Ut(o.args):[],i=o.description,c=`\`${t} ${e}\``;if(i&&(c+=`: ${i}`),c+=`
|
|
20
|
+
`,r.length>0||n.length>0){let m=[];for(let l of n){let g=l.required?`<${l.name}>`:`[${l.name}]`,b=l.description||"";l.defaultValue!==void 0&&(b+=b?` (default: ${l.defaultValue})`:`(default: ${l.defaultValue})`),m.push(`\xB7 ${g}${b?": "+b:""}`);}for(let l of r){let g=l.description||"";l.defaultValue!==void 0&&(g+=g?` (default: ${l.defaultValue})`:`(default: ${l.defaultValue})`),m.push(`\xB7 --${l.name}${g?": "+g:""}`);}c+=m.join(`
|
|
21
21
|
`)+`
|
|
22
|
-
`;}return
|
|
23
|
-
`,
|
|
22
|
+
`;}return c+=`
|
|
23
|
+
`,c},Kt=p({description:"Print generated CLI reference from command schemas",options:z$1.object({}),handler:async()=>{let{default:t}=await Promise.resolve().then(()=>(ot(),kt)),e="Prepend `aip` to each command\n\n",o=Object.keys(t).sort();for(let r of o){let n=t[r],i=Object.keys(n).sort();for(let c of i){let d=n[c];e+=Xe(r,c,d);}}console.log(e);}});});var eo,Mt,zt=f(()=>{k();eo=`# AIP Hooks
|
|
24
24
|
|
|
25
25
|
Automated scripts that run before/after project/task actions.
|
|
26
26
|
|
|
@@ -62,7 +62,7 @@ Projects can include validation scripts and hooks to enforce folder semantics:
|
|
|
62
62
|
|
|
63
63
|
- **\`hooks/pre-complete.sh\`** \u2013 Runs before task completion
|
|
64
64
|
- Validates required files exist
|
|
65
|
-
- Checks
|
|
65
|
+
- Checks log.tsv has completion entry
|
|
66
66
|
- Runs structure validation (warning only)
|
|
67
67
|
- Exit 1 blocks completion
|
|
68
68
|
|
|
@@ -112,10 +112,10 @@ if (!content.includes('description:')) {
|
|
|
112
112
|
process.exit(1)
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
// Require
|
|
116
|
-
const
|
|
117
|
-
if (!existsSync(
|
|
118
|
-
console.error('\u274C
|
|
115
|
+
// Require log update
|
|
116
|
+
const logPath = join(taskDir, config.files.LOG)
|
|
117
|
+
if (!existsSync(logPath) || readFileSync(logPath, 'utf-8').length === 0) {
|
|
118
|
+
console.error('\u274C log.tsv is empty')
|
|
119
119
|
process.exit(1)
|
|
120
120
|
}
|
|
121
121
|
\`\`\`
|
|
@@ -183,7 +183,7 @@ DEBUG=1 aip task update --status done
|
|
|
183
183
|
- Require tests before completion
|
|
184
184
|
- Check outputs exist
|
|
185
185
|
- Validate frontmatter fields
|
|
186
|
-
- Ensure
|
|
186
|
+
- Ensure log.tsv updated
|
|
187
187
|
|
|
188
188
|
### Automation
|
|
189
189
|
- Backup before changes
|
|
@@ -200,26 +200,30 @@ 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
|
-
`,
|
|
203
|
+
`,Mt=p({description:"Hook types, env vars, and patterns",options:z$1.object({}),handler:async()=>{console.log(eo);}});});var O,Bt,ro,Jt,Vt=f(()=>{P();k();B();O=Object.keys(S.bin)[0],{LOG:Bt}=a.files,ro=`# Quick Start
|
|
204
204
|
|
|
205
205
|
## New Task/Project
|
|
206
206
|
|
|
207
207
|
\`\`\`bash
|
|
208
208
|
# 1. Create project (if needed)
|
|
209
|
-
${
|
|
209
|
+
${O} project create "my-project" --description "What I'm building" --body $'# Goals
|
|
210
|
+
- Build X
|
|
211
|
+
- Solve Y'
|
|
210
212
|
|
|
211
|
-
# 2. Create task
|
|
212
|
-
${
|
|
213
|
+
# 2. Create task (heredoc works too)
|
|
214
|
+
${O} task create my-project "first-task" --description "Start here" --body "$(cat <<< '# Task Details
|
|
215
|
+
- Step 1
|
|
216
|
+
- Step 2')"
|
|
213
217
|
|
|
214
218
|
# 3. Navigate to task
|
|
215
|
-
cd $(${
|
|
219
|
+
cd $(${O} task path first-task)
|
|
216
220
|
|
|
217
221
|
# 4. Start working (implicit from PWD)
|
|
218
|
-
${
|
|
222
|
+
${O} task start
|
|
219
223
|
# \u2192 sets status to in-progress, reads all context to stdout
|
|
220
224
|
|
|
221
225
|
# 5. Work session
|
|
222
|
-
# Log progress: ${
|
|
226
|
+
# Log progress: ${O} log append "API integration complete"
|
|
223
227
|
# Save: outputs/ to deliver, inputs/ for data
|
|
224
228
|
\`\`\`
|
|
225
229
|
|
|
@@ -227,27 +231,27 @@ ${A} task start
|
|
|
227
231
|
|
|
228
232
|
\`\`\`bash
|
|
229
233
|
# Find your tasks (searches all projects)
|
|
230
|
-
${
|
|
234
|
+
${O} task list
|
|
231
235
|
|
|
232
236
|
# Navigate to task
|
|
233
|
-
cd $(${
|
|
237
|
+
cd $(${O} task path task-slug)
|
|
234
238
|
|
|
235
239
|
# All commands work implicitly from PWD:
|
|
236
|
-
${
|
|
240
|
+
${O} task start # Start working (sets status to in-progress, reads all context to stdout)
|
|
237
241
|
\`\`\`
|
|
238
242
|
|
|
239
243
|
## Completing
|
|
240
244
|
|
|
241
245
|
\`\`\`bash
|
|
242
246
|
# Mark done (implicit from PWD)
|
|
243
|
-
${
|
|
244
|
-
${
|
|
247
|
+
${O} task update --status done
|
|
248
|
+
${O} log append "if you want to log something extra"
|
|
245
249
|
\`\`\`
|
|
246
250
|
|
|
247
251
|
## Check current task
|
|
248
252
|
|
|
249
253
|
\`\`\`bash
|
|
250
|
-
${
|
|
254
|
+
${O} task current
|
|
251
255
|
\`\`\`
|
|
252
256
|
|
|
253
257
|
**Note:** All task commands accept an optional task slug, but use PWD if not provided. Navigate with \`cd\` first for smoother workflow.
|
|
@@ -256,20 +260,18 @@ ${A} task current
|
|
|
256
260
|
|
|
257
261
|
\`\`\`
|
|
258
262
|
$AIP_HOME/projects/slug/
|
|
259
|
-
\u251C\u2500\u2500 main.md #
|
|
260
|
-
\u251C\u2500\u2500
|
|
263
|
+
\u251C\u2500\u2500 main.md # Definition + body
|
|
264
|
+
\u251C\u2500\u2500 ${Bt} # Log (auto-appended, has key task updates too)
|
|
261
265
|
\u2514\u2500\u2500 tasks/task/
|
|
262
|
-
\u251C\u2500\u2500 main.md # Task definition
|
|
263
|
-
\u2514\u2500\u2500
|
|
266
|
+
\u251C\u2500\u2500 main.md # Task definition + body
|
|
267
|
+
\u2514\u2500\u2500 ${Bt} # Updates
|
|
264
268
|
\`\`\`
|
|
265
269
|
|
|
266
|
-
**
|
|
270
|
+
**Log format:** TSV with columns: date, time, entityType, slug, action, text
|
|
267
271
|
**Example:** \`2026-03-30<TAB>14:30:00<TAB>task<TAB>api-integration<TAB>log<TAB>API integration complete\`
|
|
268
272
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
Run \`${A} help usage\` for all commands.
|
|
272
|
-
`,Jt=p({description:"Quick start guide for new users",options:z$1.object({}),handler:async()=>{console.log(po);}});});var lo,mo,uo,fo,go,ko,ho,Vt,Zt,G,ht,qt,Yt=f(()=>{B();$();g();x();lo=Object.values(M).join("|"),{PROJECTS:mo,TASKS:uo,HOOKS:fo,INPUTS:go,OUTPUTS:ko,SCRIPTS:ho}=c.dirs,{MAIN:Vt,STATUS:Zt}=c.files,G=Object.keys(b.bin)[0],ht=`# AIP - Project Management Skill
|
|
273
|
+
Run \`${O} help usage\` for all commands.
|
|
274
|
+
`,Jt=p({description:"Quick start guide for new users",options:z$1.object({}),handler:async()=>{console.log(ro);}});});var so,no,io,ao,co,po,lo,Wt,yt,q,ht,qt,Yt=f(()=>{B();P();k();x();so=Object.values(M).join("|"),{PROJECTS:no,TASKS:io,HOOKS:ao,INPUTS:co,OUTPUTS:po,SCRIPTS:lo}=a.dirs,{MAIN:Wt,LOG:yt}=a.files,q=Object.keys(S.bin)[0],ht=`# AIP - Project Management Skill
|
|
273
275
|
|
|
274
276
|
Automated project and task creation with proper structure, front-matter, and file organization.
|
|
275
277
|
|
|
@@ -279,25 +281,25 @@ Streamline creation of new projects and tasks with the correct directory structu
|
|
|
279
281
|
|
|
280
282
|
## Quick Start
|
|
281
283
|
|
|
282
|
-
- New user? Run: \`${
|
|
283
|
-
- All commands? Run: \`${
|
|
284
|
-
- Just for one noun? Run: \`${
|
|
285
|
-
- Need EVERYTHING (big)? Run: \`${
|
|
284
|
+
- New user? Run: \`${q} help quickstart\`
|
|
285
|
+
- All commands? Run: \`${q} help usage\`
|
|
286
|
+
- Just for one noun? Run: \`${q} help usage <noun>\` (e.g., \`${q} help usage task\`)
|
|
287
|
+
- Need EVERYTHING (big)? Run: \`${q} help api\` - Shows all commands with full option details
|
|
286
288
|
|
|
287
289
|
## File Structure Overview
|
|
288
290
|
|
|
289
291
|
\`\`\`
|
|
290
|
-
$AIP_HOME/${
|
|
291
|
-
\u251C\u2500\u2500 ${
|
|
292
|
-
\u251C\u2500\u2500 ${
|
|
293
|
-
\u251C\u2500\u2500 ${
|
|
294
|
-
\u251C\u2500\u2500 ${
|
|
295
|
-
\u251C\u2500\u2500 ${
|
|
296
|
-
\u251C\u2500\u2500 ${
|
|
297
|
-
\u2514\u2500\u2500 ${
|
|
292
|
+
$AIP_HOME/${no}/{project-slug}/
|
|
293
|
+
\u251C\u2500\u2500 ${Wt} # Goals + body (YAML frontmatter + markdown content)
|
|
294
|
+
\u251C\u2500\u2500 ${yt} # Chronological log (TSV: date, time, entityType, slug, action, text)
|
|
295
|
+
\u251C\u2500\u2500 ${ao}/ # pre|post-{create,start,update,complete}.*
|
|
296
|
+
\u251C\u2500\u2500 ${po}/ # Deliverables
|
|
297
|
+
\u251C\u2500\u2500 ${co}/ # External data
|
|
298
|
+
\u251C\u2500\u2500 ${lo}/ # Automation
|
|
299
|
+
\u2514\u2500\u2500 ${io}/
|
|
298
300
|
\u2514\u2500\u2500 {task-slug}/
|
|
299
|
-
\u251C\u2500\u2500 ${
|
|
300
|
-
\u251C\u2500\u2500 ${
|
|
301
|
+
\u251C\u2500\u2500 ${Wt} # Task definition + body
|
|
302
|
+
\u251C\u2500\u2500 ${yt} # Activity log
|
|
301
303
|
\u2514\u2500\u2500 ... (same structure)
|
|
302
304
|
\`\`\`
|
|
303
305
|
|
|
@@ -308,11 +310,15 @@ $AIP_HOME/${mo}/{project-slug}/
|
|
|
308
310
|
name: Clear Title
|
|
309
311
|
description: One-line summary
|
|
310
312
|
assignee: agent-name
|
|
311
|
-
status: ${
|
|
313
|
+
status: ${so}
|
|
312
314
|
created: YYYY-MM-DD
|
|
313
315
|
---
|
|
314
316
|
\`\`\`
|
|
315
317
|
|
|
318
|
+
## Body/Content
|
|
319
|
+
|
|
320
|
+
Markdown content after frontmatter. See \`aip help quickstart\` for examples of adding body content via CLI.
|
|
321
|
+
|
|
316
322
|
## Best Practices
|
|
317
323
|
|
|
318
324
|
**DO:** Concise status entries, update every session, save deliverables to outputs/
|
|
@@ -320,32 +326,27 @@ created: YYYY-MM-DD
|
|
|
320
326
|
|
|
321
327
|
## For Agents
|
|
322
328
|
|
|
323
|
-
|
|
324
|
-
1.
|
|
325
|
-
2. Review \`status.tsv\` (activity history)
|
|
326
|
-
3. Work and save outputs to \`outputs/\`
|
|
327
|
-
4. Log progress: \`${G} log append "message"\`
|
|
328
|
-
5. On completion: set status=\`done\`, log summary
|
|
329
|
-
`,qt=p({description:"Project management skill for creating and managing projects/tasks",options:z$1.object({mode:z$1.enum(["md","claude","hermes"]).default("md").describe("Output format: md (no header), claude (name+description), hermes (full frontmatter)")}),handler:async t=>{let e=Object.keys(b.bin)[0];if(t.mode==="md"){console.log(ht);return}if(t.mode==="claude"){console.log(`---
|
|
329
|
+
Typical workflow: read \`main.md\` for context, check \`${yt}\` for history, work, and log progress with \`aip log append\`.
|
|
330
|
+
`,qt=p({description:"Project management skill for creating and managing projects/tasks",options:z$1.object({mode:z$1.enum(["md","claude","hermes"]).default("md").describe("Output format: md (no header), claude (name+description), hermes (full frontmatter)")}),handler:async t=>{let e=Object.keys(S.bin)[0];if(t.mode==="md"){console.log(ht);return}if(t.mode==="claude"){console.log(`---
|
|
330
331
|
name: ${e}
|
|
331
|
-
description: ${
|
|
332
|
+
description: ${S.description}
|
|
332
333
|
---`),console.log(),console.log(ht);return}if(t.mode==="hermes"){console.log(`---
|
|
333
334
|
name: ${e}
|
|
334
|
-
description: ${
|
|
335
|
-
version: ${
|
|
336
|
-
author: ${
|
|
337
|
-
license: ${
|
|
335
|
+
description: ${S.description}
|
|
336
|
+
version: ${S.version}
|
|
337
|
+
author: ${S.author}
|
|
338
|
+
license: ${S.license}
|
|
338
339
|
metadata:
|
|
339
340
|
hermes:
|
|
340
|
-
tags: [${
|
|
341
|
-
---`),console.log(),console.log(ht);return}}});});var Qt,Xt=f(()=>{B();
|
|
342
|
-
`)),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
|
|
343
|
-
`)},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
|
|
344
|
-
/** ${t} hook for ${
|
|
341
|
+
tags: [${S.keywords.join(", ")}]
|
|
342
|
+
---`),console.log(),console.log(ht);return}}});});var Qt,Xt=f(()=>{B();k();j();Qt=p({description:"Print compact CLI usage (all nouns, or one noun if name is given)",options:z$1.object({}),args:z$1.object({name:z$1.string().optional().describe("Noun (e.g. task) to list verbs for")}),handler:async({name:t})=>{let{default:e}=await Promise.resolve().then(()=>(ot(),kt)),o=`${S.name} ${S.version} -`,r=s.dumpCommandMapLines(e,t);if(!t)console.log(o,"Usage: aip <noun> <verb> [options]"),console.log(r.map(n=>`-> ${n}`).join(`
|
|
343
|
+
`)),console.log(),console.log("Run `aip help quickstart` for a quick start guide"),console.log("Run `aip help skill` for a broader overview");else {let n=r[0]??`${t} {?}`;console.log(o,`Usage: aip ${n} [options]`);}}});});var Tt,mo,y,D=f(()=>{P();j();Tt=s.joinHome(a.dirs.PROJECTS),mo={getProjectFromPwd(t=process.cwd()){let e=rt.relative(Tt,t);if(!e||e.startsWith(".."))return null;let o=e.split(rt.sep).filter(Boolean);return o.length===0?null:o[0]},getTaskFromPwd(t=process.cwd()){let e=rt.relative(Tt,t);if(!e||e.startsWith(".."))return null;let o=e.split(rt.sep).filter(Boolean);return o.length<3||o[1]!==a.dirs.TASKS?null:o[2]},getCurrentContext(t=process.cwd()){return {project:this.getProjectFromPwd(t),task:this.getTaskFromPwd(t)}},requireProject(t=process.cwd()){let e=this.getProjectFromPwd(t);if(!e)throw new Error(`Not in a project directory. PWD: ${t}, projects: ${Tt}`);return e},requireTask(t=process.cwd()){let e=this.getCurrentContext(t);if(!e.project||!e.task)throw new Error(`Not in a task directory. PWD: ${t}`);return {project:e.project,task:e.task}},exportContext(t=process.cwd()){let e=this.getCurrentContext(t),o=[];return e.project&&o.push(`export CURRENT_PROJECT="${e.project}"`),e.task&&o.push(`export CURRENT_TASK="${e.task}"`),process.env.CURRENT_AGENT&&o.push(`export CURRENT_AGENT="${process.env.CURRENT_AGENT}"`),o.join(`
|
|
344
|
+
`)},getTargetDir(t,e=process.cwd()){let o=this.getCurrentContext(e);if(t==="project"){let r=this.getProjectFromPwd(e);if(!r)throw new Error("Not in a project directory. Use --project flag or cd into a project.");let n=s.joinHome(a.dirs.PROJECTS,r);return {targetDir:n,projectDir:n,entityType:"project"}}if(t==="task"){if(!o.project||!o.task)throw new Error("Not in a task directory. Use --project and --task flags or cd into a task.");let r=s.joinHome(a.dirs.PROJECTS,o.project);return {targetDir:s.join(r,a.dirs.TASKS,o.task),projectDir:r,entityType:"task"}}if(o.task&&o.project){let r=s.joinHome(a.dirs.PROJECTS,o.project);return {targetDir:s.join(r,a.dirs.TASKS,o.task),projectDir:r,entityType:"task"}}if(o.project){let r=s.joinHome(a.dirs.PROJECTS,o.project);return {targetDir:r,projectDir:r,entityType:"project"}}throw new Error("Not in a project or task directory. Specify --target flag.")}},y=mo;});var te,ee=f(()=>{k();j();D();P();te=p({options:z$1.object({lang:z$1.enum(a.languages).default("ts").describe("Language"),target:z$1.enum(a.targets).default("project").describe("Target level")}),args:z$1.object({type:z$1.enum(a.hookTypes).describe("Hook type (e.g., pre-create, post-complete)")}),handler:async({type:t,lang:e,target:o})=>{let r=e,n=`.${r}`,{targetDir:i,entityType:c}=y.getTargetDir(o),d=s.join(i,a.dirs.HOOKS);await s.ensureDir(d);let m=s.join(d,`${t}${n}`);if(await s.fileExists(m))throw new Error(`Hook already exists: ${m}`);let g;if(r==="ts")g=`#!/usr/bin/env tsx
|
|
345
|
+
/** ${t} hook for ${c} */
|
|
345
346
|
|
|
346
347
|
import { env } from 'node:process'
|
|
347
348
|
|
|
348
|
-
console.log('Running ${t} hook for ${
|
|
349
|
+
console.log('Running ${t} hook for ${c}')
|
|
349
350
|
console.log('PROJECT_SLUG:', env.PROJECT_SLUG)
|
|
350
351
|
if (env.TASK_SLUG) {
|
|
351
352
|
console.log('TASK_SLUG:', env.TASK_SLUG)
|
|
@@ -353,10 +354,10 @@ if (env.TASK_SLUG) {
|
|
|
353
354
|
|
|
354
355
|
// Exit with non-zero to prevent action (for pre-hooks)
|
|
355
356
|
// process.exit(1)
|
|
356
|
-
`;else if(r==="js")
|
|
357
|
-
/** ${t} hook for ${
|
|
357
|
+
`;else if(r==="js")g=`#!/usr/bin/env node
|
|
358
|
+
/** ${t} hook for ${c} */
|
|
358
359
|
|
|
359
|
-
console.log('Running ${t} hook for ${
|
|
360
|
+
console.log('Running ${t} hook for ${c}')
|
|
360
361
|
console.log('PROJECT_SLUG:', process.env.PROJECT_SLUG)
|
|
361
362
|
if (process.env.TASK_SLUG) {
|
|
362
363
|
console.log('TASK_SLUG:', process.env.TASK_SLUG)
|
|
@@ -364,10 +365,10 @@ if (process.env.TASK_SLUG) {
|
|
|
364
365
|
|
|
365
366
|
// Exit with non-zero to prevent action (for pre-hooks)
|
|
366
367
|
// process.exit(1)
|
|
367
|
-
`;else if(r==="sh")
|
|
368
|
-
# ${t} hook for ${
|
|
368
|
+
`;else if(r==="sh")g=`#!/bin/bash
|
|
369
|
+
# ${t} hook for ${c}
|
|
369
370
|
|
|
370
|
-
echo "Running ${t} hook for ${
|
|
371
|
+
echo "Running ${t} hook for ${c}"
|
|
371
372
|
echo "PROJECT_SLUG: $PROJECT_SLUG"
|
|
372
373
|
if [ -n "$TASK_SLUG" ]; then
|
|
373
374
|
echo "TASK_SLUG: $TASK_SLUG"
|
|
@@ -375,25 +376,19 @@ fi
|
|
|
375
376
|
|
|
376
377
|
# Exit with non-zero to prevent action (for pre-hooks)
|
|
377
378
|
# exit 1
|
|
378
|
-
`;else if(r==="py")
|
|
379
|
-
"""${t} hook for ${
|
|
379
|
+
`;else if(r==="py")g=`#!/usr/bin/env python3
|
|
380
|
+
"""${t} hook for ${c}"""
|
|
380
381
|
|
|
381
382
|
import os
|
|
382
383
|
|
|
383
|
-
print(f"Running ${t} hook for ${
|
|
384
|
+
print(f"Running ${t} hook for ${c}")
|
|
384
385
|
print(f"PROJECT_SLUG: {os.environ.get('PROJECT_SLUG')}")
|
|
385
386
|
if os.environ.get('TASK_SLUG'):
|
|
386
387
|
print(f"TASK_SLUG: {os.environ.get('TASK_SLUG')}")
|
|
387
388
|
|
|
388
389
|
# Exit with non-zero to prevent action (for pre-hooks)
|
|
389
390
|
# sys.exit(1)
|
|
390
|
-
`;else throw new Error(`Unsupported language: ${r}`);await
|
|
391
|
-
`},async
|
|
392
|
-
Expected at: ${o}`);await
|
|
393
|
-
${
|
|
394
|
-
`).filter(m=>m.startsWith("[")).length,a=[],l=r?.name||e;i>5&&a.push("High status update count - consider breaking into smaller tasks"),l.toLowerCase().includes("implement")&&a.push("Implementation task - check if similar patterns exist to reuse"),l.toLowerCase().includes("create")&&l.toLowerCase().includes("command")&&a.push("Command creation - check existing command patterns in src/commands/"),console.log(`
|
|
395
|
-
=== Post-Mortem Analysis ===`),console.log(`Project: ${t}`),console.log(`Task: ${e}`),console.log(`Name: ${l}`),console.log(`Status: ${r?.status||"unknown"}`),console.log(`Status updates: ${i}`),a.length>0?(console.log(`
|
|
396
|
-
Suggestions:`),a.forEach(m=>console.log(` - ${m}`))):console.log(`
|
|
397
|
-
No specific suggestions - task looks well-scoped`),console.log(`
|
|
398
|
-
=== End Post-Mortem ===
|
|
399
|
-
`);}});});var Ue,_e=f(()=>{g();T();Ue=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 kt={};Ke(kt,{default:()=>L});var Po,L,ot=f(()=>{Dt();Ct();Nt();Ut();Lt();Mt();zt();Bt();Yt();Xt();ee();se();ie();ce();le();de();ge();he();ye();we();be();xe();ve();Ae();Oe();Re();St();Ie();_e();Po={agent:{create:At,current:Ot,list:Rt,path:It,start:_t},help:{api:Kt,hooks:Gt,quickstart:Jt,skill:qt,usage:Qt},hook:{create:te,run:re},log:{append:ne,read:ae},project:{create:pe,current:me,list:fe,path:ke,update:je},skill:{read:Te},task:{create:Se,current:Pe,ingest:$e,list:Ee,path:De,start:Ce,update:ct},util:{postmortem:Ne,read:Ue}},L=Po;});B();ot();T();process.on("unhandledRejection",t=>{console.error("Unhandled Rejection:",t),process.exit(1);});process.on("uncaughtException",t=>{console.error("Unhandled Exception:",t),process.exit(1);});async function Le(t){let[e,o,...r]=t;(e==="--version"||e==="-v")&&(console.log(b.version),process.exit(0));try{(!e||!n.isKeyOf(e,L))&&(await L.help.usage.handler({}),process.exit(1));let s=L[e];(!o||!n.isKeyOf(o,s))&&(await L.help.usage.handler({name:e}),process.exit(1));let i=s[o];i||(console.error(`Error: unknown command '${e} ${o}'`),console.log("Run with --help for more information"),process.exit(1)),await i.handler(i.parser.name(`${e} ${o}`).parse(r));}catch(s){console.error("Error:",n.errorMessage(s)),process.exit(1);}}var Ri=Le,Ni=L;n.isMain()&&Le(process.argv.slice(2));export{Ni as commands,Ri as default};
|
|
391
|
+
`;else throw new Error(`Unsupported language: ${r}`);await s.write(m,g);let{chmod:b}=await import('fs/promises');await b(m,493),console.log(`Hook created: ${m}`);}});});var fo,$,z=f(()=>{P();j();fo={async findHooks(t,e){let o=s.join(t,a.dirs.HOOKS);if(!await s.fileExists(o))return [];let n=await s.listDir(o),i=`${e}.`;return n.filter(c=>c.startsWith(i)).map(c=>s.join(o,c))},async executeHook(t,e,o){if(!await s.fileExists(t))return true;let n=e.project?s.joinHome(a.dirs.PROJECTS,e.project):o,i=e.task?s.join(n,a.dirs.TASKS,e.task):"",c={...process.env,HOOK_TYPE:e.action,ENTITY_TYPE:e.entityType,TARGET_DIR:o,PROJECT_DIR:n,...e.project?{PROJECT_SLUG:e.project}:{},...e.task?{TASK_SLUG:e.task,TASK_DIR:i}:{}};return new Promise(d=>{let m=spawn(t,[],{stdio:"inherit",env:c,cwd:rt.dirname(t),shell:false});m.on("close",(l,g)=>{l===0?d(true):(console.error(`Hook ${rt.basename(t)} failed (code=${l??g})`),d(false));}),m.on("error",l=>{console.error(`Failed to execute hook ${t}: ${l.message}`),d(false);});})},async runHooks(t,e,o){let r=await this.findHooks(t,e),n=e.startsWith("pre-");for(let i of r)if(!await this.executeHook(i,o,t)&&n)return false;return true},async runHooksForContext(t,e,o,r){return !(!await this.runHooks(t,o,r)||e&&!await this.runHooks(e,o,r))}},$=fo;});var re,se=f(()=>{k();z();D();P();re=p({options:z$1.object({target:z$1.enum(a.targets).optional().describe("Target level")}),args:z$1.object({type:z$1.enum(a.hookTypes).describe("Hook type to run")}),handler:async({type:t,target:e})=>{let{targetDir:o,entityType:r}=y.getTargetDir(e),n={action:t,entityType:r,project:y.getProjectFromPwd()||void 0,task:y.getTaskFromPwd()||void 0};await $.runHooks(o,t,n)||(console.error(`Hook ${t} failed`),process.exit(1)),console.log(`Hook ${t} completed successfully`);}});});var go,w,L=f(()=>{P();D();j();go={formatEntry(t,e,o,r){let n=new Date,i=n.getFullYear(),c=String(n.getMonth()+1).padStart(2,"0"),d=String(n.getDate()).padStart(2,"0"),m=n.toLocaleTimeString("en-US",{hour12:false,hour:"2-digit",minute:"2-digit",second:"2-digit"});return `${`${i}-${c}-${d}`} ${m} ${t} ${e} ${o} ${r}
|
|
392
|
+
`},async append(t,e,o,r,n){let i=s.join(t,a.files.LOG),c=this.formatEntry(e,o,r,n);await s.append(i,c);},async read(t){let e=s.join(t,a.files.LOG);return await s.fileExists(e)?await s.read(e):""},async task(t,e,o){let r=y.getCurrentContext();if(!r.project||!r.task)throw new Error("Not in a task directory");let n=s.joinHome(a.dirs.PROJECTS,r.project,a.dirs.TASKS,r.task);await this.append(n,"task",t,"log",o?`${o}: ${e}`:e);},async project(t,e,o){let r=y.getProjectFromPwd();if(!r)throw new Error("Not in a project directory");let n=s.joinHome(a.dirs.PROJECTS,r);await this.append(n,"project",t,"log",o?`${o}: ${e}`:e);}},w=go;});var ne,ie=f(()=>{P();D();k();j();L();ne=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=y.getCurrentContext(),n=t||r.project;if(!n)throw new Error("No project specified. Use --project or run from a project/task directory");let i=s.joinHome(a.dirs.PROJECTS,n);if(e||r.task){let c=e||r.task;if(!c)throw new Error("No task specified");let d=s.join(i,a.dirs.TASKS,c);await w.append(d,"task",c,"log",o),console.log(`Appended to task ${c} log.tsv`);}else await w.append(i,"project",n,"log",o),console.log(`Appended to project ${n} log.tsv`);}});});var ae,ce=f(()=>{P();D();k();j();L();ae=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=y.getCurrentContext(),r=t||o.project;if(!r)throw new Error("No project specified. Use --project or run from a project/task directory");let n=s.joinHome(a.dirs.PROJECTS,r);if(e||o.task){let i=e||o.task;if(!i)throw new Error("No task specified");let c=s.join(n,a.dirs.TASKS,i),d=await w.read(c);console.log(d||`No log.tsv found for task ${i}`);}else {let i=await w.read(n);console.log(i||`No log.tsv found for project ${r}`);}}});});var pe,le=f(()=>{k();z();j();x();L();pe=p({description:"Create a new project with name, description, optional status, assignee and body",options:z$1.object({description:z$1.string().describe("Project description"),status:z$1.string().default("active").describe("Initial status"),assignee:z$1.string().optional().describe("Assignee agent slug"),body:z$1.string().optional().describe("Initial body/content (markdown)")}),args:z$1.object({name:z$1.string().describe("Project name")}),handler:async({name:t,description:e,status:o,assignee:r,body:n})=>{let i=s.slugify(t),c=u.getProjectDir(i);if(!await $.runHooks(c,"pre-create",{action:"pre-create",entityType:"project"}))throw new Error("Pre-create hook failed, aborting project creation");await u.createProject(i,{name:t,description:e,status:o,assignee:r,created:new Date().toISOString()},n),await w.append(c,"project",i,"created",`${t} > status is ${o}`),await $.runHooks(c,"post-create",{action:"post-create",entityType:"project"}),console.log(`Project created: ${i}`),console.log(` Path: ${c}`);}});});var de,me=f(()=>{k();D();de=p({options:z$1.object({}),handler:async()=>{let t=y.getProjectFromPwd();t||(console.error("Not in a project directory"),process.exit(1)),console.log(t);}});});var fe,ge=f(()=>{k();x();fe=p({description:"List all projects, optionally filtered by status",options:z$1.object({status:z$1.string().optional().describe("Filter by status")}),handler:async({status:t})=>{let e=await u.listProjects(),o=[];for(let r of e){let n=await u.getProject(r);n&&(t&&n.status!==t||o.push({slug:r,name:n.name||r,status:n.status,assignee:n.assignee}));}if(o.length===0){console.log("No projects found");return}console.log("Projects:"),console.log("---");for(let r of o)console.log(`${r.slug.padEnd(20)} ${r.name?.padEnd(30)||""} ${r.status||""} ${r.assignee||""}`);}});});var ke,ye=f(()=>{k();x();ke=p({description:"Output project directory path (for cd)",options:z$1.object({}),args:z$1.object({name:z$1.string().describe("Project name (slug)")}),handler:async({name:t})=>{let e=u.getProjectDir(t);console.log(e);}});});var he,je=f(()=>{P();D();k();z();j();x();L();he=p({description:"Update project properties: name, description, status, assignee, or replace body",options:z$1.object({name:z$1.string().optional().describe("New name"),description:z$1.string().optional().describe("New description"),status:z$1.string().optional().describe("New status"),assignee:z$1.string().optional().describe("New assignee"),body:z$1.string().optional().describe("Replace entire body/content (markdown)")}),args:z$1.object({project:z$1.string().optional().describe("Project slug (defaults to current project from $PWD)")}),handler:async({project:t,name:e,description:o,status:r,assignee:n,body:i})=>{let c=t||y.getProjectFromPwd();if(!c)throw new Error("No project specified and not in a project directory");let d=u.getProjectDir(c),m=s.join(d,a.files.MAIN);if(!await $.runHooks(d,"pre-update",{action:"pre-update",entityType:"project"}))throw new Error("Pre-update hook failed, aborting update");let g={};if(e&&(g.name=e),o&&(g.description=o),r&&(g.status=r),n&&(g.assignee=n),Object.keys(g).length===0&&!i){console.log("No updates provided");return}if(Object.keys(g).length>0){await u.updateProject(c,g);let b=Object.entries(g).map(([C,E])=>`${C}=${E}`).join(", ");await w.append(d,"project",c,"updated",b);}i!==void 0&&(await u.updateBody(m,i),await w.append(d,"project",c,"updated",`body replaced (${i.length} chars)`)),await $.runHooks(d,"post-update",{action:"post-update",entityType:"project"}),console.log(`Project ${c} updated`);}});});var Te,we=f(()=>{P();k();H();j();Te=p({description:"Read a skill's SKILL.md file into the console for agent context",options:z$1.object({}),args:z$1.object({name:z$1.string().describe("Skill name (directory name)")}),handler:async({name:t})=>{let e=s.join(A.AIP_HOME,a.dirs.SKILLS,t),o=s.join(e,a.files.SKILL);if(!await s.fileExists(o))throw new Error(`Skill not found: ${t}
|
|
393
|
+
Expected at: ${o}`);await s.logFiles(o);}});});var be,Pe=f(()=>{k();z();j();x();L();be=p({description:"Create a new task with assignee, initial status and optional body",options:z$1.object({description:z$1.string().optional().describe("Task description"),assignee:z$1.string().optional().describe("Assignee agent slug"),status:z$1.string().default("backlog").describe("Initial status"),body:z$1.string().optional().describe("Initial body/content (markdown)")}),args:z$1.object({project:z$1.string().describe("Project slug"),name:z$1.string().describe("Task name")}),handler:async({project:t,name:e,description:o,assignee:r,status:n,body:i})=>{let c=s.slugify(e),d=u.getProjectDir(t),m=u.getTaskDir(t,c);if(!await $.runHooksForContext(d,m,"pre-create",{action:"pre-create",entityType:"task",project:t}))throw new Error("Pre-create hook failed, aborting task creation");await u.createTask(t,c,{name:e,description:o,assignee:r,status:n,created:new Date().toISOString()},i),await w.append(m,"task",c,"created",e),await w.append(d,"task",c,"created",`${c} > status is ${n}`),await $.runHooksForContext(d,m,"post-create",{action:"post-create",entityType:"task",project:t}),console.log(`Task created: ${c}`),console.log(` Project: ${t}`),console.log(` Path: ${m}`);}});});var Se,xe=f(()=>{k();D();Se=p({description:"Get the current task slug from PWD",options:z$1.object({}),handler:async()=>{let t=y.getTaskFromPwd();t||(console.error("Not in a task directory"),process.exit(1)),console.log(t);}});});var $e,ve=f(()=>{D();k();x();$e=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=y.getCurrentContext(),r=e??o.task;if(!r)throw new Error("Need task slug (or cd into task dir)");let{project:n}=await u.findTask(r,t);await u.ingestTask(n,r);}});});var Ee,Ae=f(()=>{k();x();Ee=p({description:"List tasks, optionally filtered by project, status, assignee, or search query",options:z$1.object({project:z$1.string().optional().describe("Project slug (searches all projects if not provided)"),statuses:z$1.array(z$1.string()).default([]).describe("Filter by statuses (multiple allowed)"),assignee:z$1.string().optional().describe("Filter by assignee"),all:z$1.boolean().default(false).describe("Include all tasks (including done/blocked)"),search:z$1.string().optional().describe("Search query (matches task slug or name, case-insensitive)")}),handler:async({project:t,statuses:e,assignee:o,all:r,search:n})=>{if(e&&e.length>0){for(let l of e)if(!et.includes(l))throw new Error(`Invalid status: ${l}. Valid values: ${et.join(", ")}`)}let i;e&&e.length>0?i=e:r?i=et:i=vt;let c=t?[t]:await u.listProjects(),d={};for(let l of c){let g=await u.listTasks(l),b=[];for(let C of g){let E=await u.getTask(l,C);if(E&&!(i.length>0&&!i.includes(E.status||""))&&!(o&&E.assignee!==o)){if(n){let v=n.toLowerCase(),lt=C.toLowerCase().includes(v),dt=(E.name||"").toLowerCase().includes(v);if(!lt&&!dt)continue}b.push({slug:C,name:E.name||C,status:E.status,assignee:E.assignee});}}b.length>0&&(d[l]=b.sort((C,E)=>C.slug.localeCompare(E.slug)));}let m=Object.keys(d).sort();if(m.length===0){console.log("No tasks found");return}for(let l of m){console.log(`
|
|
394
|
+
${l}:`),console.log("---");for(let g of d[l])console.log(`${g.slug.padEnd(20)} ${g.name?.padEnd(30)||""} ${g.status||""} ${g.assignee||""}`);}}});});var Oe,De=f(()=>{k();x();Oe=p({description:"Output task directory path (for cd)",options:z$1.object({project:z$1.string().optional().describe("Project slug (searches all projects if not provided)")}),args:z$1.object({task:z$1.string().describe("Task slug")}),handler:async({project:t,task:e})=>{let{project:o,task:r}=await u.findTask(e,t),n=u.getTaskDir(o,r);console.log(n);}});});var ct,Pt=f(()=>{P();D();k();z();j();x();L();ct=p({description:"Update task properties: name, description, status, assignee, or replace body",options:z$1.object({name:z$1.string().optional().describe("New name"),description:z$1.string().optional().describe("New description"),status:z$1.string().optional().describe("New status"),assignee:z$1.string().optional().describe("New assignee"),project:z$1.string().optional().describe("Project slug (searches all projects if not provided)"),body:z$1.string().optional().describe("Replace entire body/content (markdown)")}),args:z$1.object({task:z$1.string().optional().describe("Task slug (default: from $PWD)")}),handler:async({project:t,task:e,name:o,description:r,status:n,assignee:i,body:c})=>{let d=y.getCurrentContext(),m=e??d.task;if(!m)throw new Error("No task specified (use --task or cd into task dir)");let{project:l}=await u.findTask(m,t),g=u.getTaskDir(l,m),b=u.getProjectDir(l),C=s.join(g,a.files.MAIN);if(!await $.runHooksForContext(b,g,"pre-update",{action:"pre-update",entityType:"task",project:l,task:m}))throw new Error("Pre-update hook failed, aborting update");let v={};if(o&&(v.name=o),r&&(v.description=r),n&&(v.status=n),i&&(v.assignee=i),Object.keys(v).length===0&&!c){console.log("No updates provided");return}if(Object.keys(v).length>0){await u.updateTask(l,m,v);let lt=Object.entries(v).map(([dt,Fe])=>`${dt}=${Fe}`).join(", ");await w.append(g,"task",m,"updated",lt);}c!==void 0&&(await u.updateBody(C,c),await w.append(g,"task",m,"updated",`body replaced (${c.length} chars)`)),v.status&&await w.append(b,"task",m,"updated",`status to ${v.status}`),await $.runHooksForContext(u.getProjectDir(l),g,"post-update",{action:"post-update",entityType:"task",project:l,task:m}),console.log(`Task ${m} updated`);}});});var Ce,Ne=f(()=>{D();k();x();Pt();Ce=p({description:"Start a task: set status to in-progress, optionally print context",options:z$1.object({project:z$1.string().optional().describe("Project slug (searches all projects if not provided)"),ingest:z$1.boolean().default(false).describe("Also output context for this task")}),args:z$1.object({task:z$1.string().optional().describe("Task slug (default: from $PWD)")}),handler:async({project:t,task:e,ingest:o})=>{let r=y.getCurrentContext(),n=e??r.task;if(!n)throw new Error("No task specified (use --task or cd into task dir)");let{project:i}=await u.findTask(n,t);(await u.getTask(i,n))?.status!=="in-progress"&&await ct.handler({project:i,task:n,status:"in-progress"}),o&&await u.ingestTask(i,n);}});});var Re,Ie=f(()=>{k();j();Re=p({description:"Read one or more files into the console",options:z$1.object({}),args:z$1.object({paths:z$1.array(z$1.string()).describe("File paths to read")}),handler:async({paths:t})=>{await s.logFiles(...t);}});});var kt={};Ue(kt,{default:()=>U});var ho,U,ot=f(()=>{Ot();Ct();Rt();Lt();_t();Gt();zt();Vt();Yt();Xt();ee();se();ie();ce();le();me();ge();ye();je();we();Pe();xe();ve();Ae();De();Ne();Pt();Ie();ho={agent:{create:At,current:Dt,list:Nt,path:It,start:Ft},help:{api:Kt,hooks:Mt,quickstart:Jt,skill:qt,usage:Qt},hook:{create:te,run:re},log:{append:ne,read:ae},project:{create:pe,current:de,list:fe,path:ke,update:he},skill:{read:Te},task:{create:be,current:Se,ingest:$e,list:Ee,path:Oe,start:Ce,update:ct},util:{read:Re}},U=ho;});B();ot();j();process.on("unhandledRejection",t=>{console.error("Unhandled Rejection:",t),process.exit(1);});process.on("uncaughtException",t=>{console.error("Unhandled Exception:",t),process.exit(1);});async function Le(t){let[e,o,...r]=t;(e==="--version"||e==="-v")&&(console.log(S.version),process.exit(0));try{(!e||!s.isKeyOf(e,U))&&(await U.help.usage.handler({}),process.exit(1));let n=U[e];(!o||!s.isKeyOf(o,n))&&(await U.help.usage.handler({name:e}),process.exit(1));let i=n[o];i||(console.error(`Error: unknown command '${e} ${o}'`),console.log("Run with --help for more information"),process.exit(1)),await i.handler(i.parser.name(`${e} ${o}`).parse(r));}catch(n){console.error("Error:",s.errorMessage(n)),process.exit(1);}}var Pi=Le,Si=U;s.isMain()&&Le(process.argv.slice(2));export{Si as commands,Pi as default};
|