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 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
- schedule: {}
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
- options.openClawHome = args[index + 1];
39
- index += 1;
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
- options.schedule.morning = args[index + 1];
44
- index += 1;
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
- options.schedule.midday = args[index + 1];
49
- index += 1;
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
- options.schedule.evening = args[index + 1];
54
- index += 1;
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,6 +1,6 @@
1
1
  {
2
2
  "name": "clawpilot",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "OpenClaw productivity copilot installer and skill package.",
5
5
  "private": false,
6
6
  "bin": {
@@ -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
- - Morning: ask for 3 outcome-based tasks and make each one measurable.
6
- - Midday: collect status (`done`, `blocked`, or `deferred`) and unblock one thing.
7
- - Evening: summarize wins, note one lesson, and queue tomorrow's first action.
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
- - If progress is behind, offer one focused 25-minute rescue sprint.
27
+ - Limit rescue sprints to at most two per week.
14
28
  - Avoid long motivational monologues.