clawpilot 0.1.1 → 0.1.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/README.md +33 -0
- package/bin/cli.js +124 -10
- package/docs/PUBLISH_CHECKLIST.md +1 -0
- package/docs/plans/2026-02-12-0.1.2-plan.md +52 -0
- package/docs/plans/2026-02-13-0.1.2-design.md +115 -0
- package/package.json +1 -1
- package/templates/soul-injection.md +19 -5
package/README.md
CHANGED
|
@@ -21,6 +21,25 @@ The installer also:
|
|
|
21
21
|
npx clawpilot@latest
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
+
## Quick Start
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# Install into default ~/.openclaw
|
|
28
|
+
npx -y clawpilot@latest install
|
|
29
|
+
|
|
30
|
+
# Or install with custom schedule
|
|
31
|
+
npx -y clawpilot@latest install --morning 08:30 --midday 13:30 --evening 21:00
|
|
32
|
+
|
|
33
|
+
# Validate CLI
|
|
34
|
+
npx -y clawpilot@latest --help
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
For isolated local verification:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
node bin/cli.js install --home ./tmp-openclaw --yes --timezone UTC --force
|
|
41
|
+
```
|
|
42
|
+
|
|
24
43
|
Or run locally:
|
|
25
44
|
|
|
26
45
|
```bash
|
|
@@ -65,3 +84,17 @@ npm test
|
|
|
65
84
|
## Publish
|
|
66
85
|
|
|
67
86
|
See `docs/PUBLISH_CHECKLIST.md`.
|
|
87
|
+
|
|
88
|
+
## Troubleshooting
|
|
89
|
+
|
|
90
|
+
### npm publish E403 (2FA required)
|
|
91
|
+
|
|
92
|
+
If publish fails with:
|
|
93
|
+
|
|
94
|
+
`403 Forbidden ... Two-factor authentication or granular access token with bypass 2fa enabled is required`
|
|
95
|
+
|
|
96
|
+
Use one of these fixes:
|
|
97
|
+
|
|
98
|
+
1. Enable npm 2FA for publishing and publish with OTP:
|
|
99
|
+
- `npm publish --access public --otp=<6-digit-code>`
|
|
100
|
+
2. Use a granular access token with publish permission and bypass 2FA enabled.
|
package/bin/cli.js
CHANGED
|
@@ -2,8 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
const os = require('node:os');
|
|
4
4
|
const path = require('node:path');
|
|
5
|
+
const readline = require('node:readline');
|
|
5
6
|
const { installSkill, DEFAULT_SCHEDULE } = require('../src/install');
|
|
6
7
|
|
|
8
|
+
const SCHEDULE_PATTERN = /^([01]\d|2[0-3]):([0-5]\d)$/;
|
|
9
|
+
|
|
7
10
|
function printHelp() {
|
|
8
11
|
console.log('clawpilot - OpenClaw productivity copilot');
|
|
9
12
|
console.log('');
|
|
@@ -17,15 +20,28 @@ function printHelp() {
|
|
|
17
20
|
console.log('Options:');
|
|
18
21
|
console.log(' --home <path> Override OpenClaw home directory');
|
|
19
22
|
console.log(' --force Replace existing clawpilot skill installation');
|
|
23
|
+
console.log(' --yes Non-interactive mode (fail if required input is missing)');
|
|
24
|
+
console.log(' --timezone <IANA> Timezone override (e.g. Asia/Taipei, UTC)');
|
|
20
25
|
console.log(` --morning <HH:mm> Morning check-in time (default: ${DEFAULT_SCHEDULE.morning})`);
|
|
21
26
|
console.log(` --midday <HH:mm> Midday check-in time (default: ${DEFAULT_SCHEDULE.midday})`);
|
|
22
27
|
console.log(` --evening <HH:mm> Evening check-in time (default: ${DEFAULT_SCHEDULE.evening})`);
|
|
23
28
|
}
|
|
24
29
|
|
|
30
|
+
function readValueArg(args, index, flagName, missingValueFlags) {
|
|
31
|
+
const value = args[index + 1];
|
|
32
|
+
if (value === undefined || value.startsWith('--')) {
|
|
33
|
+
missingValueFlags.push(flagName);
|
|
34
|
+
return { value: undefined, nextIndex: index };
|
|
35
|
+
}
|
|
36
|
+
return { value, nextIndex: index + 1 };
|
|
37
|
+
}
|
|
38
|
+
|
|
25
39
|
function parseOptions(args) {
|
|
26
40
|
const options = {
|
|
27
41
|
force: false,
|
|
28
|
-
|
|
42
|
+
yes: false,
|
|
43
|
+
schedule: {},
|
|
44
|
+
missingValueFlags: []
|
|
29
45
|
};
|
|
30
46
|
|
|
31
47
|
for (let index = 0; index < args.length; index += 1) {
|
|
@@ -34,24 +50,38 @@ function parseOptions(args) {
|
|
|
34
50
|
options.force = true;
|
|
35
51
|
continue;
|
|
36
52
|
}
|
|
53
|
+
if (arg === '--yes') {
|
|
54
|
+
options.yes = true;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
37
57
|
if (arg === '--home') {
|
|
38
|
-
|
|
39
|
-
|
|
58
|
+
const { value, nextIndex } = readValueArg(args, index, '--home', options.missingValueFlags);
|
|
59
|
+
options.openClawHome = value;
|
|
60
|
+
index = nextIndex;
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (arg === '--timezone') {
|
|
64
|
+
const { value, nextIndex } = readValueArg(args, index, '--timezone', options.missingValueFlags);
|
|
65
|
+
options.timezone = value;
|
|
66
|
+
index = nextIndex;
|
|
40
67
|
continue;
|
|
41
68
|
}
|
|
42
69
|
if (arg === '--morning') {
|
|
43
|
-
|
|
44
|
-
|
|
70
|
+
const { value, nextIndex } = readValueArg(args, index, '--morning', options.missingValueFlags);
|
|
71
|
+
options.schedule.morning = value;
|
|
72
|
+
index = nextIndex;
|
|
45
73
|
continue;
|
|
46
74
|
}
|
|
47
75
|
if (arg === '--midday') {
|
|
48
|
-
|
|
49
|
-
|
|
76
|
+
const { value, nextIndex } = readValueArg(args, index, '--midday', options.missingValueFlags);
|
|
77
|
+
options.schedule.midday = value;
|
|
78
|
+
index = nextIndex;
|
|
50
79
|
continue;
|
|
51
80
|
}
|
|
52
81
|
if (arg === '--evening') {
|
|
53
|
-
|
|
54
|
-
|
|
82
|
+
const { value, nextIndex } = readValueArg(args, index, '--evening', options.missingValueFlags);
|
|
83
|
+
options.schedule.evening = value;
|
|
84
|
+
index = nextIndex;
|
|
55
85
|
continue;
|
|
56
86
|
}
|
|
57
87
|
throw new Error(`Unknown option: ${arg}`);
|
|
@@ -60,6 +90,74 @@ function parseOptions(args) {
|
|
|
60
90
|
return options;
|
|
61
91
|
}
|
|
62
92
|
|
|
93
|
+
function prompt(question) {
|
|
94
|
+
const rl = readline.createInterface({
|
|
95
|
+
input: process.stdin,
|
|
96
|
+
output: process.stdout
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
return new Promise((resolve) => {
|
|
100
|
+
rl.question(question, (answer) => {
|
|
101
|
+
rl.close();
|
|
102
|
+
resolve(answer.trim());
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function isValidTimezone(timezone) {
|
|
108
|
+
try {
|
|
109
|
+
Intl.DateTimeFormat('en-US', { timeZone: timezone }).format();
|
|
110
|
+
return true;
|
|
111
|
+
} catch {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function validateSchedule(schedule) {
|
|
117
|
+
for (const [key, value] of Object.entries(schedule)) {
|
|
118
|
+
if (!SCHEDULE_PATTERN.test(value)) {
|
|
119
|
+
throw new Error(`Invalid ${key} time "${value}". Use HH:mm (24-hour format).`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async function resolveMissingValues(options) {
|
|
125
|
+
const missing = [...new Set(options.missingValueFlags)];
|
|
126
|
+
if (missing.length === 0) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (options.yes) {
|
|
131
|
+
throw new Error(`${missing[0]} requires a value when --yes is set.`);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (!process.stdin.isTTY) {
|
|
135
|
+
throw new Error(`${missing[0]} requires a value. Re-run with ${missing[0]} <value> or use interactive terminal.`);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
for (const flag of missing) {
|
|
139
|
+
if (flag === '--home') {
|
|
140
|
+
options.openClawHome = await prompt('OpenClaw home path: ');
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
if (flag === '--timezone') {
|
|
144
|
+
options.timezone = await prompt('Timezone (e.g. UTC, Asia/Taipei): ');
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
if (flag === '--morning') {
|
|
148
|
+
options.schedule.morning = await prompt('Morning check-in time (HH:mm): ');
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
if (flag === '--midday') {
|
|
152
|
+
options.schedule.midday = await prompt('Midday check-in time (HH:mm): ');
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
if (flag === '--evening') {
|
|
156
|
+
options.schedule.evening = await prompt('Evening check-in time (HH:mm): ');
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
63
161
|
async function main() {
|
|
64
162
|
const args = process.argv.slice(2);
|
|
65
163
|
const command = args[0] || 'install';
|
|
@@ -79,19 +177,35 @@ async function main() {
|
|
|
79
177
|
|
|
80
178
|
const projectRoot = path.resolve(__dirname, '..');
|
|
81
179
|
const options = parseOptions(commandArgs);
|
|
180
|
+
await resolveMissingValues(options);
|
|
181
|
+
validateSchedule(options.schedule);
|
|
182
|
+
|
|
183
|
+
let timezone = options.timezone || Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC';
|
|
184
|
+
if (!timezone) {
|
|
185
|
+
if (options.yes) {
|
|
186
|
+
throw new Error('Timezone could not be detected. Provide --timezone <IANA name>.');
|
|
187
|
+
}
|
|
188
|
+
timezone = await prompt('Timezone (e.g. UTC, Asia/Taipei): ');
|
|
189
|
+
}
|
|
190
|
+
if (!isValidTimezone(timezone)) {
|
|
191
|
+
throw new Error(`Invalid timezone "${timezone}". Use a valid IANA timezone like UTC or Asia/Taipei.`);
|
|
192
|
+
}
|
|
193
|
+
|
|
82
194
|
const openClawHome = options.openClawHome || process.env.OPENCLAW_HOME || path.join(os.homedir(), '.openclaw');
|
|
83
195
|
|
|
84
196
|
const result = await installSkill({
|
|
85
197
|
openClawHome,
|
|
86
198
|
packageRoot: projectRoot,
|
|
87
199
|
schedule: options.schedule,
|
|
88
|
-
force: options.force
|
|
200
|
+
force: options.force,
|
|
201
|
+
timezone
|
|
89
202
|
});
|
|
90
203
|
|
|
91
204
|
console.log(`Installed skill at: ${result.skillDir}`);
|
|
92
205
|
console.log(`Updated config at: ${result.configPath}`);
|
|
93
206
|
console.log(`Updated workspace SOUL at: ${result.workspaceSoulPath}`);
|
|
94
207
|
console.log(`Updated workspace identity at: ${result.identityPath}`);
|
|
208
|
+
console.log('Next: run openclaw and start your morning Top-3 planning check-in.');
|
|
95
209
|
}
|
|
96
210
|
|
|
97
211
|
main().catch((error) => {
|
|
@@ -17,6 +17,7 @@ Use this checklist before publishing a new `clawpilot` version to npm.
|
|
|
17
17
|
- `npm pack --dry-run`
|
|
18
18
|
6. Publish:
|
|
19
19
|
- `npm publish --access public`
|
|
20
|
+
- If your account has publish 2FA enabled: `npm publish --access public --otp=<6-digit-code>`
|
|
20
21
|
7. Validate release:
|
|
21
22
|
- `npm view clawpilot version`
|
|
22
23
|
- `npx clawpilot@latest --help`
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# clawpilot 0.1.2 Plan
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Ship a practical upgrade that improves real daily usage after installation, while keeping the package lightweight and easy to run with `npx`.
|
|
6
|
+
|
|
7
|
+
## Scope
|
|
8
|
+
|
|
9
|
+
1. Better install UX
|
|
10
|
+
- Add `--yes` non-interactive mode for CI and scripted setup.
|
|
11
|
+
- Add `--timezone` option to override auto-detected timezone.
|
|
12
|
+
- Print a concise post-install summary with next commands.
|
|
13
|
+
|
|
14
|
+
2. Productivity loop quality
|
|
15
|
+
- Expand `templates/soul-injection.md` with clearer response format:
|
|
16
|
+
- Morning: 3 measurable tasks.
|
|
17
|
+
- Midday: status and one unblock action.
|
|
18
|
+
- Evening: wins, lessons, and first task for tomorrow.
|
|
19
|
+
- Add a guardrail for rescue sprint frequency (max 2 per week in wording).
|
|
20
|
+
|
|
21
|
+
3. Config reliability
|
|
22
|
+
- Preserve existing `skills.entries.clawpilot-productivity` fields when merging.
|
|
23
|
+
- Add tests for config merge with pre-existing custom fields.
|
|
24
|
+
- Add tests for repeated installs with mixed options.
|
|
25
|
+
|
|
26
|
+
4. Documentation
|
|
27
|
+
- Add a troubleshooting section for npm publish errors (2FA and token setup).
|
|
28
|
+
- Add examples for local testing with `--home`.
|
|
29
|
+
|
|
30
|
+
## Out of Scope (0.1.2)
|
|
31
|
+
|
|
32
|
+
- Telegram or Discord runtime integration.
|
|
33
|
+
- Network calls or external APIs.
|
|
34
|
+
- Background schedulers.
|
|
35
|
+
|
|
36
|
+
## Test Plan
|
|
37
|
+
|
|
38
|
+
- Unit tests:
|
|
39
|
+
- Installer config merge behavior with existing settings.
|
|
40
|
+
- Schedule and timezone options parsing.
|
|
41
|
+
- Idempotent SOUL injection on repeated installs.
|
|
42
|
+
- Smoke tests:
|
|
43
|
+
- `node bin/cli.js install --home <temp>`
|
|
44
|
+
- `node bin/cli.js install --home <temp> --force --yes`
|
|
45
|
+
|
|
46
|
+
## Release Checklist
|
|
47
|
+
|
|
48
|
+
1. `npm test`
|
|
49
|
+
2. `npm pack --dry-run`
|
|
50
|
+
3. `npm version patch`
|
|
51
|
+
4. `npm publish --access public --otp=<code>`
|
|
52
|
+
5. `git push origin main --tags`
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# clawpilot 0.1.2 Design
|
|
2
|
+
|
|
3
|
+
## Objective
|
|
4
|
+
|
|
5
|
+
Deliver a reliable and practical 0.1.2 release for `clawpilot` that improves install UX and config safety while preserving the lightweight `npx` workflow.
|
|
6
|
+
|
|
7
|
+
## Decisions Confirmed
|
|
8
|
+
|
|
9
|
+
- Execution mode: continuous delivery for full 0.1.2 scope.
|
|
10
|
+
- Installer interaction model: mixed mode.
|
|
11
|
+
- `--yes` behavior: hard fail if required data is missing.
|
|
12
|
+
- Priority order:
|
|
13
|
+
1. Config reliability
|
|
14
|
+
2. Install UX
|
|
15
|
+
3. Productivity template quality
|
|
16
|
+
4. Documentation
|
|
17
|
+
|
|
18
|
+
## Architecture
|
|
19
|
+
|
|
20
|
+
### 1. CLI Layer (`bin/cli.js`)
|
|
21
|
+
|
|
22
|
+
- Parse command arguments and normalize options.
|
|
23
|
+
- Support new flags:
|
|
24
|
+
- `--yes`
|
|
25
|
+
- `--timezone`
|
|
26
|
+
- existing schedule options (`--morning`, `--midday`, `--evening`)
|
|
27
|
+
- Enforce validation rules:
|
|
28
|
+
- Invalid schedule/timezone format -> fail with clear error.
|
|
29
|
+
- Missing required values under `--yes` -> fail with exit code 1.
|
|
30
|
+
- Produce concise post-install summary and next-step commands.
|
|
31
|
+
|
|
32
|
+
### 2. Install Orchestration (`src/install.js`)
|
|
33
|
+
|
|
34
|
+
- Keep orchestration responsibilities only:
|
|
35
|
+
- copy skill files
|
|
36
|
+
- apply config updates
|
|
37
|
+
- inject workspace files
|
|
38
|
+
- return structured install result
|
|
39
|
+
- Delegate merge and workspace mutation to dedicated modules.
|
|
40
|
+
|
|
41
|
+
### 3. Config Module (`src/config.js`)
|
|
42
|
+
|
|
43
|
+
- Deep-merge behavior must preserve user custom fields.
|
|
44
|
+
- Managed fields:
|
|
45
|
+
- `skills.entries.clawpilot-productivity.enabled`
|
|
46
|
+
- `skills.entries.clawpilot-productivity.mode`
|
|
47
|
+
- `skills.entries.clawpilot-productivity.schedule`
|
|
48
|
+
- `skills.entries.clawpilot-productivity.timezone`
|
|
49
|
+
- Ensure `skills.load.extraDirs` is deduplicated.
|
|
50
|
+
|
|
51
|
+
### 4. Workspace Module (`src/workspace.js`)
|
|
52
|
+
|
|
53
|
+
- Marker-based injection for `workspace/SOUL.md`:
|
|
54
|
+
- replace clawpilot section if present
|
|
55
|
+
- keep non-clawpilot content untouched
|
|
56
|
+
- Write `workspace/IDENTITY.md` deterministically from template.
|
|
57
|
+
- Keep repeated installs idempotent.
|
|
58
|
+
|
|
59
|
+
## Data Flow
|
|
60
|
+
|
|
61
|
+
1. User runs `clawpilot install ...options`.
|
|
62
|
+
2. CLI parses and validates options.
|
|
63
|
+
3. Installer resolves defaults (schedule/timezone) or collects missing values in mixed mode.
|
|
64
|
+
4. With `--yes`, unresolved required values immediately fail.
|
|
65
|
+
5. Installer writes skill files and updates config/workspace.
|
|
66
|
+
6. CLI prints summary including skill path, config path, and next command examples.
|
|
67
|
+
|
|
68
|
+
## Error Handling
|
|
69
|
+
|
|
70
|
+
- Invalid option values return explicit actionable messages.
|
|
71
|
+
- `--yes` mode never prompts; it exits when data is incomplete.
|
|
72
|
+
- Existing installation without `--force` fails safely.
|
|
73
|
+
- Config parse failure falls back to empty config object, then rewrites valid JSON.
|
|
74
|
+
|
|
75
|
+
## Testing Strategy
|
|
76
|
+
|
|
77
|
+
### Unit Tests
|
|
78
|
+
|
|
79
|
+
- Config merge preserves pre-existing unknown fields.
|
|
80
|
+
- `skills.load.extraDirs` remains unique after repeated installs.
|
|
81
|
+
- Timezone and schedule options are parsed and persisted correctly.
|
|
82
|
+
- Marker injection stays single-instance after repeated install/force runs.
|
|
83
|
+
|
|
84
|
+
### CLI/Behavior Tests
|
|
85
|
+
|
|
86
|
+
- `--yes` with unresolved required input exits non-zero.
|
|
87
|
+
- Happy path install succeeds with explicit options.
|
|
88
|
+
- Reinstall with mixed options keeps idempotent state.
|
|
89
|
+
|
|
90
|
+
### Smoke Tests
|
|
91
|
+
|
|
92
|
+
- `node bin/cli.js install --home <temp>`
|
|
93
|
+
- `node bin/cli.js install --home <temp> --force --yes`
|
|
94
|
+
- `npm pack --dry-run`
|
|
95
|
+
|
|
96
|
+
## Scope Boundaries
|
|
97
|
+
|
|
98
|
+
In scope:
|
|
99
|
+
- install UX upgrades
|
|
100
|
+
- config reliability hardening
|
|
101
|
+
- productivity prompt template improvements
|
|
102
|
+
- troubleshooting docs
|
|
103
|
+
|
|
104
|
+
Out of scope:
|
|
105
|
+
- Telegram/Discord runtime integration
|
|
106
|
+
- external API calls
|
|
107
|
+
- background schedulers
|
|
108
|
+
|
|
109
|
+
## Release Readiness
|
|
110
|
+
|
|
111
|
+
0.1.2 is release-ready when:
|
|
112
|
+
- `npm test` passes
|
|
113
|
+
- smoke tests pass
|
|
114
|
+
- README and troubleshooting are updated
|
|
115
|
+
- package dry-run output is correct
|
package/package.json
CHANGED
|
@@ -1,14 +1,28 @@
|
|
|
1
1
|
## Clawpilot Productivity Loop
|
|
2
2
|
|
|
3
|
-
Run this daily structure with minimal friction:
|
|
3
|
+
Run this exact daily structure with minimal friction:
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
-
|
|
5
|
+
### Morning (Plan)
|
|
6
|
+
|
|
7
|
+
- Ask for exactly 3 outcome-based tasks.
|
|
8
|
+
- Rewrite each task as measurable output (clear done criteria).
|
|
9
|
+
- Ask for the first task to start now.
|
|
10
|
+
|
|
11
|
+
### Midday (Status)
|
|
12
|
+
|
|
13
|
+
- Ask for status per task: `done`, `blocked`, or `deferred`.
|
|
14
|
+
- If blocked, suggest one concrete unblock action.
|
|
15
|
+
- If behind, propose one 25-minute rescue sprint.
|
|
16
|
+
|
|
17
|
+
### Evening (Review)
|
|
18
|
+
|
|
19
|
+
- Summarize completed tasks and unfinished items.
|
|
20
|
+
- Capture one lesson from the day.
|
|
21
|
+
- Queue tomorrow's first action in one sentence.
|
|
8
22
|
|
|
9
23
|
Coaching rules:
|
|
10
24
|
|
|
11
25
|
- Keep guidance direct and practical.
|
|
12
26
|
- Use supportive language, never guilt-driven language.
|
|
13
|
-
-
|
|
27
|
+
- Limit rescue sprints to at most two per week.
|
|
14
28
|
- Avoid long motivational monologues.
|