aiblueprint-cli 1.4.24 → 1.4.26
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/claude-code-config/skills/workflow-apex-free/SKILL.md +261 -0
- package/claude-code-config/skills/workflow-apex-free/scripts/setup-templates.sh +100 -0
- package/claude-code-config/skills/workflow-apex-free/scripts/update-progress.sh +80 -0
- package/claude-code-config/skills/workflow-apex-free/steps/step-00-init.md +267 -0
- package/claude-code-config/skills/workflow-apex-free/steps/step-00b-branch.md +126 -0
- package/claude-code-config/skills/workflow-apex-free/steps/step-00b-economy.md +244 -0
- package/claude-code-config/skills/workflow-apex-free/steps/step-00b-interactive.md +153 -0
- package/claude-code-config/skills/workflow-apex-free/steps/step-01-analyze.md +361 -0
- package/claude-code-config/skills/workflow-apex-free/steps/step-02-plan.md +264 -0
- package/claude-code-config/skills/workflow-apex-free/steps/step-03-execute.md +239 -0
- package/claude-code-config/skills/workflow-apex-free/steps/step-04-validate.md +251 -0
- package/claude-code-config/skills/workflow-apex-free/templates/00-context.md +43 -0
- package/claude-code-config/skills/workflow-apex-free/templates/01-analyze.md +10 -0
- package/claude-code-config/skills/workflow-apex-free/templates/02-plan.md +10 -0
- package/claude-code-config/skills/workflow-apex-free/templates/03-execute.md +10 -0
- package/claude-code-config/skills/workflow-apex-free/templates/04-validate.md +10 -0
- package/claude-code-config/skills/workflow-apex-free/templates/README.md +176 -0
- package/claude-code-config/skills/workflow-apex-free/templates/step-complete.md +7 -0
- package/dist/cli.js +179 -37
- package/package.json +1 -1
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# APEX Template System
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This directory contains template files used to initialize APEX workflow outputs when save mode (`-s`) is enabled. This template system significantly reduces token usage by moving repetitive content out of step files.
|
|
6
|
+
|
|
7
|
+
## Template Files
|
|
8
|
+
|
|
9
|
+
| Template | Purpose | Created When |
|
|
10
|
+
|----------|---------|--------------|
|
|
11
|
+
| `00-context.md` | Workflow configuration and progress tracking | Always (if save_mode) |
|
|
12
|
+
| `01-analyze.md` | Analysis findings | Always (if save_mode) |
|
|
13
|
+
| `02-plan.md` | Implementation plan | Always (if save_mode) |
|
|
14
|
+
| `03-execute.md` | Implementation log | Always (if save_mode) |
|
|
15
|
+
| `04-validate.md` | Validation results and workflow completion | Always (if save_mode) |
|
|
16
|
+
| `step-complete.md` | Completion marker template | Referenced in steps |
|
|
17
|
+
|
|
18
|
+
## Template Variables
|
|
19
|
+
|
|
20
|
+
Templates use `{{variable}}` syntax for placeholders:
|
|
21
|
+
|
|
22
|
+
| Variable | Description | Example |
|
|
23
|
+
|----------|-------------|---------|
|
|
24
|
+
| `{{task_id}}` | Kebab-case task identifier | `01-add-auth-middleware` |
|
|
25
|
+
| `{{task_description}}` | Plain text task description | `add authentication middleware` |
|
|
26
|
+
| `{{timestamp}}` | ISO 8601 timestamp | `2026-01-12T10:30:00Z` |
|
|
27
|
+
| `{{auto_mode}}` | Auto mode flag | `true` or `false` |
|
|
28
|
+
| `{{save_mode}}` | Save mode flag | `true` or `false` |
|
|
29
|
+
| `{{economy_mode}}` | Economy mode flag | `true` or `false` |
|
|
30
|
+
| `{{branch_mode}}` | Branch mode flag | `true` or `false` |
|
|
31
|
+
| `{{interactive_mode}}` | Interactive mode flag | `true` or `false` |
|
|
32
|
+
| `{{branch_name}}` | Git branch name | `feature/add-auth` |
|
|
33
|
+
| `{{original_input}}` | Raw user input | `/apex -a -s add auth` |
|
|
34
|
+
|
|
35
|
+
## Setup Script
|
|
36
|
+
|
|
37
|
+
### `setup-templates.sh`
|
|
38
|
+
|
|
39
|
+
Initializes all template files in the output directory with variables replaced.
|
|
40
|
+
|
|
41
|
+
**Usage:**
|
|
42
|
+
```bash
|
|
43
|
+
bash scripts/setup-templates.sh \
|
|
44
|
+
"feature_name" \
|
|
45
|
+
"task_description" \
|
|
46
|
+
"auto_mode" \
|
|
47
|
+
"save_mode" \
|
|
48
|
+
"economy_mode" \
|
|
49
|
+
"branch_mode" \
|
|
50
|
+
"interactive_mode" \
|
|
51
|
+
"branch_name" \
|
|
52
|
+
"original_input"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Output:**
|
|
56
|
+
```
|
|
57
|
+
.claude/output/apex/01-add-auth-middleware/
|
|
58
|
+
├── 00-context.md # Always created
|
|
59
|
+
├── 01-analyze.md # Always created
|
|
60
|
+
├── 02-plan.md # Always created
|
|
61
|
+
├── 03-execute.md # Always created
|
|
62
|
+
└── 04-validate.md # Always created
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Progress Update Script
|
|
66
|
+
|
|
67
|
+
### `update-progress.sh`
|
|
68
|
+
|
|
69
|
+
Updates the progress table in `00-context.md` without manual markdown editing.
|
|
70
|
+
|
|
71
|
+
**Usage:**
|
|
72
|
+
```bash
|
|
73
|
+
bash scripts/update-progress.sh <task_id> <step_number> <step_name> <status>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**Examples:**
|
|
77
|
+
```bash
|
|
78
|
+
# Mark step 01 as in progress
|
|
79
|
+
bash scripts/update-progress.sh "01-add-auth" "01" "analyze" "in_progress"
|
|
80
|
+
|
|
81
|
+
# Mark step 01 as complete
|
|
82
|
+
bash scripts/update-progress.sh "01-add-auth" "01" "analyze" "complete"
|
|
83
|
+
|
|
84
|
+
# Mark step 02 as in progress
|
|
85
|
+
bash scripts/update-progress.sh "01-add-auth" "02" "plan" "in_progress"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**Status Values:**
|
|
89
|
+
- `in_progress` → `⏳ In Progress`
|
|
90
|
+
- `complete` → `✓ Complete`
|
|
91
|
+
|
|
92
|
+
## Token Savings
|
|
93
|
+
|
|
94
|
+
### Before Optimization
|
|
95
|
+
|
|
96
|
+
Each step file contained full template content inline:
|
|
97
|
+
|
|
98
|
+
```markdown
|
|
99
|
+
### 1. Initialize Save Output (if save_mode)
|
|
100
|
+
|
|
101
|
+
**If `{save_mode}` = true:**
|
|
102
|
+
|
|
103
|
+
Create `{output_dir}/01-analyze.md`:
|
|
104
|
+
```markdown
|
|
105
|
+
# Step 01: Analyze
|
|
106
|
+
|
|
107
|
+
**Task:** {task_description}
|
|
108
|
+
**Started:** {ISO timestamp}
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Context Discovery
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Update `00-context.md` progress:
|
|
116
|
+
```markdown
|
|
117
|
+
| 01-analyze | ⏳ In Progress | {timestamp} |
|
|
118
|
+
```
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
**Token cost per step:** ~200 tokens × 5 steps = ~1,000 tokens
|
|
122
|
+
|
|
123
|
+
### After Optimization
|
|
124
|
+
|
|
125
|
+
Step files now reference templates and scripts:
|
|
126
|
+
|
|
127
|
+
```markdown
|
|
128
|
+
### 1. Initialize Save Output (if save_mode)
|
|
129
|
+
|
|
130
|
+
**If `{save_mode}` = true:**
|
|
131
|
+
|
|
132
|
+
The file `{output_dir}/01-analyze.md` has already been created by the setup script.
|
|
133
|
+
|
|
134
|
+
Update progress:
|
|
135
|
+
```bash
|
|
136
|
+
bash {skill_dir}/scripts/update-progress.sh "{task_id}" "01" "analyze" "in_progress"
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Append your findings to `01-analyze.md` as you work.
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
**Token cost per step:** ~50 tokens × 5 steps = ~250 tokens
|
|
143
|
+
|
|
144
|
+
**Total savings:** ~750 tokens per workflow execution (75% reduction)
|
|
145
|
+
|
|
146
|
+
## How It Works
|
|
147
|
+
|
|
148
|
+
1. **Initialization (step-00-init.md):**
|
|
149
|
+
- Runs `setup-templates.sh` once at workflow start
|
|
150
|
+
- Creates all template files with variables replaced
|
|
151
|
+
- Output directory is ready with pre-initialized files
|
|
152
|
+
|
|
153
|
+
2. **Each Step:**
|
|
154
|
+
- Runs `update-progress.sh` to mark step as "in_progress"
|
|
155
|
+
- Appends findings/logs to the pre-created step file
|
|
156
|
+
- Runs `update-progress.sh` again to mark step as "complete"
|
|
157
|
+
|
|
158
|
+
3. **Benefits:**
|
|
159
|
+
- AI doesn't need to hold template content in context
|
|
160
|
+
- Consistent formatting across all workflows
|
|
161
|
+
- Easy to update templates without editing step files
|
|
162
|
+
- Scripts handle the tedious markdown updates
|
|
163
|
+
|
|
164
|
+
## Updating Templates
|
|
165
|
+
|
|
166
|
+
To modify template content:
|
|
167
|
+
|
|
168
|
+
1. Edit the template file in `templates/`
|
|
169
|
+
2. Changes apply to all future workflows automatically
|
|
170
|
+
3. No need to update step files
|
|
171
|
+
|
|
172
|
+
## Maintenance
|
|
173
|
+
|
|
174
|
+
- Templates are stateless (no workflow-specific logic)
|
|
175
|
+
- Scripts are idempotent (safe to run multiple times)
|
|
176
|
+
- Variables use `{{var}}` syntax to avoid conflicts with markdown
|
package/dist/cli.js
CHANGED
|
@@ -12963,7 +12963,7 @@ var require_signal_exit = __commonJS((exports, module) => {
|
|
|
12963
12963
|
emitter.on(ev, cb);
|
|
12964
12964
|
return remove;
|
|
12965
12965
|
};
|
|
12966
|
-
unload = function
|
|
12966
|
+
unload = function unload2() {
|
|
12967
12967
|
if (!loaded || !processOk(global.process)) {
|
|
12968
12968
|
return;
|
|
12969
12969
|
}
|
|
@@ -12978,7 +12978,7 @@ var require_signal_exit = __commonJS((exports, module) => {
|
|
|
12978
12978
|
emitter.count -= 1;
|
|
12979
12979
|
};
|
|
12980
12980
|
module.exports.unload = unload;
|
|
12981
|
-
emit = function
|
|
12981
|
+
emit = function emit2(event, code, signal) {
|
|
12982
12982
|
if (emitter.emitted[event]) {
|
|
12983
12983
|
return;
|
|
12984
12984
|
}
|
|
@@ -13007,7 +13007,7 @@ var require_signal_exit = __commonJS((exports, module) => {
|
|
|
13007
13007
|
return signals;
|
|
13008
13008
|
};
|
|
13009
13009
|
loaded = false;
|
|
13010
|
-
load = function
|
|
13010
|
+
load = function load2() {
|
|
13011
13011
|
if (loaded || !processOk(global.process)) {
|
|
13012
13012
|
return;
|
|
13013
13013
|
}
|
|
@@ -13026,7 +13026,7 @@ var require_signal_exit = __commonJS((exports, module) => {
|
|
|
13026
13026
|
};
|
|
13027
13027
|
module.exports.load = load;
|
|
13028
13028
|
originalProcessReallyExit = process3.reallyExit;
|
|
13029
|
-
processReallyExit = function
|
|
13029
|
+
processReallyExit = function processReallyExit2(code) {
|
|
13030
13030
|
if (!processOk(global.process)) {
|
|
13031
13031
|
return;
|
|
13032
13032
|
}
|
|
@@ -13036,7 +13036,7 @@ var require_signal_exit = __commonJS((exports, module) => {
|
|
|
13036
13036
|
originalProcessReallyExit.call(process3, process3.exitCode);
|
|
13037
13037
|
};
|
|
13038
13038
|
originalProcessEmit = process3.emit;
|
|
13039
|
-
processEmit = function
|
|
13039
|
+
processEmit = function processEmit2(ev, arg) {
|
|
13040
13040
|
if (ev === "exit" && processOk(global.process)) {
|
|
13041
13041
|
if (arg !== undefined) {
|
|
13042
13042
|
process3.exitCode = arg;
|
|
@@ -15063,12 +15063,12 @@ var require_wcwidth = __commonJS((exports, module) => {
|
|
|
15063
15063
|
nul: 0,
|
|
15064
15064
|
control: 0
|
|
15065
15065
|
};
|
|
15066
|
-
module.exports = function
|
|
15066
|
+
module.exports = function wcwidth2(str) {
|
|
15067
15067
|
return wcswidth(str, DEFAULTS);
|
|
15068
15068
|
};
|
|
15069
15069
|
module.exports.config = function(opts) {
|
|
15070
15070
|
opts = defaults(opts || {}, DEFAULTS);
|
|
15071
|
-
return function
|
|
15071
|
+
return function wcwidth2(str) {
|
|
15072
15072
|
return wcswidth(str, opts);
|
|
15073
15073
|
};
|
|
15074
15074
|
};
|
|
@@ -15738,7 +15738,7 @@ var require__stream_writable = __commonJS((exports, module) => {
|
|
|
15738
15738
|
}
|
|
15739
15739
|
});
|
|
15740
15740
|
} else {
|
|
15741
|
-
realHasInstance = function
|
|
15741
|
+
realHasInstance = function realHasInstance2(object) {
|
|
15742
15742
|
return object instanceof this;
|
|
15743
15743
|
};
|
|
15744
15744
|
}
|
|
@@ -16536,28 +16536,28 @@ var require_end_of_stream = __commonJS((exports, module) => {
|
|
|
16536
16536
|
callback = once(callback || noop);
|
|
16537
16537
|
var readable = opts.readable || opts.readable !== false && stream.readable;
|
|
16538
16538
|
var writable = opts.writable || opts.writable !== false && stream.writable;
|
|
16539
|
-
var onlegacyfinish = function
|
|
16539
|
+
var onlegacyfinish = function onlegacyfinish2() {
|
|
16540
16540
|
if (!stream.writable)
|
|
16541
16541
|
onfinish();
|
|
16542
16542
|
};
|
|
16543
16543
|
var writableEnded = stream._writableState && stream._writableState.finished;
|
|
16544
|
-
var onfinish = function
|
|
16544
|
+
var onfinish = function onfinish2() {
|
|
16545
16545
|
writable = false;
|
|
16546
16546
|
writableEnded = true;
|
|
16547
16547
|
if (!readable)
|
|
16548
16548
|
callback.call(stream);
|
|
16549
16549
|
};
|
|
16550
16550
|
var readableEnded = stream._readableState && stream._readableState.endEmitted;
|
|
16551
|
-
var onend = function
|
|
16551
|
+
var onend = function onend2() {
|
|
16552
16552
|
readable = false;
|
|
16553
16553
|
readableEnded = true;
|
|
16554
16554
|
if (!writable)
|
|
16555
16555
|
callback.call(stream);
|
|
16556
16556
|
};
|
|
16557
|
-
var onerror = function
|
|
16557
|
+
var onerror = function onerror2(err) {
|
|
16558
16558
|
callback.call(stream, err);
|
|
16559
16559
|
};
|
|
16560
|
-
var onclose = function
|
|
16560
|
+
var onclose = function onclose2() {
|
|
16561
16561
|
var err;
|
|
16562
16562
|
if (readable && !readableEnded) {
|
|
16563
16563
|
if (!stream._readableState || !stream._readableState.ended)
|
|
@@ -16570,7 +16570,7 @@ var require_end_of_stream = __commonJS((exports, module) => {
|
|
|
16570
16570
|
return callback.call(stream, err);
|
|
16571
16571
|
}
|
|
16572
16572
|
};
|
|
16573
|
-
var onrequest = function
|
|
16573
|
+
var onrequest = function onrequest2() {
|
|
16574
16574
|
stream.req.on("finish", onfinish);
|
|
16575
16575
|
};
|
|
16576
16576
|
if (isRequest(stream)) {
|
|
@@ -16727,7 +16727,7 @@ var require_async_iterator = __commonJS((exports, module) => {
|
|
|
16727
16727
|
});
|
|
16728
16728
|
});
|
|
16729
16729
|
}), _Object$setPrototypeO), AsyncIteratorPrototype);
|
|
16730
|
-
var createReadableStreamAsyncIterator = function
|
|
16730
|
+
var createReadableStreamAsyncIterator = function createReadableStreamAsyncIterator2(stream) {
|
|
16731
16731
|
var _Object$create;
|
|
16732
16732
|
var iterator = Object.create(ReadableStreamAsyncIteratorPrototype, (_Object$create = {}, _defineProperty(_Object$create, kStream, {
|
|
16733
16733
|
value: stream,
|
|
@@ -16916,7 +16916,7 @@ var require__stream_readable = __commonJS((exports, module) => {
|
|
|
16916
16916
|
var Duplex;
|
|
16917
16917
|
Readable.ReadableState = ReadableState;
|
|
16918
16918
|
var EE = __require("events").EventEmitter;
|
|
16919
|
-
var EElistenerCount = function
|
|
16919
|
+
var EElistenerCount = function EElistenerCount2(emitter, type) {
|
|
16920
16920
|
return emitter.listeners(type).length;
|
|
16921
16921
|
};
|
|
16922
16922
|
var Stream = __require("stream");
|
|
@@ -16933,7 +16933,7 @@ var require__stream_readable = __commonJS((exports, module) => {
|
|
|
16933
16933
|
if (debugUtil && debugUtil.debuglog) {
|
|
16934
16934
|
debug = debugUtil.debuglog("stream");
|
|
16935
16935
|
} else {
|
|
16936
|
-
debug = function
|
|
16936
|
+
debug = function debug2() {};
|
|
16937
16937
|
}
|
|
16938
16938
|
var BufferList = require_buffer_list();
|
|
16939
16939
|
var destroyImpl = require_destroy();
|
|
@@ -17993,14 +17993,14 @@ var require_BufferList = __commonJS((exports, module) => {
|
|
|
17993
17993
|
if (srcEnd <= 0) {
|
|
17994
17994
|
return dst || Buffer2.alloc(0);
|
|
17995
17995
|
}
|
|
17996
|
-
const
|
|
17996
|
+
const copy2 = !!dst;
|
|
17997
17997
|
const off = this._offset(srcStart);
|
|
17998
17998
|
const len = srcEnd - srcStart;
|
|
17999
17999
|
let bytes = len;
|
|
18000
|
-
let bufoff =
|
|
18000
|
+
let bufoff = copy2 && dstStart || 0;
|
|
18001
18001
|
let start = off[1];
|
|
18002
18002
|
if (srcStart === 0 && srcEnd === this.length) {
|
|
18003
|
-
if (!
|
|
18003
|
+
if (!copy2) {
|
|
18004
18004
|
return this._bufs.length === 1 ? this._bufs[0] : Buffer2.concat(this._bufs, this.length);
|
|
18005
18005
|
}
|
|
18006
18006
|
for (let i = 0;i < this._bufs.length; i++) {
|
|
@@ -18010,9 +18010,9 @@ var require_BufferList = __commonJS((exports, module) => {
|
|
|
18010
18010
|
return dst;
|
|
18011
18011
|
}
|
|
18012
18012
|
if (bytes <= this._bufs[off[0]].length - start) {
|
|
18013
|
-
return
|
|
18013
|
+
return copy2 ? this._bufs[off[0]].copy(dst, dstStart, start, start + bytes) : this._bufs[off[0]].slice(start, start + bytes);
|
|
18014
18014
|
}
|
|
18015
|
-
if (!
|
|
18015
|
+
if (!copy2) {
|
|
18016
18016
|
dst = Buffer2.allocUnsafe(len);
|
|
18017
18017
|
}
|
|
18018
18018
|
for (let i = off[0];i < this._bufs.length; i++) {
|
|
@@ -18234,7 +18234,7 @@ var require_bl = __commonJS((exports, module) => {
|
|
|
18234
18234
|
}
|
|
18235
18235
|
if (typeof callback === "function") {
|
|
18236
18236
|
this._callback = callback;
|
|
18237
|
-
const piper = function
|
|
18237
|
+
const piper = function piper2(err) {
|
|
18238
18238
|
if (this._callback) {
|
|
18239
18239
|
this._callback(err);
|
|
18240
18240
|
this._callback = null;
|
|
@@ -28633,9 +28633,9 @@ GFS4: `);
|
|
|
28633
28633
|
function readdir(path2, options, cb) {
|
|
28634
28634
|
if (typeof options === "function")
|
|
28635
28635
|
cb = options, options = null;
|
|
28636
|
-
var go$readdir = noReaddirOptionVersions.test(process.version) ? function go$
|
|
28636
|
+
var go$readdir = noReaddirOptionVersions.test(process.version) ? function go$readdir2(path3, options2, cb2, startTime) {
|
|
28637
28637
|
return fs$readdir(path3, fs$readdirCallback(path3, options2, cb2, startTime));
|
|
28638
|
-
} : function go$
|
|
28638
|
+
} : function go$readdir2(path3, options2, cb2, startTime) {
|
|
28639
28639
|
return fs$readdir(path3, options2, fs$readdirCallback(path3, options2, cb2, startTime));
|
|
28640
28640
|
};
|
|
28641
28641
|
return go$readdir(path2, options, cb);
|
|
@@ -29482,7 +29482,7 @@ var require_empty2 = __commonJS((exports, module) => {
|
|
|
29482
29482
|
var path2 = __require("path");
|
|
29483
29483
|
var mkdir = require_mkdirs();
|
|
29484
29484
|
var remove = require_remove();
|
|
29485
|
-
var emptyDir = u(async function
|
|
29485
|
+
var emptyDir = u(async function emptyDir2(dir) {
|
|
29486
29486
|
let items;
|
|
29487
29487
|
try {
|
|
29488
29488
|
items = await fs.readdir(dir);
|
|
@@ -33301,6 +33301,44 @@ function formatDate(date) {
|
|
|
33301
33301
|
const pad = (n) => n.toString().padStart(2, "0");
|
|
33302
33302
|
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}-${pad(date.getHours())}-${pad(date.getMinutes())}-${pad(date.getSeconds())}`;
|
|
33303
33303
|
}
|
|
33304
|
+
async function listBackups() {
|
|
33305
|
+
const exists = await import_fs_extra5.default.pathExists(BACKUP_BASE_DIR);
|
|
33306
|
+
if (!exists) {
|
|
33307
|
+
return [];
|
|
33308
|
+
}
|
|
33309
|
+
const entries = await import_fs_extra5.default.readdir(BACKUP_BASE_DIR, { withFileTypes: true });
|
|
33310
|
+
const backups = [];
|
|
33311
|
+
for (const entry of entries) {
|
|
33312
|
+
if (!entry.isDirectory())
|
|
33313
|
+
continue;
|
|
33314
|
+
const match = entry.name.match(/^(\d{4})-(\d{2})-(\d{2})-(\d{2})-(\d{2})-(\d{2})$/);
|
|
33315
|
+
if (!match)
|
|
33316
|
+
continue;
|
|
33317
|
+
const [, year, month, day, hour, minute, second] = match;
|
|
33318
|
+
const date = new Date(parseInt(year), parseInt(month) - 1, parseInt(day), parseInt(hour), parseInt(minute), parseInt(second));
|
|
33319
|
+
backups.push({
|
|
33320
|
+
name: entry.name,
|
|
33321
|
+
path: path7.join(BACKUP_BASE_DIR, entry.name),
|
|
33322
|
+
date
|
|
33323
|
+
});
|
|
33324
|
+
}
|
|
33325
|
+
return backups.sort((a, b) => b.date.getTime() - a.date.getTime());
|
|
33326
|
+
}
|
|
33327
|
+
async function loadBackup(backupPath, claudeDir) {
|
|
33328
|
+
const exists = await import_fs_extra5.default.pathExists(backupPath);
|
|
33329
|
+
if (!exists) {
|
|
33330
|
+
throw new Error(`Backup not found: ${backupPath}`);
|
|
33331
|
+
}
|
|
33332
|
+
await import_fs_extra5.default.ensureDir(claudeDir);
|
|
33333
|
+
const itemsToCopy = ["commands", "agents", "skills", "scripts", "song", "settings.json"];
|
|
33334
|
+
for (const item of itemsToCopy) {
|
|
33335
|
+
const sourcePath = path7.join(backupPath, item);
|
|
33336
|
+
const destPath = path7.join(claudeDir, item);
|
|
33337
|
+
if (await import_fs_extra5.default.pathExists(sourcePath)) {
|
|
33338
|
+
await import_fs_extra5.default.copy(sourcePath, destPath, { overwrite: true });
|
|
33339
|
+
}
|
|
33340
|
+
}
|
|
33341
|
+
}
|
|
33304
33342
|
async function createBackup(claudeDir) {
|
|
33305
33343
|
const exists = await import_fs_extra5.default.pathExists(claudeDir);
|
|
33306
33344
|
if (!exists) {
|
|
@@ -33459,8 +33497,13 @@ async function setupCommand(params = {}) {
|
|
|
33459
33497
|
}
|
|
33460
33498
|
if (options.aiblueprintCommands) {
|
|
33461
33499
|
s.start("Setting up AIBlueprint commands");
|
|
33462
|
-
|
|
33463
|
-
|
|
33500
|
+
const commandsSourcePath = path8.join(sourceDir, "commands");
|
|
33501
|
+
if (await import_fs_extra6.default.pathExists(commandsSourcePath)) {
|
|
33502
|
+
await import_fs_extra6.default.copy(commandsSourcePath, path8.join(claudeDir, "commands"), { overwrite: true });
|
|
33503
|
+
s.stop("Commands installed");
|
|
33504
|
+
} else {
|
|
33505
|
+
s.stop("Commands not available in repository");
|
|
33506
|
+
}
|
|
33464
33507
|
}
|
|
33465
33508
|
if (options.codexSymlink && options.aiblueprintCommands) {
|
|
33466
33509
|
s.start("Setting up Codex symlink");
|
|
@@ -35732,6 +35775,22 @@ async function proSyncCommand(options = {}) {
|
|
|
35732
35775
|
if (syncMode === "updates") {
|
|
35733
35776
|
selectedItems = [...newItems, ...modifiedItems];
|
|
35734
35777
|
} else if (syncMode === "updates_and_delete") {
|
|
35778
|
+
M2.message("");
|
|
35779
|
+
M2.message(source_default.red.bold("⚠️ WARNING: DESTRUCTIVE ACTION"));
|
|
35780
|
+
M2.message(source_default.red("━".repeat(50)));
|
|
35781
|
+
M2.message(source_default.red("All your custom skills, commands, agents, and configuration files"));
|
|
35782
|
+
M2.message(source_default.red("that are not in the premium version will be PERMANENTLY DELETED"));
|
|
35783
|
+
M2.message(source_default.red("and replaced by the new version."));
|
|
35784
|
+
M2.message(source_default.red("━".repeat(50)));
|
|
35785
|
+
M2.message("");
|
|
35786
|
+
const deleteConfirm = await ye({
|
|
35787
|
+
message: source_default.red.bold("Are you sure you want to delete and replace all files?"),
|
|
35788
|
+
initialValue: false
|
|
35789
|
+
});
|
|
35790
|
+
if (pD(deleteConfirm) || !deleteConfirm) {
|
|
35791
|
+
xe("Sync cancelled");
|
|
35792
|
+
process.exit(0);
|
|
35793
|
+
}
|
|
35735
35794
|
selectedItems = [...newItems, ...modifiedItems, ...deletedItems];
|
|
35736
35795
|
} else {
|
|
35737
35796
|
const fileChoices = choices.filter((c) => c.value.type !== "hook");
|
|
@@ -35879,13 +35938,90 @@ async function proSyncCommand(options = {}) {
|
|
|
35879
35938
|
}
|
|
35880
35939
|
}
|
|
35881
35940
|
|
|
35941
|
+
// src/commands/backup.ts
|
|
35942
|
+
import os15 from "os";
|
|
35943
|
+
import path15 from "path";
|
|
35944
|
+
function formatBackupDate(date) {
|
|
35945
|
+
const now = new Date;
|
|
35946
|
+
const diffMs = now.getTime() - date.getTime();
|
|
35947
|
+
const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
|
|
35948
|
+
const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
|
|
35949
|
+
const diffMinutes = Math.floor(diffMs / (1000 * 60));
|
|
35950
|
+
let relative;
|
|
35951
|
+
if (diffMinutes < 60) {
|
|
35952
|
+
relative = `${diffMinutes} minute${diffMinutes !== 1 ? "s" : ""} ago`;
|
|
35953
|
+
} else if (diffHours < 24) {
|
|
35954
|
+
relative = `${diffHours} hour${diffHours !== 1 ? "s" : ""} ago`;
|
|
35955
|
+
} else if (diffDays < 7) {
|
|
35956
|
+
relative = `${diffDays} day${diffDays !== 1 ? "s" : ""} ago`;
|
|
35957
|
+
} else {
|
|
35958
|
+
relative = date.toLocaleDateString();
|
|
35959
|
+
}
|
|
35960
|
+
return `${date.toLocaleString()} (${relative})`;
|
|
35961
|
+
}
|
|
35962
|
+
async function backupLoadCommand(options = {}) {
|
|
35963
|
+
const claudeDir = options.folder || path15.join(os15.homedir(), ".claude");
|
|
35964
|
+
Ie(source_default.blue("\uD83D\uDCE6 Load Backup"));
|
|
35965
|
+
const spinner = Y2();
|
|
35966
|
+
spinner.start("Scanning for backups...");
|
|
35967
|
+
const backups = await listBackups();
|
|
35968
|
+
spinner.stop(`Found ${backups.length} backup${backups.length !== 1 ? "s" : ""}`);
|
|
35969
|
+
if (backups.length === 0) {
|
|
35970
|
+
M2.warn("No backups found in ~/.config/aiblueprint/backup/");
|
|
35971
|
+
M2.info("Backups are created automatically when you run setup or sync commands.");
|
|
35972
|
+
Se(source_default.gray("Nothing to restore"));
|
|
35973
|
+
return;
|
|
35974
|
+
}
|
|
35975
|
+
const backupOptions = backups.map((backup) => ({
|
|
35976
|
+
value: backup,
|
|
35977
|
+
label: backup.name,
|
|
35978
|
+
hint: formatBackupDate(backup.date)
|
|
35979
|
+
}));
|
|
35980
|
+
const selected = await ve({
|
|
35981
|
+
message: "Select a backup to restore:",
|
|
35982
|
+
options: backupOptions
|
|
35983
|
+
});
|
|
35984
|
+
if (pD(selected)) {
|
|
35985
|
+
xe("Operation cancelled");
|
|
35986
|
+
process.exit(0);
|
|
35987
|
+
}
|
|
35988
|
+
M2.info(`Selected: ${source_default.cyan(selected.name)}`);
|
|
35989
|
+
M2.info(`Date: ${source_default.gray(formatBackupDate(selected.date))}`);
|
|
35990
|
+
const confirm = await ye({
|
|
35991
|
+
message: `This will overwrite your current configuration in ${source_default.cyan(claudeDir)}. Continue?`,
|
|
35992
|
+
initialValue: false
|
|
35993
|
+
});
|
|
35994
|
+
if (pD(confirm) || !confirm) {
|
|
35995
|
+
xe("Operation cancelled");
|
|
35996
|
+
process.exit(0);
|
|
35997
|
+
}
|
|
35998
|
+
spinner.start("Creating backup of current configuration...");
|
|
35999
|
+
const currentBackup = await createBackup(claudeDir);
|
|
36000
|
+
if (currentBackup) {
|
|
36001
|
+
spinner.stop(`Current config backed up to: ${source_default.gray(currentBackup)}`);
|
|
36002
|
+
} else {
|
|
36003
|
+
spinner.stop("No current config to backup");
|
|
36004
|
+
}
|
|
36005
|
+
spinner.start("Restoring backup...");
|
|
36006
|
+
try {
|
|
36007
|
+
await loadBackup(selected.path, claudeDir);
|
|
36008
|
+
spinner.stop("Backup restored successfully");
|
|
36009
|
+
M2.success(`Restored configuration from ${source_default.cyan(selected.name)}`);
|
|
36010
|
+
Se(source_default.green("✅ Backup loaded successfully"));
|
|
36011
|
+
} catch (error) {
|
|
36012
|
+
spinner.stop("Restore failed");
|
|
36013
|
+
M2.error(`Failed to restore backup: ${error}`);
|
|
36014
|
+
process.exit(1);
|
|
36015
|
+
}
|
|
36016
|
+
}
|
|
36017
|
+
|
|
35882
36018
|
// src/commands/dynamic-scripts.ts
|
|
35883
|
-
import
|
|
36019
|
+
import path18 from "path";
|
|
35884
36020
|
import { homedir } from "os";
|
|
35885
36021
|
|
|
35886
36022
|
// src/lib/script-parser.ts
|
|
35887
36023
|
var import_fs_extra12 = __toESM(require_lib4(), 1);
|
|
35888
|
-
import
|
|
36024
|
+
import path16 from "path";
|
|
35889
36025
|
var EXCLUDED_SCRIPTS = ["test", "lint", "format", "start"];
|
|
35890
36026
|
var EXCLUDED_SUFFIXES = [":test", ":lint", ":test-fixtures", ":start"];
|
|
35891
36027
|
function shouldIncludeScript(scriptName) {
|
|
@@ -35896,7 +36032,7 @@ function shouldIncludeScript(scriptName) {
|
|
|
35896
36032
|
return true;
|
|
35897
36033
|
}
|
|
35898
36034
|
async function readScriptsPackageJson(claudeDir) {
|
|
35899
|
-
const packageJsonPath =
|
|
36035
|
+
const packageJsonPath = path16.join(claudeDir, "scripts", "package.json");
|
|
35900
36036
|
try {
|
|
35901
36037
|
if (!await import_fs_extra12.default.pathExists(packageJsonPath)) {
|
|
35902
36038
|
return null;
|
|
@@ -35948,11 +36084,11 @@ function groupScriptsByPrefix(commands) {
|
|
|
35948
36084
|
var import_fs_extra13 = __toESM(require_lib4(), 1);
|
|
35949
36085
|
import { spawn as spawn2 } from "child_process";
|
|
35950
36086
|
import { execSync as execSync4 } from "child_process";
|
|
35951
|
-
import
|
|
35952
|
-
import
|
|
36087
|
+
import path17 from "path";
|
|
36088
|
+
import os16 from "os";
|
|
35953
36089
|
function checkCommand(cmd) {
|
|
35954
36090
|
try {
|
|
35955
|
-
const isWindows =
|
|
36091
|
+
const isWindows = os16.platform() === "win32";
|
|
35956
36092
|
const whichCmd = isWindows ? `where ${cmd}` : `which ${cmd}`;
|
|
35957
36093
|
execSync4(whichCmd, { stdio: "ignore" });
|
|
35958
36094
|
return true;
|
|
@@ -35978,13 +36114,13 @@ async function executeScript(scriptName, claudeDir) {
|
|
|
35978
36114
|
console.error(source_default.red("Bun is not installed. Install with: npm install -g bun"));
|
|
35979
36115
|
return 1;
|
|
35980
36116
|
}
|
|
35981
|
-
const scriptsDir =
|
|
36117
|
+
const scriptsDir = path17.join(claudeDir, "scripts");
|
|
35982
36118
|
if (!await import_fs_extra13.default.pathExists(scriptsDir)) {
|
|
35983
36119
|
console.error(source_default.red(`Scripts directory not found at ${scriptsDir}`));
|
|
35984
36120
|
console.log(source_default.gray("Run: aiblueprint claude-code setup"));
|
|
35985
36121
|
return 1;
|
|
35986
36122
|
}
|
|
35987
|
-
const packageJsonPath =
|
|
36123
|
+
const packageJsonPath = path17.join(scriptsDir, "package.json");
|
|
35988
36124
|
if (!await import_fs_extra13.default.pathExists(packageJsonPath)) {
|
|
35989
36125
|
console.error(source_default.red(`package.json not found in ${scriptsDir}`));
|
|
35990
36126
|
return 1;
|
|
@@ -36012,7 +36148,7 @@ async function executeScript(scriptName, claudeDir) {
|
|
|
36012
36148
|
|
|
36013
36149
|
// src/commands/dynamic-scripts.ts
|
|
36014
36150
|
function getClaudeDir(parentOptions) {
|
|
36015
|
-
return parentOptions.claudeCodeFolder || parentOptions.folder ?
|
|
36151
|
+
return parentOptions.claudeCodeFolder || parentOptions.folder ? path18.resolve(parentOptions.claudeCodeFolder || parentOptions.folder) : path18.join(homedir(), ".claude");
|
|
36016
36152
|
}
|
|
36017
36153
|
async function registerDynamicScriptCommands(claudeCodeCmd, claudeDir) {
|
|
36018
36154
|
const scripts = await readScriptsPackageJson(claudeDir);
|
|
@@ -36095,6 +36231,12 @@ proCmd.command("sync").description("Sync premium configurations with selective u
|
|
|
36095
36231
|
const claudeCodeFolder = parentOptions.claudeCodeFolder || parentOptions.folder;
|
|
36096
36232
|
proSyncCommand({ folder: claudeCodeFolder });
|
|
36097
36233
|
});
|
|
36234
|
+
var backupCmd = claudeCodeCmd.command("backup").description("Manage Claude Code configuration backups");
|
|
36235
|
+
backupCmd.command("load").description("Load a previous backup interactively").action((options, command) => {
|
|
36236
|
+
const parentOptions = command.parent.parent.opts();
|
|
36237
|
+
const claudeCodeFolder = parentOptions.claudeCodeFolder || parentOptions.folder;
|
|
36238
|
+
backupLoadCommand({ folder: claudeCodeFolder });
|
|
36239
|
+
});
|
|
36098
36240
|
try {
|
|
36099
36241
|
const claudeDir = join2(homedir2(), ".claude");
|
|
36100
36242
|
await registerDynamicScriptCommands(claudeCodeCmd, claudeDir);
|