prjct-cli 0.25.0 → 0.25.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/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.25.1] - 2026-01-01
4
+
5
+ ### Bug Fix: npm install symlink resolution
6
+
7
+ **Fixed:** CLI fails when invoked via npm symlink (`node_modules/.bin/prjct`)
8
+
9
+ **Root Cause:**
10
+ The shell wrapper script `bin/prjct` used `dirname "$0"` to find `prjct.ts`, which returns the symlink's directory (`.bin/`) instead of the actual script location (`prjct-cli/bin/`).
11
+
12
+ **Solution:**
13
+ Added `resolve_symlink()` function that properly resolves symlinks before determining paths. Works on both Linux (`readlink -f`) and macOS (manual resolution fallback).
14
+
15
+ **Files Changed:**
16
+ - `bin/prjct` - Added symlink resolution (v1.0.0 → v1.1.0)
17
+
3
18
  ## [0.25.0] - 2025-12-30
4
19
 
5
20
  ### Maintenance Release
package/bin/prjct CHANGED
@@ -5,10 +5,40 @@
5
5
  # Detects available runtime (bun preferred, node fallback)
6
6
  # and executes the appropriate entry point.
7
7
  #
8
- # @version 1.0.0
8
+ # @version 1.1.0
9
9
 
10
- # Get the directory where this script is located
11
- SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
10
+ # Resolve symlinks to get the actual script location
11
+ resolve_symlink() {
12
+ TARGET="$1"
13
+
14
+ # Try readlink -f (Linux, newer macOS)
15
+ if command -v readlink >/dev/null 2>&1; then
16
+ RESOLVED="$(readlink -f "$TARGET" 2>/dev/null)"
17
+ if [ -n "$RESOLVED" ]; then
18
+ echo "$RESOLVED"
19
+ return
20
+ fi
21
+ fi
22
+
23
+ # Fallback: manual symlink resolution
24
+ while [ -L "$TARGET" ]; do
25
+ DIR="$(dirname "$TARGET")"
26
+ TARGET="$(readlink "$TARGET")"
27
+ # Handle relative symlinks
28
+ case "$TARGET" in
29
+ /*) ;;
30
+ *) TARGET="$DIR/$TARGET" ;;
31
+ esac
32
+ done
33
+
34
+ # Get absolute path
35
+ DIR="$(cd "$(dirname "$TARGET")" && pwd)"
36
+ echo "$DIR/$(basename "$TARGET")"
37
+ }
38
+
39
+ # Get the actual script location (resolving symlinks)
40
+ SCRIPT_PATH="$(resolve_symlink "$0")"
41
+ SCRIPT_DIR="$(dirname "$SCRIPT_PATH")"
12
42
  ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
13
43
 
14
44
  # Check if bun is available
@@ -117,6 +117,9 @@ export async function run(): Promise<SetupResults> {
117
117
  // Step 5: Save version in editors-config
118
118
  await editorsConfig.saveConfig(VERSION, installer.getInstallPath())
119
119
 
120
+ // Step 6: Migrate existing projects to add cliVersion
121
+ await migrateProjectsCliVersion()
122
+
120
123
  // Show results
121
124
  showResults(results)
122
125
 
@@ -126,6 +129,54 @@ export async function run(): Promise<SetupResults> {
126
129
  // Default export for CommonJS require
127
130
  export default { run }
128
131
 
132
+ /**
133
+ * Migrate existing projects to add cliVersion field
134
+ * This clears the status line warning after npm update
135
+ */
136
+ async function migrateProjectsCliVersion(): Promise<void> {
137
+ try {
138
+ const projectsDir = path.join(os.homedir(), '.prjct-cli', 'projects')
139
+
140
+ if (!fs.existsSync(projectsDir)) {
141
+ return
142
+ }
143
+
144
+ const projectDirs = fs.readdirSync(projectsDir, { withFileTypes: true })
145
+ .filter(dirent => dirent.isDirectory())
146
+ .map(dirent => dirent.name)
147
+
148
+ let migrated = 0
149
+
150
+ for (const projectId of projectDirs) {
151
+ const projectJsonPath = path.join(projectsDir, projectId, 'project.json')
152
+
153
+ if (!fs.existsSync(projectJsonPath)) {
154
+ continue
155
+ }
156
+
157
+ try {
158
+ const content = fs.readFileSync(projectJsonPath, 'utf8')
159
+ const project = JSON.parse(content)
160
+
161
+ // Only update if cliVersion is missing or different
162
+ if (project.cliVersion !== VERSION) {
163
+ project.cliVersion = VERSION
164
+ fs.writeFileSync(projectJsonPath, JSON.stringify(project, null, 2))
165
+ migrated++
166
+ }
167
+ } catch {
168
+ // Skip invalid project.json files
169
+ }
170
+ }
171
+
172
+ if (migrated > 0) {
173
+ console.log(` ${GREEN}✓${NC} Updated ${migrated} project(s) to v${VERSION}`)
174
+ }
175
+ } catch {
176
+ // Silently fail - migration is optional
177
+ }
178
+ }
179
+
129
180
  /**
130
181
  * Install status line script with version check
131
182
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prjct-cli",
3
- "version": "0.25.0",
3
+ "version": "0.25.2",
4
4
  "description": "Built for Claude - Ship fast, track progress, stay focused. Developer momentum tool for indie hackers.",
5
5
  "main": "core/index.ts",
6
6
  "bin": {
@@ -383,20 +383,25 @@ WRITE: `{globalPath}/context/CLAUDE.md`
383
383
 
384
384
  ---
385
385
 
386
- ## Step 6: Update project.json
386
+ ## Step 6: Update project.json (CRITICAL: cliVersion)
387
387
 
388
- READ existing: `{globalPath}/project.json` (preserve createdAt)
388
+ READ existing: `{globalPath}/project.json` (preserve createdAt, integrations)
389
389
 
390
- GET CLI version:
390
+ GET CLI version (REQUIRED - this clears the status line warning):
391
391
  ```bash
392
392
  bun -e "console.log(require('./package.json').version)" 2>/dev/null || node -e "console.log(require('./package.json').version)"
393
393
  ```
394
- SET: `{cliVersion}` = result (e.g., "0.24.0")
394
+ SET: `{cliVersion}` = result (e.g., "0.25.1")
395
395
 
396
396
  CHECK: `{previousCliVersion}` = existing.cliVersion (if any)
397
- SET: `{isVersionUpgrade}` = previousCliVersion != cliVersion
397
+ SET: `{isVersionUpgrade}` = previousCliVersion != cliVersion OR previousCliVersion is missing
398
398
 
399
- WRITE: `{globalPath}/project.json`
399
+ **CRITICAL**: The `cliVersion` field MUST be written to project.json. This field:
400
+ - Clears the "⚠️ prjct v{version} available!" status line warning
401
+ - Indicates which CLI version last synced this project
402
+ - If missing, the warning will persist even after sync
403
+
404
+ WRITE: `{globalPath}/project.json` (merge with existing, but ALWAYS update these fields):
400
405
 
401
406
  ```json
402
407
  {
@@ -404,7 +409,7 @@ WRITE: `{globalPath}/project.json`
404
409
  "repoPath": "{cwd}",
405
410
  "name": "{projectName}",
406
411
  "version": "{version}",
407
- "cliVersion": "{cliVersion}",
412
+ "cliVersion": "{cliVersion}", // ← REQUIRED: Must match CLI version to clear warning
408
413
  "techStack": {techStack},
409
414
  "fileCount": {fileCount},
410
415
  "commitCount": {commitCount},
@@ -412,7 +417,8 @@ WRITE: `{globalPath}/project.json`
412
417
  "currentBranch": "{currentBranch}",
413
418
  "hasUncommittedChanges": {hasUncommittedChanges},
414
419
  "createdAt": "{existingCreatedAt || GetTimestamp()}",
415
- "lastSync": "{GetTimestamp()}"
420
+ "lastSync": "{GetTimestamp()}",
421
+ "integrations": "{existing.integrations || {}}" // ← Preserve integrations
416
422
  }
417
423
  ```
418
424