ai-projects 1.6.0 → 1.6.2
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 +76 -91
- package/package.json +6 -10
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
|
|
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 Le=Object.defineProperty;var f=(t,e)=>()=>(t&&(e=t(t=0)),e);var _e=(t,e)=>{for(var o in e)Le(t,o,{get:e[o],enumerable:true});};var S,B=f(()=>{S={name:"ai-projects",version:"1.6.2",type:"module",description:"Useful CLI for AI agents to create and manage projects, tasks, skills and agents",main:"dist/index.js",types:"dist/index.d.ts",bin:{aip:"dist/index.js"},files:["dist/**/*","README.md","LICENSE"],scripts:{build:"npm run build:map && npm run build:code","build:map":"tsx bin/map-commands.ts","build:code":"tsup --no-dts","build:full":"npm run build:map && tsup","build:check":"tsc --noEmit","build:watch":"npm run build:code -- --watch","build:clean":"rimraf dist/*",start:"dist/index.js",dev:'npm run build:watch -- --onSuccess "dist/index.js"',cli:"npm run build && npm start --",ts:"tsx",vitest:"VITE_CJS_IGNORE_WARNING=true vitest",test:"npm run test:types && npm run test:unit","test:unit":"npm run vitest -- run","test:types:test":"tsc -p tsconfig.test.json --incremental --tsBuildInfoFile test.tsbuildinfo","test:types:bin":"tsc -p bin/tsconfig.json --incremental --tsBuildInfoFile bin.tsbuildinfo","test:types":"npm run test:types:test && npm run test:types:bin","test:full":"npm run lint:full && npm run test",eslint:"eslint --cache",lint:"npm run eslint -- '{src,bin}/**/*.ts'","lint:fix":"npm run lint -- --fix","lint:full":"npm run build:check && npm run test:types:bin && npm run lint:fix","lint:full:silent":"npm run -s lint:full && echo LINT OK",prepare:'[ "$CI" != "true" ] && [ -d node_modules/husky ] && husky || true',prepack:"npm run test:full && npm run build:full","publish:dry":"npm pack --dry-run","version:patch":"npm version patch","version:minor":"npm version minor","version:major":"npm version major","agent:stop":"npm run -s lint:full:silent"},keywords:["ai","aip","project","task","kanban","cli","agent","automation"],author:"Ariel Flesler <aflesler@gmail.com>",license:"MIT",repository:{type:"git",url:"git+https://github.com/flesler/ai-projects.git"},homepage:"https://github.com/flesler/ai-projects#readme",bugs:{url:"https://github.com/flesler/ai-projects/issues"},engines:{node:">=20.0.0"},dependencies:{dotenv:"^17.3.1",lodash:"^4.17.21",moment:"^2.30.1",tslib:"^2.8.1",yaml:"^2.8.0",zod:"^3.25.76","zod-opts":"^1.0.0"},devDependencies:{"@eslint/js":"^10.0.1","@stylistic/eslint-plugin":"^5.7.0","@types/dotenv":"^8.2.3","@types/eslint":"^9.6.1","@types/lodash":"^4.17.23","@types/moment":"^2.13.0","@types/node":"^25.0.9","@types/source-map-support":"^0.5.10","@typescript-eslint/eslint-plugin":"^8.53.0","@typescript-eslint/parser":"^8.53.0",eslint:"^10.0.3","eslint-plugin-import-x":"^4.16.2","eslint-plugin-unused-imports":"^4.4.1","fast-glob":"^3.3.3",husky:"^9.1.7",rimraf:"^6.0.1","source-map-support":"^0.5.21",tsup:"^8.5.1",tsx:"^4.20.3","types-package-json":"^2.0.39",typescript:"^5.8.3",vitest:"^4.0.17"}};});function p(t){let{description:e,options:o=z$1.object({}),args:r,handler: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,Ge,D,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}}}Ge={AIP_HOME:J},D=Ge;});var y,s,j=f(()=>{H();y={REPO:fileURLToPath(import.meta.url.replace(/\/(dist|src)\/.*/,"/")),join:(...t)=>rt.join(...t),onRepo:(...t)=>y.join(y.REPO,...t),joinHome:(...t)=>y.join(D.AIP_HOME,...t),async ensureDir(t){await K.mkdir(t,{recursive:true});},async write(t,e){await y.ensureDir(rt.dirname(t)),await K.writeFile(t,e,"utf8");},async append(t,e){await y.ensureDir(rt.dirname(t)),await K.appendFile(t,e,"utf8");},async read(t){return K.readFile(t,"utf8")},async readRepo(...t){return y.read(y.onRepo(...t))},async readMany(...t){return (await Promise.all(t.map(async o=>{let r=await y.fileExists(o)?await y.read(o):"ERROR: File not found";return `# ${o}
|
|
3
3
|
|
|
4
|
-
${r}`}
|
|
4
|
+
${r}`}))).filter(Boolean)},async logFiles(...t){let e=await y.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 y.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=>y.omitByDeep(o,e)):T.isPlainObject(t)?T.mapValues(T.omitBy(t,e),o=>y.omitByDeep(o,e)):t,omitNilsDeep:t=>y.omitByDeep(t,T.isNil),omitUndefinedsDeep:t=>y.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)?y.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,y.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=>y.oneLine(y.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=>y.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=y;});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,Ve,Ze,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],Ve=[a.dirs.TASKS,...Et],Ze={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(D.AIP_HOME,a.dirs.AGENTS,t)},async listProjects(){let t=s.join(D.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(D.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(Ve.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=Ze;});var At,Dt=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 Ot,Ct=f(()=>{k();Ot=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,Ft=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(D.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 Lt,_t=f(()=>{P();k();H();j();Lt=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(D.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,Qe,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"},Qe=(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+=Qe(r,c,d);}}console.log(e);}});});var to,Mt,zt=f(()=>{k();to=`# AIP Hooks
|
|
24
24
|
|
|
25
25
|
Automated scripts that run before/after project/task actions.
|
|
26
26
|
|
|
@@ -200,30 +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(to);}});});var $,Bt,oo,Jt,Vt=f(()=>{B();P();k();$=Object.keys(S.bin)[0],{LOG:Bt}=a.files,oo=`# Quick Start
|
|
204
204
|
|
|
205
205
|
## New Task/Project
|
|
206
206
|
|
|
207
207
|
\`\`\`bash
|
|
208
208
|
# 1. Create project (if needed)
|
|
209
|
-
${
|
|
209
|
+
${$} project create "my-project" --description "What I'm building" --body $'# Goals
|
|
210
210
|
- Build X
|
|
211
211
|
- Solve Y'
|
|
212
212
|
|
|
213
213
|
# 2. Create task (heredoc works too)
|
|
214
|
-
${
|
|
214
|
+
${$} task create my-project "first-task" --description "Start here" --body "$(cat <<< '# Task Details
|
|
215
215
|
- Step 1
|
|
216
216
|
- Step 2')"
|
|
217
217
|
|
|
218
218
|
# 3. Navigate to task
|
|
219
|
-
cd $(${
|
|
219
|
+
cd $(${$} task path first-task)
|
|
220
220
|
|
|
221
221
|
# 4. Start working (implicit from PWD)
|
|
222
|
-
${
|
|
222
|
+
${$} task start
|
|
223
223
|
# \u2192 sets status to in-progress, reads all context to stdout
|
|
224
224
|
|
|
225
225
|
# 5. Work session
|
|
226
|
-
# Log progress: ${
|
|
226
|
+
# Log progress: ${$} log append "API integration complete"
|
|
227
227
|
# Save: outputs/ to deliver, inputs/ for data
|
|
228
228
|
\`\`\`
|
|
229
229
|
|
|
@@ -231,47 +231,56 @@ ${O} task start
|
|
|
231
231
|
|
|
232
232
|
\`\`\`bash
|
|
233
233
|
# Find your tasks (searches all projects)
|
|
234
|
-
${
|
|
234
|
+
${$} task list
|
|
235
235
|
|
|
236
236
|
# Navigate to task
|
|
237
|
-
cd $(${
|
|
237
|
+
cd $(${$} task path task-slug)
|
|
238
238
|
|
|
239
239
|
# All commands work implicitly from PWD:
|
|
240
|
-
${
|
|
240
|
+
${$} task start # Start working (sets status to in-progress, reads all context to stdout)
|
|
241
241
|
\`\`\`
|
|
242
242
|
|
|
243
243
|
## Completing
|
|
244
244
|
|
|
245
245
|
\`\`\`bash
|
|
246
246
|
# Mark done (implicit from PWD)
|
|
247
|
-
${
|
|
248
|
-
${
|
|
247
|
+
${$} task update --status done
|
|
248
|
+
${$} log append "if you want to log something extra"
|
|
249
249
|
\`\`\`
|
|
250
250
|
|
|
251
251
|
## Check current task
|
|
252
252
|
|
|
253
253
|
\`\`\`bash
|
|
254
|
-
${
|
|
254
|
+
${$} task current
|
|
255
255
|
\`\`\`
|
|
256
256
|
|
|
257
|
-
**Note:** All task commands accept an optional task slug, but use PWD if not provided. Navigate with \`cd\` first for smoother workflow.
|
|
257
|
+
**Note:** All task commands (except create) accept an optional task slug, but use PWD if not provided. Navigate with \`cd\` first for smoother workflow.
|
|
258
258
|
|
|
259
259
|
## Structure
|
|
260
260
|
|
|
261
|
-
\`\`\`
|
|
262
261
|
$AIP_HOME/projects/slug/
|
|
263
262
|
\u251C\u2500\u2500 main.md # Definition + body
|
|
264
|
-
\u251C\u2500\u2500 ${
|
|
263
|
+
\u251C\u2500\u2500 ${Bt} # Log (auto-appended, has key task updates too)
|
|
265
264
|
\u2514\u2500\u2500 tasks/task/
|
|
266
265
|
\u251C\u2500\u2500 main.md # Task definition + body
|
|
267
|
-
\u2514\u2500\u2500 ${
|
|
268
|
-
\`\`\`
|
|
266
|
+
\u2514\u2500\u2500 ${Bt} # Updates
|
|
269
267
|
|
|
270
268
|
**Log format:** TSV with columns: date, time, entityType, slug, action, text
|
|
271
269
|
**Example:** \`2026-03-30<TAB>14:30:00<TAB>task<TAB>api-integration<TAB>log<TAB>API integration complete\`
|
|
272
270
|
|
|
273
|
-
|
|
274
|
-
|
|
271
|
+
## Help
|
|
272
|
+
|
|
273
|
+
\`\`\`bash
|
|
274
|
+
# Get all nouns and verbs
|
|
275
|
+
${$} --help
|
|
276
|
+
|
|
277
|
+
# All verbs for a noun
|
|
278
|
+
${$} <noun> --help
|
|
279
|
+
|
|
280
|
+
# All parameters and --options for a command
|
|
281
|
+
${$} <noun> <verb> --help
|
|
282
|
+
\`\`\`
|
|
283
|
+
`,Jt=p({description:"Quick start guide for new users",options:z$1.object({}),handler:async()=>{console.log(oo);}});});var ro,so,no,io,ao,co,po,Wt,ht,q,yt,qt,Yt=f(()=>{B();P();k();x();ro=Object.values(M).join("|"),{PROJECTS:so,TASKS:no,HOOKS:io,INPUTS:ao,OUTPUTS:co,SCRIPTS:po}=a.dirs,{MAIN:Wt,LOG:ht}=a.files,q=Object.keys(S.bin)[0],yt=`# AIP - Project Management Skill
|
|
275
284
|
|
|
276
285
|
Automated project and task creation with proper structure, front-matter, and file organization.
|
|
277
286
|
|
|
@@ -281,25 +290,25 @@ Streamline creation of new projects and tasks with the correct directory structu
|
|
|
281
290
|
|
|
282
291
|
## Quick Start
|
|
283
292
|
|
|
284
|
-
- New user? Run: \`${
|
|
285
|
-
- All commands? Run: \`${
|
|
286
|
-
- Just for one noun? Run: \`${
|
|
287
|
-
- Need EVERYTHING (big)? Run: \`${
|
|
293
|
+
- New user? Run: \`${q} help quickstart\`
|
|
294
|
+
- All commands? Run: \`${q} help usage\`
|
|
295
|
+
- Just for one noun? Run: \`${q} help usage <noun>\` (e.g., \`${q} help usage task\`)
|
|
296
|
+
- Need EVERYTHING (big)? Run: \`${q} help api\` - Shows all commands with full option details
|
|
288
297
|
|
|
289
298
|
## File Structure Overview
|
|
290
299
|
|
|
291
300
|
\`\`\`
|
|
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 ${
|
|
301
|
+
$AIP_HOME/${so}/{project-slug}/
|
|
302
|
+
\u251C\u2500\u2500 ${Wt} # Goals + body (YAML frontmatter + markdown content)
|
|
303
|
+
\u251C\u2500\u2500 ${ht} # Chronological log (TSV: date, time, entityType, slug, action, text)
|
|
304
|
+
\u251C\u2500\u2500 ${io}/ # pre|post-{create,start,update,complete}.*
|
|
305
|
+
\u251C\u2500\u2500 ${co}/ # Deliverables
|
|
306
|
+
\u251C\u2500\u2500 ${ao}/ # External data
|
|
307
|
+
\u251C\u2500\u2500 ${po}/ # Automation
|
|
308
|
+
\u2514\u2500\u2500 ${no}/
|
|
300
309
|
\u2514\u2500\u2500 {task-slug}/
|
|
301
|
-
\u251C\u2500\u2500 ${
|
|
302
|
-
\u251C\u2500\u2500 ${
|
|
310
|
+
\u251C\u2500\u2500 ${Wt} # Task definition + body
|
|
311
|
+
\u251C\u2500\u2500 ${ht} # Activity log
|
|
303
312
|
\u2514\u2500\u2500 ... (same structure)
|
|
304
313
|
\`\`\`
|
|
305
314
|
|
|
@@ -310,27 +319,14 @@ $AIP_HOME/${go}/{project-slug}/
|
|
|
310
319
|
name: Clear Title
|
|
311
320
|
description: One-line summary
|
|
312
321
|
assignee: agent-name
|
|
313
|
-
status: ${
|
|
322
|
+
status: ${ro}
|
|
314
323
|
created: YYYY-MM-DD
|
|
315
324
|
---
|
|
316
325
|
\`\`\`
|
|
317
326
|
|
|
318
327
|
## Body/Content
|
|
319
328
|
|
|
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
|
-
\`\`\`
|
|
329
|
+
Markdown content after frontmatter. See \`aip help quickstart\` for examples of adding body content via CLI.
|
|
334
330
|
|
|
335
331
|
## Best Practices
|
|
336
332
|
|
|
@@ -339,16 +335,11 @@ ${R} project update --body "$(cat new-content.md)"
|
|
|
339
335
|
|
|
340
336
|
## For Agents
|
|
341
337
|
|
|
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(`---
|
|
338
|
+
Typical workflow: read \`main.md\` for context, check \`${ht}\` for history, work, and log progress with \`aip log append\`.
|
|
339
|
+
`,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(yt);return}if(t.mode==="claude"){console.log(`---
|
|
349
340
|
name: ${e}
|
|
350
341
|
description: ${S.description}
|
|
351
|
-
---`),console.log(),console.log(
|
|
342
|
+
---`),console.log(),console.log(yt);return}if(t.mode==="hermes"){console.log(`---
|
|
352
343
|
name: ${e}
|
|
353
344
|
description: ${S.description}
|
|
354
345
|
version: ${S.version}
|
|
@@ -357,14 +348,14 @@ license: ${S.license}
|
|
|
357
348
|
metadata:
|
|
358
349
|
hermes:
|
|
359
350
|
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 ${
|
|
351
|
+
---`),console.log(),console.log(yt);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(`
|
|
352
|
+
`)),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,lo,h,O=f(()=>{P();j();Tt=s.joinHome(a.dirs.PROJECTS),lo={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(`
|
|
353
|
+
`)},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.")}},h=lo;});var te,ee=f(()=>{k();j();O();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}=h.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
|
|
354
|
+
/** ${t} hook for ${c} */
|
|
364
355
|
|
|
365
356
|
import { env } from 'node:process'
|
|
366
357
|
|
|
367
|
-
console.log('Running ${t} hook for ${
|
|
358
|
+
console.log('Running ${t} hook for ${c}')
|
|
368
359
|
console.log('PROJECT_SLUG:', env.PROJECT_SLUG)
|
|
369
360
|
if (env.TASK_SLUG) {
|
|
370
361
|
console.log('TASK_SLUG:', env.TASK_SLUG)
|
|
@@ -372,10 +363,10 @@ if (env.TASK_SLUG) {
|
|
|
372
363
|
|
|
373
364
|
// Exit with non-zero to prevent action (for pre-hooks)
|
|
374
365
|
// process.exit(1)
|
|
375
|
-
`;else if(r==="js")
|
|
376
|
-
/** ${t} hook for ${
|
|
366
|
+
`;else if(r==="js")g=`#!/usr/bin/env node
|
|
367
|
+
/** ${t} hook for ${c} */
|
|
377
368
|
|
|
378
|
-
console.log('Running ${t} hook for ${
|
|
369
|
+
console.log('Running ${t} hook for ${c}')
|
|
379
370
|
console.log('PROJECT_SLUG:', process.env.PROJECT_SLUG)
|
|
380
371
|
if (process.env.TASK_SLUG) {
|
|
381
372
|
console.log('TASK_SLUG:', process.env.TASK_SLUG)
|
|
@@ -383,10 +374,10 @@ if (process.env.TASK_SLUG) {
|
|
|
383
374
|
|
|
384
375
|
// Exit with non-zero to prevent action (for pre-hooks)
|
|
385
376
|
// process.exit(1)
|
|
386
|
-
`;else if(r==="sh")
|
|
387
|
-
# ${t} hook for ${
|
|
377
|
+
`;else if(r==="sh")g=`#!/bin/bash
|
|
378
|
+
# ${t} hook for ${c}
|
|
388
379
|
|
|
389
|
-
echo "Running ${t} hook for ${
|
|
380
|
+
echo "Running ${t} hook for ${c}"
|
|
390
381
|
echo "PROJECT_SLUG: $PROJECT_SLUG"
|
|
391
382
|
if [ -n "$TASK_SLUG" ]; then
|
|
392
383
|
echo "TASK_SLUG: $TASK_SLUG"
|
|
@@ -394,25 +385,19 @@ fi
|
|
|
394
385
|
|
|
395
386
|
# Exit with non-zero to prevent action (for pre-hooks)
|
|
396
387
|
# exit 1
|
|
397
|
-
`;else if(r==="py")
|
|
398
|
-
"""${t} hook for ${
|
|
388
|
+
`;else if(r==="py")g=`#!/usr/bin/env python3
|
|
389
|
+
"""${t} hook for ${c}"""
|
|
399
390
|
|
|
400
391
|
import os
|
|
401
392
|
|
|
402
|
-
print(f"Running ${t} hook for ${
|
|
393
|
+
print(f"Running ${t} hook for ${c}")
|
|
403
394
|
print(f"PROJECT_SLUG: {os.environ.get('PROJECT_SLUG')}")
|
|
404
395
|
if os.environ.get('TASK_SLUG'):
|
|
405
396
|
print(f"TASK_SLUG: {os.environ.get('TASK_SLUG')}")
|
|
406
397
|
|
|
407
398
|
# Exit with non-zero to prevent action (for pre-hooks)
|
|
408
399
|
# 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};
|
|
400
|
+
`;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,v,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:o,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))}},v=fo;});var oe,re=f(()=>{k();z();O();P();oe=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}=h.getTargetDir(e),n={action:t,entityType:r,project:h.getProjectFromPwd()||void 0,task:h.getTaskFromPwd()||void 0};await v.runHooks(o,t,n)||(console.error(`Hook ${t} failed`),process.exit(1)),console.log(`Hook ${t} completed successfully`);}});});var go,w,F=f(()=>{P();O();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}
|
|
401
|
+
`},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=h.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=h.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 se,ne=f(()=>{P();O();k();j();F();se=p({description:"Append a custom entry to log.tsv",options:z$1.object({project:z$1.string().optional().describe("Project slug (uses current project from $PWD if not provided)"),task:z$1.string().optional().describe("Task slug (uses current task from $PWD if not provided)")}),args:z$1.object({text:z$1.string().describe("Text to append")}),handler:async({project:t,task:e,text:o})=>{let r=h.getCurrentContext(),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 ie,ae=f(()=>{P();O();k();j();F();ie=p({description:"Read log.tsv history",options:z$1.object({project:z$1.string().optional().describe("Project slug (uses current project from $PWD if not provided)"),task:z$1.string().optional().describe("Task slug (uses current task from $PWD if not provided)")}),args:z$1.object({}),handler:async({project:t,task:e})=>{let o=h.getCurrentContext(),r=t||o.project;if(!r)throw new Error("No project specified. Use --project or run from a project/task directory");let 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 ce,pe=f(()=>{k();j();F();x();ce=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);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}`),console.log(`Project created: ${i}. Path: ${c}`);}});});var le,de=f(()=>{k();O();le=p({options:z$1.object({}),handler:async()=>{let t=h.getProjectFromPwd();t||(console.error("Not in a project directory"),process.exit(1)),console.log(t);}});});var ue,fe=f(()=>{k();x();ue=p({description:"List all projects, optionally filtered by status",options:z$1.object({status:z$1.string().optional().describe("Filter by status")}),handler:async({status:t})=>{let e=await 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 ge,ke=f(()=>{k();x();ge=p({description:"Output project directory path (for cd)",options:z$1.object({}),args:z$1.object({name:z$1.string().describe("Project name (slug)")}),handler:async({name:t})=>{let e=u.getProjectDir(t);console.log(e);}});});var he,ye=f(()=>{P();O();k();z();j();x();F();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||h.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 v.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,A])=>`${C}=${A}`).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 v.runHooks(d,"post-update",{action:"post-update",entityType:"project"}),console.log(`Project ${c} updated`);}});});var je,Te=f(()=>{P();k();H();j();je=p({description:"Read a skill's SKILL.md file into the console for agent context",options:z$1.object({}),args:z$1.object({name:z$1.string().describe("Skill name (directory name)")}),handler:async({name:t})=>{let e=s.join(D.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}
|
|
402
|
+
Expected at: ${o}`);await s.logFiles(o);}});});var we,be=f(()=>{k();z();j();x();F();we=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 v.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 v.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 Pe,Se=f(()=>{k();O();Pe=p({description:"Get the current task slug from PWD",options:z$1.object({}),handler:async()=>{let t=h.getTaskFromPwd();t||(console.error("Not in a task directory"),process.exit(1)),console.log(t);}});});var xe,$e=f(()=>{O();k();x();xe=p({description:"Output full task context (main.md, log.tsv) for ingestion by agents",options:z$1.object({project:z$1.string().optional().describe("Project slug (searches all projects if not provided)")}),args:z$1.object({task:z$1.string().optional().describe("Task slug (default: from $PWD)")}),handler:async({project:t,task:e})=>{let o=h.getCurrentContext(),r=e??o.task;if(!r)throw new Error("Need task slug (or cd into task dir)");let{project:n}=await u.findTask(r,t);await u.ingestTask(n,r);}});});var ve,Ee=f(()=>{k();x();ve=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 A=await u.getTask(l,C);if(A&&!(i.length>0&&!i.includes(A.status||""))&&!(o&&A.assignee!==o)){if(n){let E=n.toLowerCase(),lt=C.toLowerCase().includes(E),dt=(A.name||"").toLowerCase().includes(E);if(!lt&&!dt)continue}b.push({slug:C,name:A.name||C,status:A.status,assignee:A.assignee});}}b.length>0&&(d[l]=b.sort((C,A)=>C.slug.localeCompare(A.slug)));}let m=Object.keys(d).sort();if(m.length===0){console.log("No tasks found");return}for(let l of m){console.log(`
|
|
403
|
+
${l}:`),console.log("---");for(let g of d[l])console.log(`${g.slug.padEnd(20)} ${g.name?.padEnd(30)||""} ${g.status||""} ${g.assignee||""}`);}}});});var Ae,De=f(()=>{k();x();Ae=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();O();k();z();j();x();F();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=h.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 v.runHooksForContext(b,g,"pre-update",{action:"pre-update",entityType:"task",project:l,task:m}))throw new Error("Pre-update hook failed, aborting update");let E={};if(o&&(E.name=o),r&&(E.description=r),n&&(E.status=n),i&&(E.assignee=i),Object.keys(E).length===0&&!c){console.log("No updates provided");return}if(Object.keys(E).length>0){await u.updateTask(l,m,E);let lt=Object.entries(E).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)`)),E.status&&await w.append(b,"task",m,"updated",`status to ${E.status}`),await v.runHooksForContext(u.getProjectDir(l),g,"post-update",{action:"post-update",entityType:"task",project:l,task:m}),console.log(`Task ${m} updated`);}});});var Oe,Ce=f(()=>{O();k();z();x();Pt();Oe=p({description:"Start a task: set status to in-progress, optionally print context",options:z$1.object({project:z$1.string().optional().describe("Project slug (searches all projects if not provided)"),ingest:z$1.boolean().default(true).describe("Also output context for this task")}),args:z$1.object({task:z$1.string().optional().describe("Task slug (default: from $PWD)")}),handler:async({project:t,task:e,ingest:o})=>{let r=h.getCurrentContext(),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),c=u.getProjectDir(i),d=u.getTaskDir(i,n);if(!await v.runHooksForContext(c,d,"pre-start",{action:"pre-start",entityType:"task",project:i,task:n}))throw new Error("Pre-start hook failed, aborting task start");(await u.getTask(i,n))?.status!=="in-progress"&&await ct.handler({project:i,task:n,status:"in-progress"}),o&&await u.ingestTask(i,n),await v.runHooksForContext(c,d,"post-start",{action:"post-start",entityType:"task",project:i,task:n});}});});var Ne,Re=f(()=>{k();j();Ne=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={};_e(kt,{default:()=>U});var yo,U,ot=f(()=>{Dt();Ct();Rt();Ft();_t();Gt();zt();Vt();Yt();Xt();ee();re();ne();ae();pe();de();fe();ke();ye();Te();be();Se();$e();Ee();De();Ce();Pt();Re();yo={agent:{create:At,current:Ot,list:Nt,path:It,start:Lt},help:{api:Kt,hooks:Mt,quickstart:Jt,skill:qt,usage:Qt},hook:{create:te,run:oe},log:{append:se,read:ie},project:{create:ce,current:le,list:ue,path:ge,update:he},skill:{read:je},task:{create:we,current:Pe,ingest:xe,list:ve,path:Ae,start:Oe,update:ct},util:{read:Ne}},U=yo;});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 Ie(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=Ie,Si=U;s.isMain()&&Ie(process.argv.slice(2));export{Si as commands,Pi as default};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-projects",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Useful CLI for AI agents to create and manage projects, tasks, skills and agents",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -17,11 +17,10 @@
|
|
|
17
17
|
"build": "npm run build:map && npm run build:code",
|
|
18
18
|
"build:map": "tsx bin/map-commands.ts",
|
|
19
19
|
"build:code": "tsup --no-dts",
|
|
20
|
-
"build:
|
|
20
|
+
"build:full": "npm run build:map && tsup",
|
|
21
21
|
"build:check": "tsc --noEmit",
|
|
22
22
|
"build:watch": "npm run build:code -- --watch",
|
|
23
23
|
"build:clean": "rimraf dist/*",
|
|
24
|
-
"build:incr": "tsup --no-dts",
|
|
25
24
|
"start": "dist/index.js",
|
|
26
25
|
"dev": "npm run build:watch -- --onSuccess \"dist/index.js\"",
|
|
27
26
|
"cli": "npm run build && npm start --",
|
|
@@ -29,20 +28,17 @@
|
|
|
29
28
|
"vitest": "VITE_CJS_IGNORE_WARNING=true vitest",
|
|
30
29
|
"test": "npm run test:types && npm run test:unit",
|
|
31
30
|
"test:unit": "npm run vitest -- run",
|
|
32
|
-
"test:types:test": "tsc -p tsconfig.test.json --incremental --tsBuildInfoFile
|
|
33
|
-
"test:types:bin": "tsc -p bin/tsconfig.json --incremental --tsBuildInfoFile
|
|
31
|
+
"test:types:test": "tsc -p tsconfig.test.json --incremental --tsBuildInfoFile test.tsbuildinfo",
|
|
32
|
+
"test:types:bin": "tsc -p bin/tsconfig.json --incremental --tsBuildInfoFile bin.tsbuildinfo",
|
|
34
33
|
"test:types": "npm run test:types:test && npm run test:types:bin",
|
|
35
34
|
"test:full": "npm run lint:full && npm run test",
|
|
36
35
|
"eslint": "eslint --cache",
|
|
37
36
|
"lint": "npm run eslint -- '{src,bin}/**/*.ts'",
|
|
38
37
|
"lint:fix": "npm run lint -- --fix",
|
|
39
|
-
"lint:full": "npm run build:
|
|
38
|
+
"lint:full": "npm run build:check && npm run test:types:bin && npm run lint:fix",
|
|
40
39
|
"lint:full:silent": "npm run -s lint:full && echo LINT OK",
|
|
41
|
-
"map": "npm run build:map",
|
|
42
|
-
"link": "npm link",
|
|
43
|
-
"unlink": "npm unlink",
|
|
44
40
|
"prepare": "[ \"$CI\" != \"true\" ] && [ -d node_modules/husky ] && husky || true",
|
|
45
|
-
"prepack": "npm run test:full && npm run build:
|
|
41
|
+
"prepack": "npm run test:full && npm run build:full",
|
|
46
42
|
"publish:dry": "npm pack --dry-run",
|
|
47
43
|
"version:patch": "npm version patch",
|
|
48
44
|
"version:minor": "npm version minor",
|