@hasna/project 0.1.2 → 0.1.4
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 +25 -25
- package/dist/cli/index.js +14 -8
- package/dist/db/projects.d.ts.map +1 -1
- package/dist/index.js +8 -2
- package/dist/mcp/index.js +14 -8
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -5,58 +5,58 @@ Project management CLI + MCP server for AI agents. Register projects once, open
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
bun install -g @hasna/
|
|
8
|
+
bun install -g @hasna/project
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
## CLI
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
14
|
# Register a project
|
|
15
|
-
|
|
15
|
+
project create --name my-app --path /path/to/my-app
|
|
16
16
|
|
|
17
17
|
# List projects
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
project list
|
|
19
|
+
project list --status archived
|
|
20
20
|
|
|
21
21
|
# Get details
|
|
22
|
-
|
|
22
|
+
project get my-app
|
|
23
23
|
|
|
24
24
|
# Open a project (cd into it)
|
|
25
|
-
cd $(
|
|
25
|
+
cd $(project open my-app)
|
|
26
26
|
|
|
27
27
|
# Update metadata
|
|
28
|
-
|
|
28
|
+
project update my-app --description "My app" --tags "web,ts"
|
|
29
29
|
|
|
30
30
|
# Archive / unarchive
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
project archive my-app
|
|
32
|
+
project unarchive my-app
|
|
33
33
|
|
|
34
34
|
# Import existing directories
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
project import /path/to/existing-project
|
|
36
|
+
project import-bulk /path/to/workspace # imports all subdirs
|
|
37
37
|
|
|
38
38
|
# Sync to/from S3
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
project update my-app --s3-bucket my-bucket
|
|
40
|
+
project sync my-app
|
|
41
|
+
project sync my-app --direction push
|
|
42
|
+
project sync-all # sync all projects with S3 configured
|
|
43
43
|
|
|
44
44
|
# Schedule auto-sync
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
project schedule set --interval daily --direction both
|
|
46
|
+
project schedule status
|
|
47
|
+
project schedule remove
|
|
48
48
|
|
|
49
49
|
# Publish to GitHub
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
project publish my-app --org hasnaxyz
|
|
51
|
+
project unpublish my-app
|
|
52
52
|
|
|
53
53
|
# Git passthrough
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
project git my-app status
|
|
55
|
+
project git my-app log --oneline -10
|
|
56
56
|
|
|
57
57
|
# Shell completion
|
|
58
|
-
eval "$(
|
|
59
|
-
eval "$(
|
|
58
|
+
eval "$(project completion)" # bash
|
|
59
|
+
eval "$(project completion --shell zsh)" # zsh
|
|
60
60
|
```
|
|
61
61
|
|
|
62
62
|
## MCP Server
|
|
@@ -67,7 +67,7 @@ Add to your Claude config:
|
|
|
67
67
|
{
|
|
68
68
|
"mcpServers": {
|
|
69
69
|
"open-projects": {
|
|
70
|
-
"command": "
|
|
70
|
+
"command": "project-mcp"
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
}
|
package/dist/cli/index.js
CHANGED
|
@@ -36382,6 +36382,9 @@ function updateProject(id, input, db) {
|
|
|
36382
36382
|
if (input.name !== undefined) {
|
|
36383
36383
|
sets.push("name = ?");
|
|
36384
36384
|
params.push(input.name);
|
|
36385
|
+
const newSlug = ensureUniqueSlug(slugify(input.name), d, id);
|
|
36386
|
+
sets.push("slug = ?");
|
|
36387
|
+
params.push(newSlug);
|
|
36385
36388
|
}
|
|
36386
36389
|
if (input.description !== undefined) {
|
|
36387
36390
|
sets.push("description = ?");
|
|
@@ -36456,7 +36459,10 @@ function resolveProject(idOrSlug, db) {
|
|
|
36456
36459
|
const prefixRow = d.query("SELECT id FROM projects WHERE id LIKE ? LIMIT 1").get(`${idOrSlug}%`);
|
|
36457
36460
|
if (prefixRow)
|
|
36458
36461
|
return getProject(prefixRow.id, d);
|
|
36459
|
-
const
|
|
36462
|
+
const nameRow = d.query("SELECT id FROM projects WHERE name = ? LIMIT 1").get(idOrSlug);
|
|
36463
|
+
if (nameRow)
|
|
36464
|
+
return getProject(nameRow.id, d);
|
|
36465
|
+
const subRow = d.query("SELECT id FROM projects WHERE slug LIKE ? OR name LIKE ? ORDER BY length(slug) ASC LIMIT 1").get(`%${idOrSlug}%`, `%${idOrSlug}%`);
|
|
36460
36466
|
if (subRow)
|
|
36461
36467
|
return getProject(subRow.id, d);
|
|
36462
36468
|
const allRows = d.query("SELECT id, slug FROM projects WHERE status = 'active'").all();
|
|
@@ -45582,7 +45588,7 @@ async function syncProject(project, options = {}) {
|
|
|
45582
45588
|
const region = options.region ?? process.env["AWS_DEFAULT_REGION"] ?? "us-east-1";
|
|
45583
45589
|
const log = options.onProgress ?? (() => {});
|
|
45584
45590
|
if (!project.s3_bucket) {
|
|
45585
|
-
throw new Error(`Project "${project.name}" has no s3_bucket configured. Run:
|
|
45591
|
+
throw new Error(`Project "${project.name}" has no s3_bucket configured. Run: project update ${project.slug} --s3-bucket <bucket>`);
|
|
45586
45592
|
}
|
|
45587
45593
|
const client = makeS3Client(region);
|
|
45588
45594
|
const bucket = project.s3_bucket;
|
|
@@ -45949,12 +45955,12 @@ ${buildWorkdirList(allWorkdirs, workdir.path)}
|
|
|
45949
45955
|
## Instructions for AI Agents
|
|
45950
45956
|
|
|
45951
45957
|
1. **Write code in \`${workdir.path}\`** \u2014 this is your working directory for this session.
|
|
45952
|
-
2. Use \`
|
|
45953
|
-
3. Use \`
|
|
45958
|
+
2. Use \`project sync ${project.slug}\` to push changes to S3.
|
|
45959
|
+
3. Use \`project git ${project.slug} <args>\` to run git commands.
|
|
45954
45960
|
4. If you need to switch to a different workdir, call \`projects_open\` with the project ID.
|
|
45955
45961
|
|
|
45956
45962
|
---
|
|
45957
|
-
*Generated by open-projects. Regenerate: \`
|
|
45963
|
+
*Generated by open-projects. Regenerate: \`project workdir generate ${project.slug}\`*
|
|
45958
45964
|
`.trimStart();
|
|
45959
45965
|
}
|
|
45960
45966
|
function agentsMdContent(project, workdir, allWorkdirs) {
|
|
@@ -45993,11 +45999,11 @@ ${otherDirs.map((w2) => `- \`${w2.path}\` [${w2.label}] on ${w2.machine_id}`).jo
|
|
|
45993
45999
|
cd ${workdir.path}
|
|
45994
46000
|
|
|
45995
46001
|
# Sync to S3
|
|
45996
|
-
|
|
46002
|
+
project sync ${project.slug}
|
|
45997
46003
|
|
|
45998
46004
|
# Git operations
|
|
45999
|
-
|
|
46000
|
-
|
|
46005
|
+
project git ${project.slug} status
|
|
46006
|
+
project git ${project.slug} log --oneline -10
|
|
46001
46007
|
\`\`\`
|
|
46002
46008
|
${Object.keys(project.integrations).length ? `
|
|
46003
46009
|
## Service IDs
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"projects.d.ts","sourceRoot":"","sources":["../../src/db/projects.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAoB,MAAM,YAAY,CAAC;AAE7D,OAAO,KAAK,EACV,kBAAkB,EAClB,kBAAkB,EAClB,OAAO,EAEP,aAAa,EACb,mBAAmB,EACnB,OAAO,EAEP,aAAa,EACd,MAAM,mBAAmB,CAAC;AAc3B,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK5C;AAwBD,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,OAAO,CAmD/E;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,IAAI,CAMpE;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,IAAI,CAM5E;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,IAAI,CAM5E;AAED,wBAAgB,YAAY,CAAC,MAAM,GAAE,aAAkB,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,OAAO,EAAE,CAmBjF;AAED,wBAAgB,aAAa,CAC3B,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,kBAAkB,EACzB,EAAE,CAAC,EAAE,QAAQ,GACZ,OAAO,
|
|
1
|
+
{"version":3,"file":"projects.d.ts","sourceRoot":"","sources":["../../src/db/projects.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAoB,MAAM,YAAY,CAAC;AAE7D,OAAO,KAAK,EACV,kBAAkB,EAClB,kBAAkB,EAClB,OAAO,EAEP,aAAa,EACb,mBAAmB,EACnB,OAAO,EAEP,aAAa,EACd,MAAM,mBAAmB,CAAC;AAc3B,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK5C;AAwBD,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,OAAO,CAmD/E;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,IAAI,CAMpE;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,IAAI,CAM5E;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,IAAI,CAM5E;AAED,wBAAgB,YAAY,CAAC,MAAM,GAAE,aAAkB,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,OAAO,EAAE,CAmBjF;AAED,wBAAgB,aAAa,CAC3B,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,kBAAkB,EACzB,EAAE,CAAC,EAAE,QAAQ,GACZ,OAAO,CAmCT;AAGD,wBAAgB,eAAe,CAC7B,EAAE,EAAE,MAAM,EACV,YAAY,EAAE,mBAAmB,EACjC,EAAE,CAAC,EAAE,QAAQ,GACZ,OAAO,CAqBT;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,OAAO,CAMjE;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,OAAO,CAMnE;AAeD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,IAAI,CAoC9E;AAOD,wBAAgB,YAAY,CAC1B,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,aAAa,EACxB,EAAE,CAAC,EAAE,QAAQ,GACZ,OAAO,CAST;AAED,wBAAgB,eAAe,CAC7B,EAAE,EAAE,MAAM,EACV,MAAM,EAAE;IAAE,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,EACjE,EAAE,CAAC,EAAE,QAAQ,GACZ,OAAO,CAST;AAED,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,SAAK,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,OAAO,EAAE,CAMpF"}
|
package/dist/index.js
CHANGED
|
@@ -22658,6 +22658,9 @@ function updateProject(id, input, db) {
|
|
|
22658
22658
|
if (input.name !== undefined) {
|
|
22659
22659
|
sets.push("name = ?");
|
|
22660
22660
|
params.push(input.name);
|
|
22661
|
+
const newSlug = ensureUniqueSlug(slugify(input.name), d, id);
|
|
22662
|
+
sets.push("slug = ?");
|
|
22663
|
+
params.push(newSlug);
|
|
22661
22664
|
}
|
|
22662
22665
|
if (input.description !== undefined) {
|
|
22663
22666
|
sets.push("description = ?");
|
|
@@ -22753,7 +22756,10 @@ function resolveProject(idOrSlug, db) {
|
|
|
22753
22756
|
const prefixRow = d.query("SELECT id FROM projects WHERE id LIKE ? LIMIT 1").get(`${idOrSlug}%`);
|
|
22754
22757
|
if (prefixRow)
|
|
22755
22758
|
return getProject(prefixRow.id, d);
|
|
22756
|
-
const
|
|
22759
|
+
const nameRow = d.query("SELECT id FROM projects WHERE name = ? LIMIT 1").get(idOrSlug);
|
|
22760
|
+
if (nameRow)
|
|
22761
|
+
return getProject(nameRow.id, d);
|
|
22762
|
+
const subRow = d.query("SELECT id FROM projects WHERE slug LIKE ? OR name LIKE ? ORDER BY length(slug) ASC LIMIT 1").get(`%${idOrSlug}%`, `%${idOrSlug}%`);
|
|
22757
22763
|
if (subRow)
|
|
22758
22764
|
return getProject(subRow.id, d);
|
|
22759
22765
|
const allRows = d.query("SELECT id, slug FROM projects WHERE status = 'active'").all();
|
|
@@ -31858,7 +31864,7 @@ async function syncProject(project, options = {}) {
|
|
|
31858
31864
|
const region = options.region ?? process.env["AWS_DEFAULT_REGION"] ?? "us-east-1";
|
|
31859
31865
|
const log = options.onProgress ?? (() => {});
|
|
31860
31866
|
if (!project.s3_bucket) {
|
|
31861
|
-
throw new Error(`Project "${project.name}" has no s3_bucket configured. Run:
|
|
31867
|
+
throw new Error(`Project "${project.name}" has no s3_bucket configured. Run: project update ${project.slug} --s3-bucket <bucket>`);
|
|
31862
31868
|
}
|
|
31863
31869
|
const client = makeS3Client(region);
|
|
31864
31870
|
const bucket = project.s3_bucket;
|
package/dist/mcp/index.js
CHANGED
|
@@ -37811,6 +37811,9 @@ function updateProject(id, input, db) {
|
|
|
37811
37811
|
if (input.name !== undefined) {
|
|
37812
37812
|
sets.push("name = ?");
|
|
37813
37813
|
params.push(input.name);
|
|
37814
|
+
const newSlug = ensureUniqueSlug(slugify(input.name), d, id);
|
|
37815
|
+
sets.push("slug = ?");
|
|
37816
|
+
params.push(newSlug);
|
|
37814
37817
|
}
|
|
37815
37818
|
if (input.description !== undefined) {
|
|
37816
37819
|
sets.push("description = ?");
|
|
@@ -37898,7 +37901,10 @@ function resolveProject(idOrSlug, db) {
|
|
|
37898
37901
|
const prefixRow = d.query("SELECT id FROM projects WHERE id LIKE ? LIMIT 1").get(`${idOrSlug}%`);
|
|
37899
37902
|
if (prefixRow)
|
|
37900
37903
|
return getProject(prefixRow.id, d);
|
|
37901
|
-
const
|
|
37904
|
+
const nameRow = d.query("SELECT id FROM projects WHERE name = ? LIMIT 1").get(idOrSlug);
|
|
37905
|
+
if (nameRow)
|
|
37906
|
+
return getProject(nameRow.id, d);
|
|
37907
|
+
const subRow = d.query("SELECT id FROM projects WHERE slug LIKE ? OR name LIKE ? ORDER BY length(slug) ASC LIMIT 1").get(`%${idOrSlug}%`, `%${idOrSlug}%`);
|
|
37902
37908
|
if (subRow)
|
|
37903
37909
|
return getProject(subRow.id, d);
|
|
37904
37910
|
const allRows = d.query("SELECT id, slug FROM projects WHERE status = 'active'").all();
|
|
@@ -47004,7 +47010,7 @@ async function syncProject(project, options = {}) {
|
|
|
47004
47010
|
const region = options.region ?? process.env["AWS_DEFAULT_REGION"] ?? "us-east-1";
|
|
47005
47011
|
const log = options.onProgress ?? (() => {});
|
|
47006
47012
|
if (!project.s3_bucket) {
|
|
47007
|
-
throw new Error(`Project "${project.name}" has no s3_bucket configured. Run:
|
|
47013
|
+
throw new Error(`Project "${project.name}" has no s3_bucket configured. Run: project update ${project.slug} --s3-bucket <bucket>`);
|
|
47008
47014
|
}
|
|
47009
47015
|
const client = makeS3Client(region);
|
|
47010
47016
|
const bucket = project.s3_bucket;
|
|
@@ -47426,12 +47432,12 @@ ${buildWorkdirList(allWorkdirs, workdir.path)}
|
|
|
47426
47432
|
## Instructions for AI Agents
|
|
47427
47433
|
|
|
47428
47434
|
1. **Write code in \`${workdir.path}\`** \u2014 this is your working directory for this session.
|
|
47429
|
-
2. Use \`
|
|
47430
|
-
3. Use \`
|
|
47435
|
+
2. Use \`project sync ${project.slug}\` to push changes to S3.
|
|
47436
|
+
3. Use \`project git ${project.slug} <args>\` to run git commands.
|
|
47431
47437
|
4. If you need to switch to a different workdir, call \`projects_open\` with the project ID.
|
|
47432
47438
|
|
|
47433
47439
|
---
|
|
47434
|
-
*Generated by open-projects. Regenerate: \`
|
|
47440
|
+
*Generated by open-projects. Regenerate: \`project workdir generate ${project.slug}\`*
|
|
47435
47441
|
`.trimStart();
|
|
47436
47442
|
}
|
|
47437
47443
|
function agentsMdContent(project, workdir, allWorkdirs) {
|
|
@@ -47470,11 +47476,11 @@ ${otherDirs.map((w2) => `- \`${w2.path}\` [${w2.label}] on ${w2.machine_id}`).jo
|
|
|
47470
47476
|
cd ${workdir.path}
|
|
47471
47477
|
|
|
47472
47478
|
# Sync to S3
|
|
47473
|
-
|
|
47479
|
+
project sync ${project.slug}
|
|
47474
47480
|
|
|
47475
47481
|
# Git operations
|
|
47476
|
-
|
|
47477
|
-
|
|
47482
|
+
project git ${project.slug} status
|
|
47483
|
+
project git ${project.slug} log --oneline -10
|
|
47478
47484
|
\`\`\`
|
|
47479
47485
|
${Object.keys(project.integrations).length ? `
|
|
47480
47486
|
## Service IDs
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hasna/project",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Project management CLI + MCP server for AI agents — register, sync, and open projects across machines",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -45,11 +45,11 @@
|
|
|
45
45
|
},
|
|
46
46
|
"repository": {
|
|
47
47
|
"type": "git",
|
|
48
|
-
"url": "https://github.com/hasna/
|
|
48
|
+
"url": "https://github.com/hasna/projects.git"
|
|
49
49
|
},
|
|
50
|
-
"homepage": "https://github.com/hasna/
|
|
50
|
+
"homepage": "https://github.com/hasna/projects",
|
|
51
51
|
"bugs": {
|
|
52
|
-
"url": "https://github.com/hasna/
|
|
52
|
+
"url": "https://github.com/hasna/projects/issues"
|
|
53
53
|
},
|
|
54
54
|
"engines": {
|
|
55
55
|
"bun": ">=1.0.0"
|