prjct-cli 0.8.4 → 0.8.8
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 +115 -0
- package/CLAUDE.md +34 -0
- package/bin/prjct +19 -166
- package/core/agentic/context-builder.js +4 -3
- package/core/agentic/tool-registry.js +35 -0
- package/core/commands.js +84 -0
- package/core/index.js +178 -0
- package/core/infrastructure/command-installer.js +9 -26
- package/core/infrastructure/legacy-installer-detector.js +546 -0
- package/core/infrastructure/session-manager.js +14 -2
- package/core/infrastructure/setup.js +185 -0
- package/core/utils/jsonl-helper.js +137 -0
- package/package.json +1 -1
- package/scripts/install.sh +45 -8
- package/scripts/postinstall.js +12 -203
- package/templates/agents/AGENTS.md +3 -3
- package/templates/commands/ask.md +25 -338
- package/templates/commands/build.md +7 -4
- package/templates/commands/feature.md +19 -160
- package/templates/commands/help.md +41 -299
- package/templates/commands/idea.md +7 -4
- package/templates/commands/init.md +15 -112
- package/templates/commands/migrate-all.md +25 -84
- package/templates/commands/now.md +4 -3
- package/templates/commands/ship.md +20 -86
- package/templates/commands/suggest.md +36 -495
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,121 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.8.8] - 2025-10-06
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **System timestamp tools** - LLM now gets real date/time from system instead of guessing
|
|
15
|
+
- ✅ `GetTimestamp()` tool - Returns ISO timestamp from system clock
|
|
16
|
+
- ✅ `GetDate()` tool - Returns YYYY-MM-DD from system clock
|
|
17
|
+
- ✅ `GetDateTime()` tool - Returns full date/time object with components
|
|
18
|
+
- 🐛 **Bug fixed**: Tasks no longer show January 1st dates when it's October
|
|
19
|
+
- 📊 Impact: Session files now use correct dates, analytics work properly
|
|
20
|
+
|
|
21
|
+
- **Template optimization** - Phase 1 complete: Top 7 critical templates optimized
|
|
22
|
+
- ✅ Reduced from 2006 → 605 lines (69.8% reduction, saved 1401 lines)
|
|
23
|
+
- ✅ All templates now in English only (removed Spanish examples)
|
|
24
|
+
- ✅ Preserved 100% of business logic and decision-making patterns
|
|
25
|
+
- ✅ Removed verbose examples, success criteria, redundant explanations
|
|
26
|
+
- 📊 Impact: Faster LLM processing, lower token usage, clearer instructions
|
|
27
|
+
|
|
28
|
+
- **Legacy installation cleanup** - Automatic detection and removal of curl-based installations
|
|
29
|
+
- ✅ Detects legacy `~/.prjct-cli/` from curl install.sh (pre-v0.8.2)
|
|
30
|
+
- ✅ Migrates project data to npm global location automatically
|
|
31
|
+
- ✅ Removes legacy installation files (bin/, core/, templates/, etc.)
|
|
32
|
+
- ✅ Preserves user data (projects/ directory migrated safely)
|
|
33
|
+
- ✅ Cleans up shell PATH entries (bash/zsh/PowerShell)
|
|
34
|
+
- ✅ Removes legacy symlinks on Unix systems
|
|
35
|
+
- 🎯 **Impact**: Users on old curl installations automatically migrate to npm
|
|
36
|
+
- 🔧 **Windows compatible**: Handles PowerShell profiles, skips Unix-only operations
|
|
37
|
+
|
|
38
|
+
### Changed
|
|
39
|
+
|
|
40
|
+
- **Critical timestamp rule in CLAUDE.md** - Added prominent warning about LLM timestamp limitations
|
|
41
|
+
- LLM knowledge cutoff is January 2025, cannot generate accurate timestamps
|
|
42
|
+
- All templates now include `timestamp-rule` in frontmatter
|
|
43
|
+
- Templates updated: feature.md, ship.md, now.md, build.md, idea.md
|
|
44
|
+
- Hardcoded example dates replaced with GetTimestamp()/GetDate() tool calls
|
|
45
|
+
|
|
46
|
+
- **Templates optimized** (Phase 1 - Top 7)
|
|
47
|
+
- suggest.md: 555 → 96 lines (82.7% reduction)
|
|
48
|
+
- ask.md: 386 → 73 lines (81.1% reduction)
|
|
49
|
+
- help.md: 348 → 90 lines (74.1% reduction)
|
|
50
|
+
- feature.md: 239 → 93 lines (61.1% reduction)
|
|
51
|
+
- init.md: 210 → 113 lines (46.2% reduction)
|
|
52
|
+
- ship.md: 148 → 79 lines (46.6% reduction)
|
|
53
|
+
- migrate-all.md: 120 → 61 lines (49.2% reduction)
|
|
54
|
+
|
|
55
|
+
- **context-builder.js** - Enhanced timestamp documentation
|
|
56
|
+
- Clarified that timestamps come from system clock, not LLM
|
|
57
|
+
- Added inline comments explaining ISO format and YYYY-MM-DD format
|
|
58
|
+
|
|
59
|
+
- **install.sh deprecation** - Enhanced messaging with legacy detection
|
|
60
|
+
- Now detects if user has legacy curl installation
|
|
61
|
+
- Shows version and location of legacy install
|
|
62
|
+
- Provides clear migration instructions
|
|
63
|
+
- Explains automatic cleanup process
|
|
64
|
+
|
|
65
|
+
- **All Spanish removed from codebase** - 100% English documentation
|
|
66
|
+
- Updated all JSDoc comments to English
|
|
67
|
+
- Removed Spanish examples from templates
|
|
68
|
+
- Fixed: setup.js, postinstall.js, AGENTS.md
|
|
69
|
+
|
|
70
|
+
### Fixed
|
|
71
|
+
|
|
72
|
+
- **Session date accuracy** - All session files now use correct system date
|
|
73
|
+
- Previously: LLM generated timestamps (often January 1st)
|
|
74
|
+
- Now: System clock provides accurate timestamps via GetTimestamp() tool
|
|
75
|
+
- Duration calculations now accurate
|
|
76
|
+
- Progress tracking and analytics now reliable
|
|
77
|
+
|
|
78
|
+
- **Windows compatibility** - Full cross-platform support
|
|
79
|
+
- Legacy installer detector works on Windows
|
|
80
|
+
- Platform detection via `process.platform === 'win32'`
|
|
81
|
+
- PowerShell profile cleanup (instead of bash/zsh)
|
|
82
|
+
- Skips symlink cleanup on Windows (Unix-only feature)
|
|
83
|
+
- Cross-platform path handling with `os.homedir()` and `path.join()`
|
|
84
|
+
- Command installer already works on Windows (no changes needed)
|
|
85
|
+
|
|
86
|
+
## [0.8.6] - 2025-10-05
|
|
87
|
+
|
|
88
|
+
### Fixed
|
|
89
|
+
|
|
90
|
+
- **Critical: Command update system** - Fixed command synchronization to ALWAYS update to latest version
|
|
91
|
+
- ✅ Removed mtime comparison (was causing commands to stay outdated)
|
|
92
|
+
- ✅ ALWAYS overwrites existing commands with latest templates
|
|
93
|
+
- ✅ Guarantees all clients get updated commands on `npm update`
|
|
94
|
+
- ✅ Preserves legacy commands (removed: always 0)
|
|
95
|
+
- 🐛 **Bug fixed**: `now.md`, `done.md` and other commands now update correctly across all client installations
|
|
96
|
+
|
|
97
|
+
- **Setup architecture redesigned** - Dual-defense strategy for reliable setup
|
|
98
|
+
- ✅ First-use setup check in `bin/prjct` (guaranteed execution)
|
|
99
|
+
- ✅ Optional postinstall optimization (when scripts enabled)
|
|
100
|
+
- ✅ Works in CI/CD environments with `--ignore-scripts`
|
|
101
|
+
- ✅ Version tracking via `editors-config.js`
|
|
102
|
+
- ✅ Zero manual steps required
|
|
103
|
+
|
|
104
|
+
### Changed
|
|
105
|
+
|
|
106
|
+
- **Command sync behavior** (`syncCommands()`)
|
|
107
|
+
- Previous: Compared mtime, only updated if source newer → ❌ Unreliable
|
|
108
|
+
- Now: ALWAYS overwrites existing commands → ✅ Always latest version
|
|
109
|
+
- Preserves legacy/custom commands not in templates
|
|
110
|
+
- Result: `{ added: X, updated: Y, removed: 0 }`
|
|
111
|
+
|
|
112
|
+
- **Setup flow**
|
|
113
|
+
- Centralized all logic in `core/infrastructure/setup.js`
|
|
114
|
+
- `bin/prjct` checks version on every execution
|
|
115
|
+
- `scripts/postinstall.js` simplified to optional helper
|
|
116
|
+
- Auto-setup triggers on version mismatch or first use
|
|
117
|
+
|
|
118
|
+
### Technical
|
|
119
|
+
|
|
120
|
+
- Reduced `scripts/postinstall.js` from 250 → 69 lines
|
|
121
|
+
- Created `core/infrastructure/setup.js` (167 lines) - single source of truth
|
|
122
|
+
- Modified `bin/prjct` to include version check (34 lines)
|
|
123
|
+
- Removed `.setup-complete` marker (using JSON version tracking instead)
|
|
124
|
+
|
|
10
125
|
## [0.8.2] - 2025-10-05
|
|
11
126
|
|
|
12
127
|
### Changed
|
package/CLAUDE.md
CHANGED
|
@@ -6,6 +6,40 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|
|
6
6
|
|
|
7
7
|
**prjct-cli** is a developer momentum tool for solo builders, indie hackers, and small teams (2-5 people). Just ship. No BS. Track progress through slash commands without meetings, ceremonies, or traditional PM overhead.
|
|
8
8
|
|
|
9
|
+
## ⚠️ CRITICAL: Timestamp Management
|
|
10
|
+
|
|
11
|
+
**LLM DOES NOT KNOW CURRENT DATE/TIME** - Your knowledge cutoff is January 2025, and you cannot generate accurate timestamps.
|
|
12
|
+
|
|
13
|
+
### Timestamp Tools (MUST USE)
|
|
14
|
+
|
|
15
|
+
**ALWAYS use these tools for ALL timestamps and dates:**
|
|
16
|
+
|
|
17
|
+
- `GetTimestamp()` → Returns current system time in ISO format (e.g., "2025-10-07T14:30:00.000Z")
|
|
18
|
+
- `GetDate()` → Returns current date in YYYY-MM-DD format (e.g., "2025-10-07")
|
|
19
|
+
- `GetDateTime()` → Returns object with timestamp, date, year, month, day
|
|
20
|
+
|
|
21
|
+
### Rules
|
|
22
|
+
|
|
23
|
+
1. **NEVER generate timestamps manually** - All dates like "2025-10-04" or "2025-01-01" are WRONG
|
|
24
|
+
2. **ALWAYS call GetTimestamp()** when writing to session files (*.jsonl)
|
|
25
|
+
3. **ALWAYS call GetDate()** when adding entries to index files (shipped.md, roadmap.md, ideas.md)
|
|
26
|
+
4. **Templates have `timestamp-rule`** in frontmatter - READ AND FOLLOW IT
|
|
27
|
+
5. **Session files are organized by date** - Use system date to determine correct file path
|
|
28
|
+
|
|
29
|
+
### Example (CORRECT)
|
|
30
|
+
|
|
31
|
+
```jsonl
|
|
32
|
+
{"ts":"{GetTimestamp()}","type":"feature_add","name":"auth","tasks":5}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Example (WRONG - DO NOT DO THIS)
|
|
36
|
+
|
|
37
|
+
```jsonl
|
|
38
|
+
{"ts":"2025-10-04T14:30:00Z","type":"feature_add","name":"auth","tasks":5}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**Why this matters**: Without system timestamps, all session data shows January 1st dates, making analytics and progress tracking completely broken.
|
|
42
|
+
|
|
9
43
|
## 🚀 Real-World Workflow (Simplified)
|
|
10
44
|
|
|
11
45
|
prjct follows your **actual** development workflow with 5 essential commands:
|
package/bin/prjct
CHANGED
|
@@ -1,181 +1,34 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* prjct CLI
|
|
4
|
+
* prjct CLI entry point
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* Zero hardcoded logic - all commands resolved dynamically.
|
|
6
|
+
* Auto-setup on first use (like Astro, Vite, etc.)
|
|
8
7
|
*/
|
|
9
8
|
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
async function main() {
|
|
14
|
-
const [commandName, ...rawArgs] = process.argv.slice(2)
|
|
15
|
-
|
|
16
|
-
// === SPECIAL COMMANDS (version, help) ===
|
|
17
|
-
|
|
18
|
-
if (['-v', '--version', 'version'].includes(commandName)) {
|
|
19
|
-
const packageJson = require('../package.json')
|
|
20
|
-
console.log(`prjct-cli v${packageJson.version}`)
|
|
21
|
-
process.exit(0)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
if (['-h', '--help', 'help', undefined].includes(commandName)) {
|
|
25
|
-
displayHelp()
|
|
26
|
-
process.exit(0)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// === DYNAMIC COMMAND EXECUTION ===
|
|
9
|
+
const { VERSION } = require('../core/utils/version')
|
|
10
|
+
const editorsConfig = require('../core/infrastructure/editors-config')
|
|
30
11
|
|
|
12
|
+
// Ensure setup has run for this version
|
|
13
|
+
;(async function ensureSetup() {
|
|
31
14
|
try {
|
|
32
|
-
|
|
33
|
-
const cmd = registry.getByName(commandName)
|
|
34
|
-
|
|
35
|
-
if (!cmd) {
|
|
36
|
-
console.error(`Unknown command: ${commandName}`)
|
|
37
|
-
console.error(`\nUse 'prjct --help' to see available commands.`)
|
|
38
|
-
process.exit(1)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// 2. Check if deprecated (before checking implemented)
|
|
42
|
-
if (cmd.deprecated) {
|
|
43
|
-
console.error(`Command '${commandName}' is deprecated.`)
|
|
44
|
-
if (cmd.replacedBy) {
|
|
45
|
-
console.error(`Use 'prjct ${cmd.replacedBy}' instead.`)
|
|
46
|
-
}
|
|
47
|
-
process.exit(1)
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// 3. Check if implemented
|
|
51
|
-
if (!cmd.implemented) {
|
|
52
|
-
console.error(`Command '${commandName}' exists but is not yet implemented.`)
|
|
53
|
-
console.error(`Check the roadmap or contribute: https://github.com/jlopezlira/prjct-cli`)
|
|
54
|
-
console.error(`\nUse 'prjct --help' to see available commands.`)
|
|
55
|
-
process.exit(1)
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// 4. Parse arguments based on command definition
|
|
59
|
-
const { parsedArgs, options } = parseCommandArgs(cmd, rawArgs)
|
|
60
|
-
|
|
61
|
-
// 5. Instantiate commands handler
|
|
62
|
-
const commands = new PrjctCommands()
|
|
15
|
+
const lastVersion = await editorsConfig.getLastVersion()
|
|
63
16
|
|
|
64
|
-
|
|
65
|
-
|
|
17
|
+
if (!lastVersion || lastVersion !== VERSION) {
|
|
18
|
+
console.log('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')
|
|
19
|
+
console.log('🔧 One-time setup (v' + VERSION + ')...')
|
|
20
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n')
|
|
66
21
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const target = parsedArgs.join(' ')
|
|
70
|
-
result = await commands.design(target, options)
|
|
71
|
-
} else if (commandName === 'analyze') {
|
|
72
|
-
result = await commands.analyze(options)
|
|
73
|
-
} else if (commandName === 'cleanup') {
|
|
74
|
-
result = await commands.cleanup(options)
|
|
75
|
-
} else if (commandName === 'setup') {
|
|
76
|
-
result = await commands.setup(options)
|
|
77
|
-
} else if (commandName === 'migrate-all') {
|
|
78
|
-
result = await commands.migrateAll(options)
|
|
79
|
-
} else if (commandName === 'progress') {
|
|
80
|
-
const period = parsedArgs[0] || 'week'
|
|
81
|
-
result = await commands.progress(period)
|
|
82
|
-
} else if (commandName === 'build') {
|
|
83
|
-
const taskOrNumber = parsedArgs.join(' ')
|
|
84
|
-
result = await commands.build(taskOrNumber)
|
|
85
|
-
} else {
|
|
86
|
-
// Standard commands (most common case)
|
|
87
|
-
const param = parsedArgs.join(' ') || null
|
|
88
|
-
result = await commands[commandName](param)
|
|
89
|
-
}
|
|
22
|
+
const setup = require('../core/infrastructure/setup')
|
|
23
|
+
await setup.run()
|
|
90
24
|
|
|
91
|
-
|
|
92
|
-
if (result && result.message) {
|
|
93
|
-
console.log(result.message)
|
|
25
|
+
console.log('✓ Setup complete!\n')
|
|
94
26
|
}
|
|
95
|
-
|
|
96
|
-
process.exit(result && result.success ? 0 : 1)
|
|
97
27
|
} catch (error) {
|
|
98
|
-
console.error('
|
|
99
|
-
|
|
100
|
-
console.error(error.stack)
|
|
101
|
-
}
|
|
102
|
-
process.exit(1)
|
|
28
|
+
console.error('\n⚠️ Setup warning:', error.message)
|
|
29
|
+
console.error('You can run setup manually: prjct setup\n')
|
|
103
30
|
}
|
|
104
|
-
}
|
|
105
31
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
function parseCommandArgs(cmd, rawArgs) {
|
|
110
|
-
const parsedArgs = []
|
|
111
|
-
const options = {}
|
|
112
|
-
|
|
113
|
-
for (let i = 0; i < rawArgs.length; i++) {
|
|
114
|
-
const arg = rawArgs[i]
|
|
115
|
-
|
|
116
|
-
if (arg.startsWith('--')) {
|
|
117
|
-
// Handle flags
|
|
118
|
-
const flagName = arg.slice(2)
|
|
119
|
-
|
|
120
|
-
// Check if next arg is a value (doesn't start with --)
|
|
121
|
-
if (i + 1 < rawArgs.length && !rawArgs[i + 1].startsWith('--')) {
|
|
122
|
-
options[flagName] = rawArgs[++i]
|
|
123
|
-
} else {
|
|
124
|
-
options[flagName] = true
|
|
125
|
-
}
|
|
126
|
-
} else {
|
|
127
|
-
parsedArgs.push(arg)
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
return { parsedArgs, options }
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Display help using registry
|
|
136
|
-
*/
|
|
137
|
-
function displayHelp() {
|
|
138
|
-
const categories = registry.getCategories()
|
|
139
|
-
const categorizedCommands = {}
|
|
140
|
-
|
|
141
|
-
// Group commands by category (exclude deprecated)
|
|
142
|
-
registry.getTerminalCommands().forEach((cmd) => {
|
|
143
|
-
if (cmd.deprecated) return
|
|
144
|
-
|
|
145
|
-
if (!categorizedCommands[cmd.category]) {
|
|
146
|
-
categorizedCommands[cmd.category] = []
|
|
147
|
-
}
|
|
148
|
-
categorizedCommands[cmd.category].push(cmd)
|
|
149
|
-
})
|
|
150
|
-
|
|
151
|
-
console.log('prjct - Developer momentum tool for solo builders')
|
|
152
|
-
console.log('\nAvailable commands:\n')
|
|
153
|
-
|
|
154
|
-
// Display commands by category
|
|
155
|
-
Object.entries(categorizedCommands).forEach(([categoryKey, cmds]) => {
|
|
156
|
-
const categoryInfo = categories[categoryKey]
|
|
157
|
-
console.log(` ${categoryInfo.title}:`)
|
|
158
|
-
|
|
159
|
-
cmds.forEach((cmd) => {
|
|
160
|
-
const params = cmd.params ? ` ${cmd.params}` : ''
|
|
161
|
-
const spacing = ' '.repeat(Math.max(20 - cmd.name.length - params.length, 1))
|
|
162
|
-
const impl = cmd.implemented ? '' : ' (not implemented)'
|
|
163
|
-
console.log(` ${cmd.name}${params}${spacing}${cmd.description}${impl}`)
|
|
164
|
-
})
|
|
165
|
-
|
|
166
|
-
console.log('')
|
|
167
|
-
})
|
|
168
|
-
|
|
169
|
-
const stats = registry.getStats()
|
|
170
|
-
console.log(`Total: ${stats.implemented} implemented / ${stats.total} commands`)
|
|
171
|
-
console.log('\nFor more info: https://prjct.app')
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// Run CLI
|
|
175
|
-
main().catch((error) => {
|
|
176
|
-
console.error('Fatal error:', error.message)
|
|
177
|
-
if (process.env.DEBUG) {
|
|
178
|
-
console.error(error.stack)
|
|
179
|
-
}
|
|
180
|
-
process.exit(1)
|
|
181
|
-
})
|
|
32
|
+
// Continue to main CLI logic
|
|
33
|
+
require('../core/index')
|
|
34
|
+
})()
|
|
@@ -41,9 +41,10 @@ class ContextBuilder {
|
|
|
41
41
|
// Command parameters
|
|
42
42
|
params: commandParams,
|
|
43
43
|
|
|
44
|
-
//
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
// System timestamps (ALWAYS use these, NEVER generate timestamps)
|
|
45
|
+
// LLM does not know current date/time - these are from system clock
|
|
46
|
+
timestamp: new Date().toISOString(), // ISO format: "2025-10-07T14:30:00.000Z"
|
|
47
|
+
date: new Date().toISOString().split('T')[0], // YYYY-MM-DD: "2025-10-07"
|
|
47
48
|
}
|
|
48
49
|
}
|
|
49
50
|
|
|
@@ -9,6 +9,7 @@ const path = require('path')
|
|
|
9
9
|
const { promisify } = require('util')
|
|
10
10
|
const { exec: execCallback } = require('child_process')
|
|
11
11
|
const exec = promisify(execCallback)
|
|
12
|
+
const dateHelper = require('../utils/date-helper')
|
|
12
13
|
|
|
13
14
|
class ToolRegistry {
|
|
14
15
|
constructor() {
|
|
@@ -17,6 +18,9 @@ class ToolRegistry {
|
|
|
17
18
|
Write: this.write.bind(this),
|
|
18
19
|
Bash: this.bash.bind(this),
|
|
19
20
|
Exec: this.bash.bind(this), // Alias
|
|
21
|
+
GetTimestamp: this.getTimestamp.bind(this),
|
|
22
|
+
GetDate: this.getDate.bind(this),
|
|
23
|
+
GetDateTime: this.getDateTime.bind(this),
|
|
20
24
|
}
|
|
21
25
|
}
|
|
22
26
|
|
|
@@ -112,6 +116,37 @@ class ToolRegistry {
|
|
|
112
116
|
return []
|
|
113
117
|
}
|
|
114
118
|
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Get current system timestamp (ISO format)
|
|
122
|
+
* LLM MUST use this instead of generating timestamps
|
|
123
|
+
* @returns {Promise<string>} ISO timestamp (e.g., "2025-10-07T14:30:00.000Z")
|
|
124
|
+
*/
|
|
125
|
+
async getTimestamp() {
|
|
126
|
+
return dateHelper.getTimestamp()
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Get current system date (YYYY-MM-DD)
|
|
131
|
+
* LLM MUST use this instead of generating dates
|
|
132
|
+
* @returns {Promise<string>} Date string (e.g., "2025-10-07")
|
|
133
|
+
*/
|
|
134
|
+
async getDate() {
|
|
135
|
+
return dateHelper.getTodayKey()
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Get current system date/time components
|
|
140
|
+
* @returns {Promise<Object>} Date components {timestamp, date, year, month, day}
|
|
141
|
+
*/
|
|
142
|
+
async getDateTime() {
|
|
143
|
+
const now = new Date()
|
|
144
|
+
return {
|
|
145
|
+
timestamp: dateHelper.getTimestamp(),
|
|
146
|
+
date: dateHelper.getTodayKey(),
|
|
147
|
+
...dateHelper.getYearMonthDay(now),
|
|
148
|
+
}
|
|
149
|
+
}
|
|
115
150
|
}
|
|
116
151
|
|
|
117
152
|
module.exports = new ToolRegistry()
|
package/core/commands.js
CHANGED
|
@@ -1126,6 +1126,81 @@ class PrjctCommands {
|
|
|
1126
1126
|
* /p:design - Design system architecture, APIs, and components
|
|
1127
1127
|
* AGENTIC EXECUTION
|
|
1128
1128
|
*/
|
|
1129
|
+
/**
|
|
1130
|
+
* Memory cleanup helper
|
|
1131
|
+
* Rotates large JSONL files, archives old sessions, reports disk usage
|
|
1132
|
+
* @private
|
|
1133
|
+
*/
|
|
1134
|
+
async _cleanupMemory(projectPath) {
|
|
1135
|
+
const projectId = await configManager.getProjectId(projectPath)
|
|
1136
|
+
const globalPath = pathManager.getGlobalProjectPath(projectId)
|
|
1137
|
+
|
|
1138
|
+
console.log('📊 Analyzing disk usage...\n')
|
|
1139
|
+
|
|
1140
|
+
const results = {
|
|
1141
|
+
rotated: [],
|
|
1142
|
+
archived: [],
|
|
1143
|
+
totalSize: 0,
|
|
1144
|
+
freedSpace: 0,
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
// 1. Check and rotate large JSONL files
|
|
1148
|
+
const jsonlFiles = [
|
|
1149
|
+
pathManager.getFilePath(projectId, 'memory', 'context.jsonl'),
|
|
1150
|
+
pathManager.getFilePath(projectId, 'progress', 'shipped.md'),
|
|
1151
|
+
pathManager.getFilePath(projectId, 'planning', 'ideas.md'),
|
|
1152
|
+
]
|
|
1153
|
+
|
|
1154
|
+
for (const filePath of jsonlFiles) {
|
|
1155
|
+
try {
|
|
1156
|
+
const sizeMB = await jsonlHelper.getFileSizeMB(filePath)
|
|
1157
|
+
if (sizeMB > 0) {
|
|
1158
|
+
results.totalSize += sizeMB
|
|
1159
|
+
|
|
1160
|
+
const rotated = await jsonlHelper.rotateJsonLinesIfNeeded(filePath, 10)
|
|
1161
|
+
if (rotated) {
|
|
1162
|
+
results.rotated.push(path.basename(filePath))
|
|
1163
|
+
results.freedSpace += sizeMB
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
} catch (error) {
|
|
1167
|
+
// File doesn't exist, skip
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
// 2. Report disk usage
|
|
1172
|
+
console.log('💾 Disk Usage Report:\n')
|
|
1173
|
+
console.log(` Total size: ${results.totalSize.toFixed(2)}MB`)
|
|
1174
|
+
console.log(` Rotated files: ${results.rotated.length}`)
|
|
1175
|
+
|
|
1176
|
+
if (results.rotated.length > 0) {
|
|
1177
|
+
console.log(` Freed space: ${results.freedSpace.toFixed(2)}MB\n`)
|
|
1178
|
+
results.rotated.forEach((file) => console.log(` ✓ ${file}`))
|
|
1179
|
+
} else {
|
|
1180
|
+
console.log(' ✓ No rotation needed - all files under 10MB\n')
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
// 3. Suggestions
|
|
1184
|
+
console.log('\n💡 Recommendations:\n')
|
|
1185
|
+
console.log(' 1. Claude Code: Compact conversation regularly')
|
|
1186
|
+
console.log(' 2. Exclude from Spotlight: System Settings → Privacy')
|
|
1187
|
+
console.log(' 3. Clear npm cache: npm cache clean --force\n')
|
|
1188
|
+
|
|
1189
|
+
return { success: true, results }
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
/**
|
|
1193
|
+
* Internal cleanup helper for memory during normal cleanup
|
|
1194
|
+
* @private
|
|
1195
|
+
*/
|
|
1196
|
+
async _cleanupMemoryInternal(projectPath) {
|
|
1197
|
+
const projectId = await configManager.getProjectId(projectPath)
|
|
1198
|
+
|
|
1199
|
+
// Silently rotate large files
|
|
1200
|
+
const memoryPath = pathManager.getFilePath(projectId, 'memory', 'context.jsonl')
|
|
1201
|
+
await jsonlHelper.rotateJsonLinesIfNeeded(memoryPath, 10)
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1129
1204
|
async design(target = null, options = {}, projectPath = process.cwd()) {
|
|
1130
1205
|
try {
|
|
1131
1206
|
const initResult = await this.ensureProjectInit(projectPath)
|
|
@@ -1575,6 +1650,13 @@ Process flow for ${target}.
|
|
|
1575
1650
|
const initResult = await this.ensureProjectInit(projectPath)
|
|
1576
1651
|
if (!initResult.success) return initResult
|
|
1577
1652
|
|
|
1653
|
+
const isMemoryMode = _options.memory === true || _options.type === 'memory'
|
|
1654
|
+
|
|
1655
|
+
if (isMemoryMode) {
|
|
1656
|
+
console.log('🧹 Memory cleanup...\n')
|
|
1657
|
+
return await this._cleanupMemory(projectPath)
|
|
1658
|
+
}
|
|
1659
|
+
|
|
1578
1660
|
console.log('🧹 Cleaning up project...\n')
|
|
1579
1661
|
|
|
1580
1662
|
const context = await contextBuilder.build(projectPath)
|
|
@@ -1649,6 +1731,8 @@ Process flow for ${target}.
|
|
|
1649
1731
|
console.log('✅ Cleanup complete!\n')
|
|
1650
1732
|
cleaned.forEach((item) => console.log(` • ${item}`))
|
|
1651
1733
|
|
|
1734
|
+
await this._cleanupMemoryInternal(projectPath)
|
|
1735
|
+
|
|
1652
1736
|
await this.logToMemory(projectPath, 'cleanup_performed', {
|
|
1653
1737
|
items: cleaned.length,
|
|
1654
1738
|
timestamp: dateHelper.getTimestamp(),
|