portable-agent-layer 0.7.0 → 0.8.1

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
@@ -77,6 +77,7 @@ pal cli status # check your setup
77
77
  | `pal cli init` | Scaffold PAL home directory and install hooks |
78
78
  | `pal cli install` | Register hooks/skills for targets |
79
79
  | `pal cli uninstall` | Remove hooks/skills for targets |
80
+ | `pal cli update` | Update PAL (git pull or npm update) and reinstall hooks |
80
81
  | `pal cli export` | Export user state (telos, memory) to a zip |
81
82
  | `pal cli import` | Import user state from a zip |
82
83
  | `pal cli status` | Show current PAL configuration |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "portable-agent-layer",
3
- "version": "0.7.0",
3
+ "version": "0.8.1",
4
4
  "description": "PAL — Portable Agent Layer: persistent personal context for AI coding assistants",
5
5
  "type": "module",
6
6
  "bin": {
package/src/cli/index.ts CHANGED
@@ -10,6 +10,7 @@
10
10
  * init Scaffold PAL home, install hooks for all targets
11
11
  * install [--claude] [--opencode] Register hooks/skills for targets
12
12
  * uninstall [--claude] [--opencode] Remove hooks/skills for targets
13
+ * update Update PAL (git pull or npm update)
13
14
  * export [path] [--dry-run] Export user state to zip
14
15
  * import [path] [--dry-run] Import user state from zip
15
16
  * status Show current PAL configuration
@@ -157,6 +158,9 @@ async function runCli(command: string | undefined, args: string[]) {
157
158
  case "import":
158
159
  await importState(args);
159
160
  break;
161
+ case "update":
162
+ await update();
163
+ break;
160
164
  case "status":
161
165
  await status();
162
166
  break;
@@ -196,6 +200,7 @@ function showHelp() {
196
200
  pal cli init [--claude] [--opencode] Scaffold and install (default: all)
197
201
  pal cli install [--claude] [--opencode] Register hooks for targets
198
202
  pal cli uninstall [--claude] [--opencode] Remove hooks for targets
203
+ pal cli update Update PAL (git pull or npm update)
199
204
  pal cli export [path] [--dry-run] Export state to zip
200
205
  pal cli import [path] [--dry-run] Import state from zip
201
206
  pal cli status Show PAL configuration
@@ -574,6 +579,45 @@ async function importState(args: string[]) {
574
579
  }
575
580
  }
576
581
 
582
+ async function update() {
583
+ const { checkForUpdate } = await import("../hooks/handlers/update-check");
584
+ const result = await checkForUpdate(true);
585
+
586
+ log.info(`Current: ${result.current} (${result.mode} mode)`);
587
+
588
+ if (!result.available) {
589
+ log.success("Already up to date.");
590
+ return;
591
+ }
592
+
593
+ log.info(`Available: ${result.latest}`);
594
+
595
+ const pkg = palPkg();
596
+ if (result.mode === "repo") {
597
+ log.info("Pulling updates...");
598
+ const pull = spawnSync("git", ["pull", "--ff-only"], { cwd: pkg, stdio: "inherit" });
599
+ if (pull.status !== 0) {
600
+ log.error("git pull failed. You may have local changes — try pulling manually.");
601
+ process.exit(1);
602
+ }
603
+ } else {
604
+ log.info("Updating via npm...");
605
+ const up = spawnSync("bun", ["update", "-g", "portable-agent-layer"], {
606
+ stdio: "inherit",
607
+ });
608
+ if (up.status !== 0) {
609
+ log.error("Update failed. Try: bun update -g portable-agent-layer");
610
+ process.exit(1);
611
+ }
612
+ }
613
+
614
+ const newPkg = JSON.parse(readFileSync(resolve(pkg, "package.json"), "utf-8"));
615
+ log.success(`Updated: ${result.current} → ${newPkg.version}`);
616
+
617
+ log.info("Reinstalling...");
618
+ await install(resolveTargets([]));
619
+ }
620
+
577
621
  async function status() {
578
622
  const home = palHome();
579
623
  const pkg = palPkg();
@@ -152,12 +152,14 @@ async function checkNpm(): Promise<UpdateCache> {
152
152
  }
153
153
  }
154
154
 
155
- /** Run update check on Stop (non-blocking). Caches result for greeting. */
156
- export async function checkForUpdate(): Promise<void> {
157
- const cached = readCache();
158
- if (cached) {
159
- logDebug("update-check", "Using cached result");
160
- return;
155
+ /** Run update check. Caches result. Use force=true to skip cache (e.g. for `pal cli update`). */
156
+ export async function checkForUpdate(force = false): Promise<UpdateCache> {
157
+ if (!force) {
158
+ const cached = readCache();
159
+ if (cached) {
160
+ logDebug("update-check", "Using cached result");
161
+ return cached;
162
+ }
161
163
  }
162
164
 
163
165
  const result = isRepoMode() ? await checkRepo() : await checkNpm();
@@ -169,6 +171,8 @@ export async function checkForUpdate(): Promise<void> {
169
171
  `Update available: ${result.current} → ${result.latest} (${result.mode})`
170
172
  );
171
173
  }
174
+
175
+ return result;
172
176
  }
173
177
 
174
178
  /** Read cached update status for greeting display. Returns null if no update. */
@@ -179,10 +183,7 @@ export function getUpdateNotice(): string | null {
179
183
  const cache = JSON.parse(readFileSync(fp, "utf-8")) as UpdateCache;
180
184
  if (!cache.available) return null;
181
185
 
182
- if (cache.mode === "repo") {
183
- return `📦 Update available: ${cache.current} → ${cache.latest} (git pull)`;
184
- }
185
- return `📦 Update available: ${cache.current} → ${cache.latest} (bun update -g portable-agent-layer)`;
186
+ return `📦 Update available: ${cache.current} ${cache.latest} (pal cli update)`;
186
187
  } catch {
187
188
  return null;
188
189
  }