@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 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/open-projects
8
+ bun install -g @hasna/project
9
9
  ```
10
10
 
11
11
  ## CLI
12
12
 
13
13
  ```bash
14
14
  # Register a project
15
- projects create --name my-app --path /path/to/my-app
15
+ project create --name my-app --path /path/to/my-app
16
16
 
17
17
  # List projects
18
- projects list
19
- projects list --status archived
18
+ project list
19
+ project list --status archived
20
20
 
21
21
  # Get details
22
- projects get my-app
22
+ project get my-app
23
23
 
24
24
  # Open a project (cd into it)
25
- cd $(projects open my-app)
25
+ cd $(project open my-app)
26
26
 
27
27
  # Update metadata
28
- projects update my-app --description "My app" --tags "web,ts"
28
+ project update my-app --description "My app" --tags "web,ts"
29
29
 
30
30
  # Archive / unarchive
31
- projects archive my-app
32
- projects unarchive my-app
31
+ project archive my-app
32
+ project unarchive my-app
33
33
 
34
34
  # Import existing directories
35
- projects import /path/to/existing-project
36
- projects import-bulk /path/to/workspace # imports all subdirs
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
- projects update my-app --s3-bucket my-bucket
40
- projects sync my-app
41
- projects sync my-app --direction push
42
- projects sync-all # sync all projects with S3 configured
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
- projects schedule set --interval daily --direction both
46
- projects schedule status
47
- projects schedule remove
45
+ project schedule set --interval daily --direction both
46
+ project schedule status
47
+ project schedule remove
48
48
 
49
49
  # Publish to GitHub
50
- projects publish my-app --org hasnaxyz
51
- projects unpublish my-app
50
+ project publish my-app --org hasnaxyz
51
+ project unpublish my-app
52
52
 
53
53
  # Git passthrough
54
- projects git my-app status
55
- projects git my-app log --oneline -10
54
+ project git my-app status
55
+ project git my-app log --oneline -10
56
56
 
57
57
  # Shell completion
58
- eval "$(projects completion)" # bash
59
- eval "$(projects completion --shell zsh)" # zsh
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": "projects-mcp"
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 subRow = d.query("SELECT id FROM projects WHERE slug LIKE ? ORDER BY length(slug) ASC LIMIT 1").get(`%${idOrSlug}%`);
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: projects update ${project.slug} --s3-bucket <bucket>`);
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 \`projects sync ${project.slug}\` to push changes to S3.
45953
- 3. Use \`projects git ${project.slug} <args>\` to run git commands.
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: \`projects workdir generate ${project.slug}\`*
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
- projects sync ${project.slug}
46002
+ project sync ${project.slug}
45997
46003
 
45998
46004
  # Git operations
45999
- projects git ${project.slug} status
46000
- projects git ${project.slug} log --oneline -10
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,CA4BT;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,CA8B9E;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"}
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 subRow = d.query("SELECT id FROM projects WHERE slug LIKE ? ORDER BY length(slug) ASC LIMIT 1").get(`%${idOrSlug}%`);
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: projects update ${project.slug} --s3-bucket <bucket>`);
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 subRow = d.query("SELECT id FROM projects WHERE slug LIKE ? ORDER BY length(slug) ASC LIMIT 1").get(`%${idOrSlug}%`);
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: projects update ${project.slug} --s3-bucket <bucket>`);
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 \`projects sync ${project.slug}\` to push changes to S3.
47430
- 3. Use \`projects git ${project.slug} <args>\` to run git commands.
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: \`projects workdir generate ${project.slug}\`*
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
- projects sync ${project.slug}
47479
+ project sync ${project.slug}
47474
47480
 
47475
47481
  # Git operations
47476
- projects git ${project.slug} status
47477
- projects git ${project.slug} log --oneline -10
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.2",
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/open-projects.git"
48
+ "url": "https://github.com/hasna/projects.git"
49
49
  },
50
- "homepage": "https://github.com/hasna/open-projects",
50
+ "homepage": "https://github.com/hasna/projects",
51
51
  "bugs": {
52
- "url": "https://github.com/hasna/open-projects/issues"
52
+ "url": "https://github.com/hasna/projects/issues"
53
53
  },
54
54
  "engines": {
55
55
  "bun": ">=1.0.0"