prjct-cli 0.29.9 → 0.30.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.
- package/CHANGELOG.md +27 -0
- package/dist/bin/prjct.mjs +1 -1
- package/package.json +1 -1
- package/scripts/postinstall.js +81 -164
- package/templates/commands/p.md +7 -14
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.30.0] - 2026-01-12
|
|
4
|
+
|
|
5
|
+
### Fix: Distribution System Overhaul (CRITICAL)
|
|
6
|
+
|
|
7
|
+
**Problem:** Users running `npm update -g prjct-cli` weren't getting updates because:
|
|
8
|
+
1. Old p.md had fallback to local cache files
|
|
9
|
+
2. postinstall copied 40+ files, too many failure points
|
|
10
|
+
|
|
11
|
+
**Solution:**
|
|
12
|
+
- **Removed fallback** in p.md - No more reading from stale local files
|
|
13
|
+
- **p.md now always reads from npm root** - `npm root -g` + template path
|
|
14
|
+
- **Simplified postinstall** - Only copies p.md (critical) + statusline (best-effort)
|
|
15
|
+
|
|
16
|
+
**How it works now:**
|
|
17
|
+
```
|
|
18
|
+
p. sync → Claude reads ~/.claude/commands/p.md
|
|
19
|
+
→ p.md says "run npm root -g, read from there"
|
|
20
|
+
→ Claude reads /opt/homebrew/lib/node_modules/prjct-cli/templates/commands/sync.md
|
|
21
|
+
→ Template always comes from installed npm package
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**Files:**
|
|
25
|
+
- `templates/commands/p.md` - Removed fallback, simplified
|
|
26
|
+
- `scripts/postinstall.js` - Minimal, only copies essential files
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
3
30
|
## [0.28.0] - 2026-01-12
|
|
4
31
|
|
|
5
32
|
### Feature: Per-Project Task Filtering for Status Bar
|
package/dist/bin/prjct.mjs
CHANGED
|
@@ -12541,7 +12541,7 @@ var require_package = __commonJS({
|
|
|
12541
12541
|
"package.json"(exports, module) {
|
|
12542
12542
|
module.exports = {
|
|
12543
12543
|
name: "prjct-cli",
|
|
12544
|
-
version: "0.29.
|
|
12544
|
+
version: "0.29.10",
|
|
12545
12545
|
description: "Built for Claude - Ship fast, track progress, stay focused. Developer momentum tool for indie hackers.",
|
|
12546
12546
|
main: "core/index.ts",
|
|
12547
12547
|
bin: {
|
package/package.json
CHANGED
package/scripts/postinstall.js
CHANGED
|
@@ -1,190 +1,107 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* postinstall - Minimal, reliable setup
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* 3. Installs statusline
|
|
10
|
-
* 4. Updates project versions
|
|
11
|
-
*
|
|
12
|
-
* IMPORTANT: This script uses COMPILED JavaScript from dist/
|
|
13
|
-
* It does NOT require TypeScript directly.
|
|
14
|
-
*
|
|
15
|
-
* @version 2.0.0
|
|
6
|
+
* CRITICAL: Only copies p.md router to ~/.claude/commands/
|
|
7
|
+
* p.md reads templates from npm root, so updates work automatically.
|
|
8
|
+
* Statusline is best-effort (optional).
|
|
16
9
|
*/
|
|
17
10
|
|
|
18
|
-
const path = require('path')
|
|
19
|
-
const { execSync } = require('child_process')
|
|
20
11
|
const fs = require('fs')
|
|
12
|
+
const path = require('path')
|
|
13
|
+
const os = require('os')
|
|
21
14
|
|
|
22
15
|
const ROOT = path.resolve(__dirname, '..')
|
|
16
|
+
const HOME = os.homedir()
|
|
17
|
+
const CLAUDE_DIR = path.join(HOME, '.claude')
|
|
18
|
+
const COMMANDS_DIR = path.join(CLAUDE_DIR, 'commands')
|
|
23
19
|
|
|
24
|
-
|
|
25
|
-
* Detect if this is a global npm install
|
|
26
|
-
*/
|
|
27
|
-
function isGlobalInstall() {
|
|
28
|
-
// Check npm config (most reliable)
|
|
29
|
-
if (process.env.npm_config_global === 'true') {
|
|
30
|
-
return true
|
|
31
|
-
}
|
|
20
|
+
console.log('\n prjct-cli postinstall\n')
|
|
32
21
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
// macOS Intel
|
|
37
|
-
'/usr/local/lib/node_modules',
|
|
38
|
-
// macOS M1/M2 (Homebrew)
|
|
39
|
-
'/opt/homebrew/lib/node_modules',
|
|
40
|
-
// Linux
|
|
41
|
-
'/usr/lib/node_modules',
|
|
42
|
-
// Custom npm prefix
|
|
43
|
-
path.join(process.env.HOME || '', '.npm-global', 'lib', 'node_modules'),
|
|
44
|
-
// nvm
|
|
45
|
-
path.join(process.env.HOME || '', '.nvm'),
|
|
46
|
-
// Windows
|
|
47
|
-
path.join(process.env.APPDATA || '', 'npm', 'node_modules'),
|
|
48
|
-
// pnpm global
|
|
49
|
-
path.join(process.env.HOME || '', '.local', 'share', 'pnpm'),
|
|
50
|
-
// Volta
|
|
51
|
-
path.join(process.env.HOME || '', '.volta'),
|
|
52
|
-
]
|
|
53
|
-
|
|
54
|
-
if (globalPaths.some((p) => installPath.includes(p))) {
|
|
55
|
-
return true
|
|
56
|
-
}
|
|
22
|
+
// 1. Copy p.md router (CRITICAL - this is the only essential file)
|
|
23
|
+
try {
|
|
24
|
+
fs.mkdirSync(COMMANDS_DIR, { recursive: true })
|
|
57
25
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
return true
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return false
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Check if bun is available
|
|
68
|
-
*/
|
|
69
|
-
function hasBun() {
|
|
70
|
-
try {
|
|
71
|
-
execSync('bun --version', { stdio: 'ignore' })
|
|
72
|
-
return true
|
|
73
|
-
} catch {
|
|
74
|
-
return false
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Run setup using compiled JavaScript (for Node.js users)
|
|
80
|
-
*/
|
|
81
|
-
async function runSetupCompiled() {
|
|
82
|
-
const setupPath = path.join(ROOT, 'dist', 'core', 'infrastructure', 'setup.js')
|
|
83
|
-
|
|
84
|
-
if (!fs.existsSync(setupPath)) {
|
|
85
|
-
console.log(' Setup module not found. Skipping setup.')
|
|
86
|
-
console.log(' Run `prjct setup` manually after install.')
|
|
87
|
-
return false
|
|
88
|
-
}
|
|
26
|
+
const pmdSrc = path.join(ROOT, 'templates', 'commands', 'p.md')
|
|
27
|
+
const pmdDest = path.join(COMMANDS_DIR, 'p.md')
|
|
89
28
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
console.warn(' Setup warning:', error.message)
|
|
96
|
-
console.log(' Run `prjct setup` manually after install.')
|
|
97
|
-
return false
|
|
29
|
+
if (fs.existsSync(pmdSrc)) {
|
|
30
|
+
fs.copyFileSync(pmdSrc, pmdDest)
|
|
31
|
+
console.log(' \u2713 p.md router installed')
|
|
32
|
+
} else {
|
|
33
|
+
console.log(' ! p.md not found in package')
|
|
98
34
|
}
|
|
35
|
+
} catch (error) {
|
|
36
|
+
console.log(' ! Could not install p.md:', error.message)
|
|
37
|
+
console.log(' Run: npx prjct-cli setup')
|
|
99
38
|
}
|
|
100
39
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
40
|
+
// 2. Statusline (best-effort, not critical)
|
|
41
|
+
try {
|
|
42
|
+
const STATUSLINE_SRC = path.join(ROOT, 'assets', 'statusline')
|
|
43
|
+
const STATUSLINE_DEST = path.join(HOME, '.prjct-cli', 'statusline')
|
|
44
|
+
|
|
45
|
+
if (fs.existsSync(STATUSLINE_SRC)) {
|
|
46
|
+
// Create dirs
|
|
47
|
+
fs.mkdirSync(path.join(STATUSLINE_DEST, 'lib'), { recursive: true })
|
|
48
|
+
fs.mkdirSync(path.join(STATUSLINE_DEST, 'components'), { recursive: true })
|
|
49
|
+
fs.mkdirSync(path.join(STATUSLINE_DEST, 'themes'), { recursive: true })
|
|
50
|
+
|
|
51
|
+
// Copy main script
|
|
52
|
+
const mainScript = path.join(STATUSLINE_SRC, 'statusline.sh')
|
|
53
|
+
if (fs.existsSync(mainScript)) {
|
|
54
|
+
fs.copyFileSync(mainScript, path.join(STATUSLINE_DEST, 'statusline.sh'))
|
|
55
|
+
fs.chmodSync(path.join(STATUSLINE_DEST, 'statusline.sh'), 0o755)
|
|
56
|
+
}
|
|
115
57
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
const statusLinePaths = [
|
|
126
|
-
path.join(homeDir, '.prjct-cli', 'statusline', 'statusline.sh'),
|
|
127
|
-
path.join(homeDir, '.claude', 'prjct-statusline.sh'),
|
|
128
|
-
]
|
|
129
|
-
|
|
130
|
-
for (const statusLinePath of statusLinePaths) {
|
|
131
|
-
if (fs.existsSync(statusLinePath)) {
|
|
132
|
-
const stats = fs.lstatSync(statusLinePath)
|
|
133
|
-
const actualPath = stats.isSymbolicLink()
|
|
134
|
-
? fs.readlinkSync(statusLinePath)
|
|
135
|
-
: statusLinePath
|
|
136
|
-
|
|
137
|
-
if (fs.existsSync(actualPath)) {
|
|
138
|
-
let content = fs.readFileSync(actualPath, 'utf8')
|
|
139
|
-
if (content.includes('CLI_VERSION=')) {
|
|
140
|
-
const updated = content.replace(/CLI_VERSION="[^"]*"/, `CLI_VERSION="${version}"`)
|
|
141
|
-
fs.writeFileSync(actualPath, updated, { mode: 0o755 })
|
|
142
|
-
return true
|
|
143
|
-
}
|
|
58
|
+
// Copy subdirs
|
|
59
|
+
for (const subdir of ['lib', 'components', 'themes']) {
|
|
60
|
+
const srcDir = path.join(STATUSLINE_SRC, subdir)
|
|
61
|
+
if (fs.existsSync(srcDir)) {
|
|
62
|
+
for (const f of fs.readdirSync(srcDir)) {
|
|
63
|
+
fs.copyFileSync(
|
|
64
|
+
path.join(srcDir, f),
|
|
65
|
+
path.join(STATUSLINE_DEST, subdir, f)
|
|
66
|
+
)
|
|
144
67
|
}
|
|
145
68
|
}
|
|
146
69
|
}
|
|
147
|
-
return false
|
|
148
|
-
} catch {
|
|
149
|
-
return false
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
70
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
// Best case: setup actually works for all users
|
|
160
|
-
|
|
161
|
-
console.log('')
|
|
162
|
-
console.log(' prjct-cli postinstall')
|
|
163
|
-
console.log('')
|
|
164
|
-
|
|
165
|
-
// Update statusline version first (fast, always works)
|
|
166
|
-
if (updateStatusLineVersion()) {
|
|
167
|
-
console.log(' ✓ Statusline version updated')
|
|
168
|
-
}
|
|
71
|
+
// Default config (only if not exists)
|
|
72
|
+
const configSrc = path.join(STATUSLINE_SRC, 'default-config.json')
|
|
73
|
+
const configDest = path.join(STATUSLINE_DEST, 'config.json')
|
|
74
|
+
if (fs.existsSync(configSrc) && !fs.existsSync(configDest)) {
|
|
75
|
+
fs.copyFileSync(configSrc, configDest)
|
|
76
|
+
}
|
|
169
77
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
78
|
+
// Symlink in ~/.claude
|
|
79
|
+
const symlinkPath = path.join(CLAUDE_DIR, 'prjct-statusline.sh')
|
|
80
|
+
const targetPath = path.join(STATUSLINE_DEST, 'statusline.sh')
|
|
81
|
+
try {
|
|
82
|
+
if (fs.existsSync(symlinkPath)) fs.unlinkSync(symlinkPath)
|
|
83
|
+
if (fs.existsSync(targetPath)) fs.symlinkSync(targetPath, symlinkPath)
|
|
84
|
+
} catch {
|
|
85
|
+
// Symlink failed, copy instead
|
|
86
|
+
if (fs.existsSync(targetPath)) {
|
|
87
|
+
fs.copyFileSync(targetPath, symlinkPath)
|
|
88
|
+
fs.chmodSync(symlinkPath, 0o755)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
177
91
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
92
|
+
// Update settings.json
|
|
93
|
+
const settingsPath = path.join(CLAUDE_DIR, 'settings.json')
|
|
94
|
+
let settings = {}
|
|
95
|
+
if (fs.existsSync(settingsPath)) {
|
|
96
|
+
try { settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8')) } catch {}
|
|
97
|
+
}
|
|
98
|
+
settings.statusLine = { type: 'command', command: symlinkPath }
|
|
99
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2))
|
|
181
100
|
|
|
182
|
-
|
|
101
|
+
console.log(' \u2713 statusline installed')
|
|
102
|
+
}
|
|
103
|
+
} catch {
|
|
104
|
+
// Statusline is optional, don't fail
|
|
183
105
|
}
|
|
184
106
|
|
|
185
|
-
|
|
186
|
-
// Log error but don't fail npm install
|
|
187
|
-
console.error(' postinstall error:', error.message)
|
|
188
|
-
console.log(' Run manually: npx prjct-cli setup')
|
|
189
|
-
process.exit(0)
|
|
190
|
-
})
|
|
107
|
+
console.log('\n')
|
package/templates/commands/p.md
CHANGED
|
@@ -5,41 +5,34 @@ allowed-tools: [Read, Write, Edit, Bash, Glob, Grep, Task, AskUserQuestion, Todo
|
|
|
5
5
|
|
|
6
6
|
# prjct Command Router
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
**ARGUMENTS**: $ARGUMENTS
|
|
9
9
|
|
|
10
10
|
## Instructions
|
|
11
11
|
|
|
12
|
-
**ARGUMENTS**: $ARGUMENTS
|
|
13
|
-
|
|
14
12
|
1. Parse ARGUMENTS: first word = `command`, rest = `commandArgs`
|
|
15
|
-
2.
|
|
13
|
+
2. Get npm global root:
|
|
16
14
|
```bash
|
|
17
15
|
npm root -g
|
|
18
16
|
```
|
|
19
|
-
|
|
20
|
-
3. Read template from the npm package location:
|
|
17
|
+
3. Read template from npm package:
|
|
21
18
|
```
|
|
22
19
|
{npmRoot}/prjct-cli/templates/commands/{command}.md
|
|
23
20
|
```
|
|
24
|
-
4. Execute
|
|
21
|
+
4. Execute template with `commandArgs` as input
|
|
25
22
|
|
|
26
23
|
## Example
|
|
27
24
|
|
|
28
|
-
|
|
25
|
+
ARGUMENTS = "task fix the login bug"
|
|
29
26
|
- command = "task"
|
|
30
27
|
- commandArgs = "fix the login bug"
|
|
31
|
-
-
|
|
28
|
+
- npm root -g → `/opt/homebrew/lib/node_modules`
|
|
32
29
|
- Read: `/opt/homebrew/lib/node_modules/prjct-cli/templates/commands/task.md`
|
|
33
30
|
- Execute with: "fix the login bug"
|
|
34
31
|
|
|
35
|
-
## Fallback
|
|
36
|
-
|
|
37
|
-
If npm root fails, read from local cache: `~/.claude/commands/p/{command}.md`
|
|
38
|
-
|
|
39
32
|
## Available Commands
|
|
40
33
|
|
|
41
34
|
`task` `done` `ship` `sync` `init` `idea` `dash` `next` `pause` `resume` `bug` `linear` `feature` `prd` `plan` `review` `merge` `git` `test` `cleanup` `design` `analyze` `history` `enrich` `update`
|
|
42
35
|
|
|
43
36
|
## Action
|
|
44
37
|
|
|
45
|
-
NOW
|
|
38
|
+
NOW run `npm root -g` and read the command template.
|