@uxmaltech/collab-cli 0.1.0

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.
Files changed (109) hide show
  1. package/README.md +227 -0
  2. package/bin/collab +10 -0
  3. package/dist/cli.js +34 -0
  4. package/dist/commands/canon/index.js +16 -0
  5. package/dist/commands/canon/rebuild.js +95 -0
  6. package/dist/commands/compose/generate.js +63 -0
  7. package/dist/commands/compose/index.js +18 -0
  8. package/dist/commands/compose/validate.js +53 -0
  9. package/dist/commands/doctor.js +153 -0
  10. package/dist/commands/index.js +27 -0
  11. package/dist/commands/infra/down.js +23 -0
  12. package/dist/commands/infra/index.js +20 -0
  13. package/dist/commands/infra/shared.js +59 -0
  14. package/dist/commands/infra/status.js +64 -0
  15. package/dist/commands/infra/up.js +29 -0
  16. package/dist/commands/init.js +830 -0
  17. package/dist/commands/mcp/index.js +20 -0
  18. package/dist/commands/mcp/shared.js +57 -0
  19. package/dist/commands/mcp/start.js +45 -0
  20. package/dist/commands/mcp/status.js +62 -0
  21. package/dist/commands/mcp/stop.js +23 -0
  22. package/dist/commands/seed.js +55 -0
  23. package/dist/commands/uninstall.js +36 -0
  24. package/dist/commands/up.js +78 -0
  25. package/dist/commands/update-canons.js +48 -0
  26. package/dist/commands/upgrade.js +54 -0
  27. package/dist/index.js +14 -0
  28. package/dist/lib/ai-client.js +317 -0
  29. package/dist/lib/ansi.js +58 -0
  30. package/dist/lib/canon-index-generator.js +64 -0
  31. package/dist/lib/canon-index-targets.js +68 -0
  32. package/dist/lib/canon-resolver.js +262 -0
  33. package/dist/lib/canon-scaffold.js +57 -0
  34. package/dist/lib/cli-detection.js +149 -0
  35. package/dist/lib/command-context.js +23 -0
  36. package/dist/lib/compose-defaults.js +47 -0
  37. package/dist/lib/compose-env.js +24 -0
  38. package/dist/lib/compose-paths.js +36 -0
  39. package/dist/lib/compose-renderer.js +134 -0
  40. package/dist/lib/compose-validator.js +56 -0
  41. package/dist/lib/config.js +195 -0
  42. package/dist/lib/credentials.js +63 -0
  43. package/dist/lib/docker-checks.js +73 -0
  44. package/dist/lib/docker-compose.js +15 -0
  45. package/dist/lib/docker-status.js +151 -0
  46. package/dist/lib/domain-gen.js +376 -0
  47. package/dist/lib/ecosystem.js +150 -0
  48. package/dist/lib/env-file.js +77 -0
  49. package/dist/lib/errors.js +30 -0
  50. package/dist/lib/executor.js +85 -0
  51. package/dist/lib/github-auth.js +204 -0
  52. package/dist/lib/hash.js +7 -0
  53. package/dist/lib/health-checker.js +140 -0
  54. package/dist/lib/logger.js +87 -0
  55. package/dist/lib/mcp-client.js +88 -0
  56. package/dist/lib/mode.js +36 -0
  57. package/dist/lib/model-listing.js +102 -0
  58. package/dist/lib/model-registry.js +55 -0
  59. package/dist/lib/npm-operations.js +69 -0
  60. package/dist/lib/orchestrator.js +170 -0
  61. package/dist/lib/parsers.js +42 -0
  62. package/dist/lib/port-resolver.js +57 -0
  63. package/dist/lib/preconditions.js +35 -0
  64. package/dist/lib/preflight.js +88 -0
  65. package/dist/lib/process.js +6 -0
  66. package/dist/lib/prompt.js +125 -0
  67. package/dist/lib/providers.js +117 -0
  68. package/dist/lib/repo-analysis-helpers.js +379 -0
  69. package/dist/lib/repo-scanner.js +195 -0
  70. package/dist/lib/service-health.js +79 -0
  71. package/dist/lib/shell.js +49 -0
  72. package/dist/lib/state.js +38 -0
  73. package/dist/lib/update-checker.js +130 -0
  74. package/dist/lib/version.js +27 -0
  75. package/dist/stages/agent-skills-setup.js +301 -0
  76. package/dist/stages/assistant-setup.js +325 -0
  77. package/dist/stages/canon-ingest.js +249 -0
  78. package/dist/stages/canon-rebuild-graph.js +33 -0
  79. package/dist/stages/canon-rebuild-indexes.js +40 -0
  80. package/dist/stages/canon-rebuild-snapshot.js +75 -0
  81. package/dist/stages/canon-rebuild-validate.js +57 -0
  82. package/dist/stages/canon-rebuild-vectors.js +30 -0
  83. package/dist/stages/canon-scaffold.js +15 -0
  84. package/dist/stages/canon-sync.js +49 -0
  85. package/dist/stages/ci-setup.js +56 -0
  86. package/dist/stages/domain-gen.js +363 -0
  87. package/dist/stages/graph-seed.js +26 -0
  88. package/dist/stages/repo-analysis-fileonly.js +111 -0
  89. package/dist/stages/repo-analysis.js +112 -0
  90. package/dist/stages/repo-scaffold.js +110 -0
  91. package/dist/templates/canon/contracts-readme.js +39 -0
  92. package/dist/templates/canon/domain-readme.js +40 -0
  93. package/dist/templates/canon/evolution/changelog.js +53 -0
  94. package/dist/templates/canon/governance/confidence-levels.js +38 -0
  95. package/dist/templates/canon/governance/implementation-process.js +34 -0
  96. package/dist/templates/canon/governance/review-process.js +29 -0
  97. package/dist/templates/canon/governance/schema-versioning.js +25 -0
  98. package/dist/templates/canon/governance/what-enters-the-canon.js +44 -0
  99. package/dist/templates/canon/index.js +28 -0
  100. package/dist/templates/canon/knowledge-readme.js +129 -0
  101. package/dist/templates/canon/system-prompt.js +101 -0
  102. package/dist/templates/ci/architecture-merge.js +29 -0
  103. package/dist/templates/ci/architecture-pr.js +26 -0
  104. package/dist/templates/ci/index.js +7 -0
  105. package/dist/templates/consolidated.js +114 -0
  106. package/dist/templates/infra.js +90 -0
  107. package/dist/templates/mcp.js +32 -0
  108. package/install.sh +455 -0
  109. package/package.json +48 -0
