ai-projects 1.6.0 → 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 +45 -37
- package/dist/index.d.ts +0 -10
- package/dist/index.js +52 -76
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,18 +12,19 @@ AIP has a comprehensive built-in help system for every level:
|
|
|
12
12
|
# 🚀 New here? Start with the quick guide
|
|
13
13
|
aip help quickstart
|
|
14
14
|
|
|
15
|
-
# 📋
|
|
16
|
-
aip help usage
|
|
15
|
+
# 📋 Read list of verbs by all nouns
|
|
16
|
+
aip --help # Same as `aip help usage`
|
|
17
17
|
|
|
18
|
-
# 🎯
|
|
19
|
-
aip help
|
|
20
|
-
|
|
21
|
-
|
|
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
|
|
22
23
|
|
|
23
24
|
# 📖 Complete API reference (comprehensive!)
|
|
24
25
|
aip help api
|
|
25
26
|
|
|
26
|
-
# 🛠️ Project management skill documentation
|
|
27
|
+
# 🛠️ Project management skill documentation (can be piped to a SKILL.md)
|
|
27
28
|
aip help skill
|
|
28
29
|
|
|
29
30
|
# 🔗 Hook system documentation
|
|
@@ -41,17 +42,13 @@ aip help hooks
|
|
|
41
42
|
## 🚀 Quick Start
|
|
42
43
|
|
|
43
44
|
```bash
|
|
44
|
-
# Create
|
|
45
|
-
aip project create "my-project" --description "..." --body
|
|
46
|
-
|
|
47
|
-
-
|
|
48
|
-
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
- Tests passing
|
|
52
|
-
- Documentation complete
|
|
53
|
-
EOF
|
|
54
|
-
)"
|
|
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')"
|
|
55
52
|
|
|
56
53
|
# Create a task in the project
|
|
57
54
|
aip task create my-project "first-task" --description "Get started"
|
|
@@ -59,6 +56,9 @@ aip task create my-project "first-task" --description "Get started"
|
|
|
59
56
|
# Navigate and work
|
|
60
57
|
cd $(aip task path first-task)
|
|
61
58
|
|
|
59
|
+
# Start working (and read in all context to stdout)
|
|
60
|
+
aip task start
|
|
61
|
+
|
|
62
62
|
# Log your progress
|
|
63
63
|
aip log append "API integration complete"
|
|
64
64
|
|
|
@@ -66,8 +66,28 @@ aip log append "API integration complete"
|
|
|
66
66
|
aip log read
|
|
67
67
|
```
|
|
68
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
|
|
85
|
+
```
|
|
86
|
+
|
|
69
87
|
## 📁 Project Structure
|
|
70
88
|
|
|
89
|
+
Once AIP_HOME is determined, the structure is:
|
|
90
|
+
|
|
71
91
|
```
|
|
72
92
|
$AIP_HOME/projects/{project}/
|
|
73
93
|
├── main.md # Goals + body (YAML frontmatter + markdown)
|
|
@@ -98,6 +118,7 @@ aip task create my-project "task-name" --description "..."
|
|
|
98
118
|
aip task update --status in-progress
|
|
99
119
|
aip task list
|
|
100
120
|
aip task path task-name # Get absolute path
|
|
121
|
+
aip task start # Start working (and read in all context to stdout)
|
|
101
122
|
```
|
|
102
123
|
|
|
103
124
|
### Logging
|
|
@@ -109,34 +130,21 @@ aip log read # View status history
|
|
|
109
130
|
|
|
110
131
|
### Utilities
|
|
111
132
|
```bash
|
|
112
|
-
aip task ingest # Output full context for AI agents
|
|
113
|
-
aip task start # Mark as in-progress
|
|
114
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
|
|
115
136
|
```
|
|
116
137
|
|
|
117
|
-
## 🤖 For AI Agents
|
|
118
|
-
|
|
119
|
-
If you're an AI agent working with AIP:
|
|
120
|
-
|
|
121
|
-
1. **Read** `$AIP_HOME/AGENTS.md` first
|
|
122
|
-
2. **Review** `main.md` for goals and context
|
|
123
|
-
3. **Check** `log.tsv` for activity history
|
|
124
|
-
4. **Work** and save outputs to `outputs/`
|
|
125
|
-
5. **Log** progress: `aip log append "message"`
|
|
126
|
-
6. **Complete**: Set status=done, summarize in project status
|
|
127
|
-
|
|
128
138
|
## 💡 Pro Tips
|
|
129
139
|
|
|
130
140
|
```bash
|
|
131
141
|
# Chain commands
|
|
132
142
|
cd $(aip task path my-task) && aip task start
|
|
133
143
|
|
|
134
|
-
# Use
|
|
135
|
-
aip project update --body "$(cat
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
EOF
|
|
139
|
-
)"
|
|
144
|
+
# Use here-string for complex body content
|
|
145
|
+
aip project update --body "$(cat <<< '# Updated Goals
|
|
146
|
+
- New goal 1
|
|
147
|
+
- New goal 2')"
|
|
140
148
|
|
|
141
149
|
# Quick status check
|
|
142
150
|
aip log read | tail -5
|
package/dist/index.d.ts
CHANGED
|
@@ -357,16 +357,6 @@ declare const commands: {
|
|
|
357
357
|
}>>;
|
|
358
358
|
};
|
|
359
359
|
readonly util: {
|
|
360
|
-
readonly postmortem: CommandDef<zod.ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, zod.ZodObject<{
|
|
361
|
-
project: zod.ZodString;
|
|
362
|
-
task: zod.ZodString;
|
|
363
|
-
}, "strip", zod.ZodTypeAny, {
|
|
364
|
-
project: string;
|
|
365
|
-
task: string;
|
|
366
|
-
}, {
|
|
367
|
-
project: string;
|
|
368
|
-
task: string;
|
|
369
|
-
}>>;
|
|
370
360
|
readonly read: CommandDef<zod.ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>, zod.ZodObject<{
|
|
371
361
|
paths: zod.ZodArray<zod.ZodString, "many">;
|
|
372
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
16
|
${o}`.trim();await s.write(t,n+`
|
|
17
|
-
`);},
|
|
18
|
-
Expected at: ${o}`);console.log(e);}});});var _t
|
|
19
|
-
Expected at: ${o}`);let i=[r,o];await s.logFiles(...i);}});});var
|
|
20
|
-
`,r.length>0||n.length>0){let m=[];for(let
|
|
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
|
|
|
@@ -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
|
-
`,
|
|
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
|
|
|
@@ -261,17 +261,17 @@ ${O} task current
|
|
|
261
261
|
\`\`\`
|
|
262
262
|
$AIP_HOME/projects/slug/
|
|
263
263
|
\u251C\u2500\u2500 main.md # Definition + body
|
|
264
|
-
\u251C\u2500\u2500 ${
|
|
264
|
+
\u251C\u2500\u2500 ${Bt} # 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 ${
|
|
267
|
+
\u2514\u2500\u2500 ${Bt} # Updates
|
|
268
268
|
\`\`\`
|
|
269
269
|
|
|
270
270
|
**Log format:** TSV with columns: date, time, entityType, slug, action, text
|
|
271
271
|
**Example:** \`2026-03-30<TAB>14:30:00<TAB>task<TAB>api-integration<TAB>log<TAB>API integration complete\`
|
|
272
272
|
|
|
273
273
|
Run \`${O} help usage\` for all commands.
|
|
274
|
-
`,
|
|
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
|
|
275
275
|
|
|
276
276
|
Automated project and task creation with proper structure, front-matter, and file organization.
|
|
277
277
|
|
|
@@ -281,25 +281,25 @@ Streamline creation of new projects and tasks with the correct directory structu
|
|
|
281
281
|
|
|
282
282
|
## Quick Start
|
|
283
283
|
|
|
284
|
-
- New user? Run: \`${
|
|
285
|
-
- All commands? Run: \`${
|
|
286
|
-
- Just for one noun? Run: \`${
|
|
287
|
-
- 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
|
|
288
288
|
|
|
289
289
|
## File Structure Overview
|
|
290
290
|
|
|
291
291
|
\`\`\`
|
|
292
|
-
$AIP_HOME/${
|
|
293
|
-
\u251C\u2500\u2500 ${
|
|
294
|
-
\u251C\u2500\u2500 ${
|
|
295
|
-
\u251C\u2500\u2500 ${
|
|
296
|
-
\u251C\u2500\u2500 ${
|
|
297
|
-
\u251C\u2500\u2500 ${
|
|
298
|
-
\u251C\u2500\u2500 ${
|
|
299
|
-
\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}/
|
|
300
300
|
\u2514\u2500\u2500 {task-slug}/
|
|
301
|
-
\u251C\u2500\u2500 ${
|
|
302
|
-
\u251C\u2500\u2500 ${
|
|
301
|
+
\u251C\u2500\u2500 ${Wt} # Task definition + body
|
|
302
|
+
\u251C\u2500\u2500 ${yt} # Activity log
|
|
303
303
|
\u2514\u2500\u2500 ... (same structure)
|
|
304
304
|
\`\`\`
|
|
305
305
|
|
|
@@ -310,27 +310,14 @@ $AIP_HOME/${go}/{project-slug}/
|
|
|
310
310
|
name: Clear Title
|
|
311
311
|
description: One-line summary
|
|
312
312
|
assignee: agent-name
|
|
313
|
-
status: ${
|
|
313
|
+
status: ${so}
|
|
314
314
|
created: YYYY-MM-DD
|
|
315
315
|
---
|
|
316
316
|
\`\`\`
|
|
317
317
|
|
|
318
318
|
## Body/Content
|
|
319
319
|
|
|
320
|
-
Markdown after frontmatter.
|
|
321
|
-
|
|
322
|
-
\`\`\`bash
|
|
323
|
-
# Using heredoc (multi-line)
|
|
324
|
-
${R} project create "my-project" --description "..." --body "$(cat <<'EOF'
|
|
325
|
-
# Goals
|
|
326
|
-
- Build X
|
|
327
|
-
- Solve Y
|
|
328
|
-
EOF
|
|
329
|
-
)"
|
|
330
|
-
|
|
331
|
-
# Update/replace body
|
|
332
|
-
${R} project update --body "$(cat new-content.md)"
|
|
333
|
-
\`\`\`
|
|
320
|
+
Markdown content after frontmatter. See \`aip help quickstart\` for examples of adding body content via CLI.
|
|
334
321
|
|
|
335
322
|
## Best Practices
|
|
336
323
|
|
|
@@ -339,16 +326,11 @@ ${R} project update --body "$(cat new-content.md)"
|
|
|
339
326
|
|
|
340
327
|
## For Agents
|
|
341
328
|
|
|
342
|
-
|
|
343
|
-
1.
|
|
344
|
-
2. Review \`${jt}\` (activity history)
|
|
345
|
-
3. Work and save outputs to \`outputs/\`
|
|
346
|
-
4. Log progress: \`${R} log append "message"\`
|
|
347
|
-
5. On completion: set status=\`done\`, log summary
|
|
348
|
-
`,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(Tt);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(`---
|
|
349
331
|
name: ${e}
|
|
350
332
|
description: ${S.description}
|
|
351
|
-
---`),console.log(),console.log(
|
|
333
|
+
---`),console.log(),console.log(ht);return}if(t.mode==="hermes"){console.log(`---
|
|
352
334
|
name: ${e}
|
|
353
335
|
description: ${S.description}
|
|
354
336
|
version: ${S.version}
|
|
@@ -357,14 +339,14 @@ license: ${S.license}
|
|
|
357
339
|
metadata:
|
|
358
340
|
hermes:
|
|
359
341
|
tags: [${S.keywords.join(", ")}]
|
|
360
|
-
---`),console.log(),console.log(
|
|
361
|
-
`)),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
|
|
362
|
-
`)},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(
|
|
363
|
-
/** ${t} hook for ${
|
|
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} */
|
|
364
346
|
|
|
365
347
|
import { env } from 'node:process'
|
|
366
348
|
|
|
367
|
-
console.log('Running ${t} hook for ${
|
|
349
|
+
console.log('Running ${t} hook for ${c}')
|
|
368
350
|
console.log('PROJECT_SLUG:', env.PROJECT_SLUG)
|
|
369
351
|
if (env.TASK_SLUG) {
|
|
370
352
|
console.log('TASK_SLUG:', env.TASK_SLUG)
|
|
@@ -372,10 +354,10 @@ if (env.TASK_SLUG) {
|
|
|
372
354
|
|
|
373
355
|
// Exit with non-zero to prevent action (for pre-hooks)
|
|
374
356
|
// process.exit(1)
|
|
375
|
-
`;else if(r==="js")
|
|
376
|
-
/** ${t} hook for ${
|
|
357
|
+
`;else if(r==="js")g=`#!/usr/bin/env node
|
|
358
|
+
/** ${t} hook for ${c} */
|
|
377
359
|
|
|
378
|
-
console.log('Running ${t} hook for ${
|
|
360
|
+
console.log('Running ${t} hook for ${c}')
|
|
379
361
|
console.log('PROJECT_SLUG:', process.env.PROJECT_SLUG)
|
|
380
362
|
if (process.env.TASK_SLUG) {
|
|
381
363
|
console.log('TASK_SLUG:', process.env.TASK_SLUG)
|
|
@@ -383,10 +365,10 @@ if (process.env.TASK_SLUG) {
|
|
|
383
365
|
|
|
384
366
|
// Exit with non-zero to prevent action (for pre-hooks)
|
|
385
367
|
// process.exit(1)
|
|
386
|
-
`;else if(r==="sh")
|
|
387
|
-
# ${t} hook for ${
|
|
368
|
+
`;else if(r==="sh")g=`#!/bin/bash
|
|
369
|
+
# ${t} hook for ${c}
|
|
388
370
|
|
|
389
|
-
echo "Running ${t} hook for ${
|
|
371
|
+
echo "Running ${t} hook for ${c}"
|
|
390
372
|
echo "PROJECT_SLUG: $PROJECT_SLUG"
|
|
391
373
|
if [ -n "$TASK_SLUG" ]; then
|
|
392
374
|
echo "TASK_SLUG: $TASK_SLUG"
|
|
@@ -394,25 +376,19 @@ fi
|
|
|
394
376
|
|
|
395
377
|
# Exit with non-zero to prevent action (for pre-hooks)
|
|
396
378
|
# exit 1
|
|
397
|
-
`;else if(r==="py")
|
|
398
|
-
"""${t} hook for ${
|
|
379
|
+
`;else if(r==="py")g=`#!/usr/bin/env python3
|
|
380
|
+
"""${t} hook for ${c}"""
|
|
399
381
|
|
|
400
382
|
import os
|
|
401
383
|
|
|
402
|
-
print(f"Running ${t} hook for ${
|
|
384
|
+
print(f"Running ${t} hook for ${c}")
|
|
403
385
|
print(f"PROJECT_SLUG: {os.environ.get('PROJECT_SLUG')}")
|
|
404
386
|
if os.environ.get('TASK_SLUG'):
|
|
405
387
|
print(f"TASK_SLUG: {os.environ.get('TASK_SLUG')}")
|
|
406
388
|
|
|
407
389
|
# Exit with non-zero to prevent action (for pre-hooks)
|
|
408
390
|
# sys.exit(1)
|
|
409
|
-
`;else throw new Error(`Unsupported language: ${r}`);await s.write(m,
|
|
410
|
-
`},async append(t,e,o,r,n){let i=s.join(t,
|
|
411
|
-
Expected at: ${o}`);await s.logFiles(o);}});});var
|
|
412
|
-
${
|
|
413
|
-
`).filter(m=>m.trim()).length,a=[],l=r?.name||e;i>5&&a.push("High log entry 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(`
|
|
414
|
-
=== Post-Mortem Analysis ===`),console.log(`Project: ${t}`),console.log(`Task: ${e}`),console.log(`Name: ${l}`),console.log(`Status: ${r?.status||"unknown"}`),console.log(`Log entries: ${i}`),a.length>0?(console.log(`
|
|
415
|
-
Suggestions:`),a.forEach(m=>console.log(` - ${m}`))):console.log(`
|
|
416
|
-
No specific suggestions - task looks well-scoped`),console.log(`
|
|
417
|
-
=== End Post-Mortem ===
|
|
418
|
-
`);}});});var Ue,_e=g(()=>{k();j();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 s.logFiles(...t);}});});var yt={};Me(yt,{default:()=>K});var $o,K,rt=g(()=>{Ct();Rt();Lt();Ut();Ht();zt();Jt();Zt();Xt();ee();re();ie();ce();le();de();ge();he();je();we();Pe();xe();ve();Ae();De();Ne();Ie();xt();Fe();_e();$o={agent:{create:Dt,current:Nt,list:It,path:Ft,start:_t},help:{api:Mt,hooks:Bt,quickstart:Wt,skill:Qt,usage:te},hook:{create:oe,run:ne},log:{append:ae,read:pe},project:{create:me,current:ue,list:ke,path:ye,update:Te},skill:{read:be},task:{create:Se,current:$e,ingest:Ee,list:Oe,path:Ce,start:Re,update:pt},util:{postmortem:Le,read:Ue}},K=$o;});W();rt();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 He(t){let[e,o,...r]=t;(e==="--version"||e==="-v")&&(console.log(S.version),process.exit(0));try{(!e||!s.isKeyOf(e,K))&&(await K.help.usage.handler({}),process.exit(1));let n=K[e];(!o||!s.isKeyOf(o,n))&&(await K.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 Hi=He,Ki=K;s.isMain()&&He(process.argv.slice(2));export{Ki as commands,Hi 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};
|