package/install.sh ADDED
@@ -0,0 +1,455 @@
1
+ #!/bin/sh
2
+ set -eu
3
+
4
+ REPO_URL=${COLLAB_REPO_URL:-https://github.com/uxmaltech/collab-cli.git}
5
+ CANON_REPO_URL=${COLLAB_CANON_REPO_URL:-https://github.com/uxmaltech/collab-architecture.git}
6
+ INSTALL_BASE=${COLLAB_HOME:-$HOME/.collab}
7
+ CLI_DIR="$INSTALL_BASE/cli"
8
+ CANONS_DIR="$INSTALL_BASE/canons/collab-architecture"
9
+ LOCAL_BIN_DIR="$HOME/.local/bin"
10
+ HOMEBREW_BIN_DIR="/opt/homebrew/bin"
11
+ SYSTEM_BIN_DIR="/usr/local/bin"
12
+ MIN_NODE_MAJOR=20
13
+ MODE=install
14
+ PATH_PROMPT_MODE=${COLLAB_INSTALL_PATH_PROMPT:-auto}
15
+
16
+ say() {
17
+ printf '%s\n' "$*"
18
+ }
19
+
20
+ die() {
21
+ printf 'Error: %s\n' "$*" >&2
22
+ exit 1
23
+ }
24
+
25
+ usage() {
26
+ cat <<'EOF'
27
+ Usage: install.sh [--update] [--help]
28
+
29
+ Install collab-cli from uxmaltech/collab-cli main branch.
30
+
31
+ Options:
32
+ --update Update an existing installation in ~/.collab/cli
33
+ --help Show this help message
34
+ EOF
35
+ }
36
+
37
+ parse_args() {
38
+ while [ "$#" -gt 0 ]; do
39
+ case "$1" in
40
+ --update)
41
+ MODE=update
42
+ ;;
43
+ -h|--help)
44
+ usage
45
+ exit 0
46
+ ;;
47
+ *)
48
+ die "Unknown option: $1 (use --help)"
49
+ ;;
50
+ esac
51
+ shift
52
+ done
53
+ }
54
+
55
+ require_cmd() {
56
+ if ! command -v "$1" >/dev/null 2>&1; then
57
+ die "Missing prerequisite: $1"
58
+ fi
59
+ }
60
+
61
+ detect_platform() {
62
+ os_name=$(uname -s 2>/dev/null || printf 'unknown')
63
+ arch_name=$(uname -m 2>/dev/null || printf 'unknown')
64
+
65
+ case "$os_name" in
66
+ Darwin|Linux) ;;
67
+ *) die "Unsupported operating system: $os_name" ;;
68
+ esac
69
+
70
+ case "$os_name/$arch_name" in
71
+ Darwin/arm64|Darwin/x86_64|Linux/x86_64|Linux/amd64) ;;
72
+ *)
73
+ die "Unsupported platform: $os_name/$arch_name (supported: macOS arm64/x86_64, Linux x86_64)"
74
+ ;;
75
+ esac
76
+
77
+ say "Detected platform: $os_name/$arch_name"
78
+ }
79
+
80
+ check_node_version() {
81
+ node_major=$(node -p "process.versions.node.split('.')[0]" 2>/dev/null || printf '0')
82
+
83
+ case "$node_major" in
84
+ ''|*[!0-9]*) die "Unable to read Node.js major version." ;;
85
+ esac
86
+
87
+ if [ "$node_major" -lt "$MIN_NODE_MAJOR" ]; then
88
+ die "Node.js >= $MIN_NODE_MAJOR is required. Found: $(node -v)"
89
+ fi
90
+
91
+ say "Node.js version: $(node -v)"
92
+ }
93
+
94
+ ensure_clean_checkout() {
95
+ if [ -n "$(git -C "$CLI_DIR" status --porcelain 2>/dev/null)" ]; then
96
+ die "Local changes detected in $CLI_DIR. Commit/stash or reset before update."
97
+ fi
98
+ }
99
+
100
+ path_contains_dir() {
101
+ dir=$1
102
+ case ":$PATH:" in
103
+ *":$dir:"*) return 0 ;;
104
+ *) return 1 ;;
105
+ esac
106
+ }
107
+
108
+ is_writable_directory() {
109
+ dir=$1
110
+ [ -d "$dir" ] && [ -w "$dir" ]
111
+ }
112
+
113
+ resolve_bin_dir() {
114
+ local_bin_ready=0
115
+ if [ -d "$LOCAL_BIN_DIR" ] && [ -w "$LOCAL_BIN_DIR" ]; then
116
+ local_bin_ready=1
117
+ elif mkdir -p "$LOCAL_BIN_DIR" 2>/dev/null; then
118
+ local_bin_ready=1
119
+ fi
120
+
121
+ if [ "$local_bin_ready" -eq 1 ] && path_contains_dir "$LOCAL_BIN_DIR"; then
122
+ BIN_DIR=$LOCAL_BIN_DIR
123
+ return
124
+ fi
125
+
126
+ if is_writable_directory "$HOMEBREW_BIN_DIR" && path_contains_dir "$HOMEBREW_BIN_DIR"; then
127
+ BIN_DIR=$HOMEBREW_BIN_DIR
128
+ return
129
+ fi
130
+
131
+ if is_writable_directory "$SYSTEM_BIN_DIR" && path_contains_dir "$SYSTEM_BIN_DIR"; then
132
+ BIN_DIR=$SYSTEM_BIN_DIR
133
+ return
134
+ fi
135
+
136
+ if [ "$local_bin_ready" -eq 1 ]; then
137
+ BIN_DIR=$LOCAL_BIN_DIR
138
+ return
139
+ fi
140
+
141
+ if is_writable_directory "$HOMEBREW_BIN_DIR"; then
142
+ BIN_DIR=$HOMEBREW_BIN_DIR
143
+ return
144
+ fi
145
+
146
+ if is_writable_directory "$SYSTEM_BIN_DIR"; then
147
+ BIN_DIR=$SYSTEM_BIN_DIR
148
+ return
149
+ fi
150
+
151
+ die "Cannot create '$LOCAL_BIN_DIR', and '$HOMEBREW_BIN_DIR'/'$SYSTEM_BIN_DIR' are not writable."
152
+ }
153
+
154
+ sync_repo() {
155
+ if [ "$MODE" = update ]; then
156
+ [ -d "$CLI_DIR/.git" ] || die "No existing installation found at $CLI_DIR for --update."
157
+ ensure_clean_checkout
158
+ say "Updating existing installation in $CLI_DIR from origin/main"
159
+ git -C "$CLI_DIR" fetch origin main
160
+ git -C "$CLI_DIR" checkout main
161
+ git -C "$CLI_DIR" pull --ff-only origin main
162
+ return
163
+ fi
164
+
165
+ if [ -d "$CLI_DIR/.git" ]; then
166
+ ensure_clean_checkout
167
+ say "Existing installation found in $CLI_DIR; refreshing from origin/main"
168
+ git -C "$CLI_DIR" fetch origin main
169
+ git -C "$CLI_DIR" checkout main
170
+ git -C "$CLI_DIR" pull --ff-only origin main
171
+ return
172
+ fi
173
+
174
+ if [ -e "$CLI_DIR" ]; then
175
+ die "Path exists but is not a git checkout: $CLI_DIR"
176
+ fi
177
+
178
+ say "Cloning repository main branch into $CLI_DIR"
179
+ mkdir -p "$INSTALL_BASE"
180
+ git clone --branch main --single-branch "$REPO_URL" "$CLI_DIR"
181
+ }
182
+
183
+ build_cli() {
184
+ say "Installing dependencies"
185
+ (cd "$CLI_DIR" && npm install)
186
+
187
+ say "Building project"
188
+ (cd "$CLI_DIR" && npm run build)
189
+ }
190
+
191
+ sync_canons() {
192
+ if [ -d "$CANONS_DIR/.git" ]; then
193
+ say "Updating collab-architecture canons in $CANONS_DIR"
194
+ git -C "$CANONS_DIR" fetch origin main
195
+ git -C "$CANONS_DIR" checkout main
196
+ git -C "$CANONS_DIR" pull --ff-only origin main
197
+ return
198
+ fi
199
+
200
+ if [ -e "$CANONS_DIR" ]; then
201
+ die "Path exists but is not a git checkout: $CANONS_DIR"
202
+ fi
203
+
204
+ say "Cloning collab-architecture canons into $CANONS_DIR"
205
+ mkdir -p "$(dirname "$CANONS_DIR")"
206
+ git clone --branch main --single-branch "$CANON_REPO_URL" "$CANONS_DIR"
207
+ }
208
+
209
+ link_binary() {
210
+ target="$CLI_DIR/bin/collab"
211
+ link_path="$BIN_DIR/collab"
212
+
213
+ [ -f "$target" ] || die "Missing binary target: $target"
214
+ chmod +x "$target"
215
+
216
+ say "Creating symlink: $link_path -> $target"
217
+ ln -sf "$target" "$link_path"
218
+ }
219
+
220
+ print_path_hint() {
221
+ case ":$PATH:" in
222
+ *":$BIN_DIR:"*)
223
+ say "PATH already includes $BIN_DIR"
224
+ ;;
225
+ *)
226
+ maybe_offer_path_update
227
+ ;;
228
+ esac
229
+ }
230
+
231
+ detect_shell_name() {
232
+ if [ -n "${COLLAB_SHELL:-}" ]; then
233
+ shell_path=$COLLAB_SHELL
234
+ elif [ -n "${SHELL:-}" ]; then
235
+ shell_path=$SHELL
236
+ else
237
+ shell_path=sh
238
+ fi
239
+
240
+ shell_name=$(basename "$shell_path")
241
+ case "$shell_name" in
242
+ zsh|bash|fish)
243
+ printf '%s' "$shell_name"
244
+ ;;
245
+ *)
246
+ printf 'unknown'
247
+ ;;
248
+ esac
249
+ }
250
+
251
+ resolve_shell_rc_file() {
252
+ shell_name=$1
253
+
254
+ case "$shell_name" in
255
+ zsh)
256
+ printf '%s/.zshrc' "$HOME"
257
+ ;;
258
+ bash)
259
+ if [ -f "$HOME/.bashrc" ]; then
260
+ printf '%s/.bashrc' "$HOME"
261
+ elif [ -f "$HOME/.bash_profile" ]; then
262
+ printf '%s/.bash_profile' "$HOME"
263
+ elif [ "${os_name:-}" = "Darwin" ]; then
264
+ printf '%s/.bash_profile' "$HOME"
265
+ else
266
+ printf '%s/.bashrc' "$HOME"
267
+ fi
268
+ ;;
269
+ fish)
270
+ printf '%s/.config/fish/config.fish' "$HOME"
271
+ ;;
272
+ *)
273
+ printf ''
274
+ ;;
275
+ esac
276
+ }
277
+
278
+ append_path_block_if_missing() {
279
+ shell_name=$1
280
+ rc_file=$2
281
+
282
+ case "$shell_name" in
283
+ zsh|bash)
284
+ marker='# collab-cli PATH configuration'
285
+ entry="export PATH=\"$BIN_DIR:\$PATH\""
286
+ if [ -f "$rc_file" ] && grep -F "$entry" "$rc_file" >/dev/null 2>&1; then
287
+ return 0
288
+ fi
289
+
290
+ if ! {
291
+ printf '\n%s\n' "$marker"
292
+ printf '%s\n' "$entry"
293
+ } >> "$rc_file"; then
294
+ return 1
295
+ fi
296
+ return 0
297
+ ;;
298
+ fish)
299
+ if [ -f "$rc_file" ] && grep -F "set -gx PATH \"$BIN_DIR\" \$PATH" "$rc_file" >/dev/null 2>&1; then
300
+ return 0
301
+ fi
302
+
303
+ if ! mkdir -p "$(dirname "$rc_file")"; then
304
+ return 1
305
+ fi
306
+
307
+ if ! {
308
+ printf '\n# collab-cli PATH configuration\n'
309
+ printf 'if not contains "%s" $PATH\n' "$BIN_DIR"
310
+ printf ' set -gx PATH "%s" $PATH\n' "$BIN_DIR"
311
+ printf 'end\n'
312
+ } >> "$rc_file"; then
313
+ return 1
314
+ fi
315
+ return 0
316
+ ;;
317
+ esac
318
+
319
+ return 1
320
+ }
321
+
322
+ print_manual_path_snippet() {
323
+ shell_name=$1
324
+
325
+ case "$shell_name" in
326
+ fish)
327
+ say "Manual PATH snippet: set -gx PATH \"$BIN_DIR\" \$PATH"
328
+ ;;
329
+ *)
330
+ say "Manual PATH snippet: export PATH=\"$BIN_DIR:\$PATH\""
331
+ ;;
332
+ esac
333
+ }
334
+
335
+ path_prompt_enabled() {
336
+ case "$PATH_PROMPT_MODE" in
337
+ always)
338
+ return 0
339
+ ;;
340
+ never)
341
+ return 1
342
+ ;;
343
+ auto|'')
344
+ [ -t 1 ] && [ -r /dev/tty ]
345
+ return $?
346
+ ;;
347
+ *)
348
+ return 1
349
+ ;;
350
+ esac
351
+ }
352
+
353
+ read_prompt_reply() {
354
+ if [ -r /dev/tty ]; then
355
+ IFS= read -r reply < /dev/tty || reply=''
356
+ else
357
+ reply=''
358
+ fi
359
+ }
360
+
361
+ refresh_path_for_installer_process() {
362
+ shell_name=$1
363
+ rc_file=$2
364
+
365
+ case "$shell_name" in
366
+ zsh|bash)
367
+ if [ -r "$rc_file" ]; then
368
+ # shellcheck disable=SC1090
369
+ if . "$rc_file" >/dev/null 2>&1; then
370
+ hash -r 2>/dev/null || true
371
+ return 0
372
+ fi
373
+ fi
374
+ ;;
375
+ esac
376
+
377
+ PATH="$BIN_DIR:$PATH"
378
+ export PATH
379
+ hash -r 2>/dev/null || true
380
+ return 0
381
+ }
382
+
383
+ maybe_offer_path_update() {
384
+ shell_name=$(detect_shell_name)
385
+ rc_file=$(resolve_shell_rc_file "$shell_name")
386
+
387
+ if [ -z "$rc_file" ]; then
388
+ say "Add '$BIN_DIR' to your PATH to call 'collab' globally."
389
+ return
390
+ fi
391
+
392
+ if ! path_prompt_enabled; then
393
+ say "Add '$BIN_DIR' to your PATH to call 'collab' globally."
394
+ return
395
+ fi
396
+
397
+ if [ ! -r /dev/tty ]; then
398
+ say "Add '$BIN_DIR' to your PATH to call 'collab' globally."
399
+ return
400
+ fi
401
+
402
+ printf "Add '%s' to your PATH in %s now? [y/N] " "$BIN_DIR" "$rc_file" > /dev/tty
403
+ read_prompt_reply
404
+
405
+ case "$reply" in
406
+ y|Y|yes|YES|Yes)
407
+ if append_path_block_if_missing "$shell_name" "$rc_file"; then
408
+ say "PATH configuration updated in $rc_file"
409
+ refresh_path_for_installer_process "$shell_name" "$rc_file" || true
410
+ say "Run 'source $rc_file' in your current terminal (or open a new one), then run 'collab --help'."
411
+ else
412
+ say "Could not update $rc_file automatically (permission or write error)."
413
+ print_manual_path_snippet "$shell_name"
414
+ fi
415
+ ;;
416
+ *)
417
+ say "Skipped PATH update. Add '$BIN_DIR' to your PATH to call 'collab' globally."
418
+ ;;
419
+ esac
420
+ }
421
+
422
+ verify_install() {
423
+ if "$BIN_DIR/collab" --help >/dev/null 2>&1; then
424
+ say "Install successful: collab --help"
425
+ else
426
+ die "Installation completed but 'collab --help' failed."
427
+ fi
428
+ }
429
+
430
+ main() {
431
+ parse_args "$@"
432
+
433
+ say "Starting collab-cli installation"
434
+ detect_platform
435
+
436
+ require_cmd git
437
+ require_cmd node
438
+ require_cmd npm
439
+ check_node_version
440
+
441
+ resolve_bin_dir
442
+ say "Using binary directory: $BIN_DIR"
443
+ say "Mode: $MODE"
444
+
445
+ sync_repo
446
+ build_cli
447
+ sync_canons
448
+ link_binary
449
+ verify_install
450
+ print_path_hint
451
+
452
+ say "Done. Run: collab --help"
453
+ }
454
+
455
+ main "$@"
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@uxmaltech/collab-cli",
3
+ "version": "0.1.0",
4
+ "description": "CLI for collaborative architecture and delivery workflows.",
5
+ "private": false,
6
+ "license": "UNLICENSED",
7
+ "publishConfig": {
8
+ "access": "public"
9
+ },
10
+ "bin": {
11
+ "collab": "bin/collab"
12
+ },
13
+ "engines": {
14
+ "node": ">=20.0.0"
15
+ },
16
+ "files": [
17
+ "bin",
18
+ "dist",
19
+ "README.md",
20
+ "LICENSE",
21
+ "install.sh"
22
+ ],
23
+ "scripts": {
24
+ "build": "tsc -p tsconfig.json",
25
+ "clean": "rm -rf dist",
26
+ "lint": "eslint \"src/**/*.ts\"",
27
+ "format": "prettier --check .",
28
+ "format:write": "prettier --write .",
29
+ "pack:dry-run": "npm pack --dry-run",
30
+ "start": "node dist/index.js",
31
+ "test": "npm run build && node scripts/run-tests.mjs",
32
+ "test:e2e": "npm run build && COLLAB_RUN_E2E=1 node --test tests/e2e/full-flow.test.mjs",
33
+ "typecheck": "tsc -p tsconfig.json --noEmit"
34
+ },
35
+ "dependencies": {
36
+ "commander": "^14.0.2",
37
+ "semver": "^7.7.3"
38
+ },
39
+ "devDependencies": {
40
+ "@types/node": "^24.6.0",
41
+ "@types/semver": "^7.7.1",
42
+ "eslint": "^9.39.3",
43
+ "eslint-config-prettier": "^10.1.8",
44
+ "prettier": "^3.6.2",
45
+ "typescript": "^5.9.3",
46
+ "typescript-eslint": "^8.56.1"
47
+ }
48
+ }