portable-agent-layer 0.57.0 → 0.58.0

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.
@@ -71,18 +71,22 @@ On Cursor, session cost and rate limits are usually absent from stdin — the sc
71
71
 
72
72
  ### On Windows
73
73
 
74
- 1. Add to `~/.claude/settings.json`:
74
+ The installer does this automatically. To wire it manually, copy `statusline.ps1` to
75
+ `~/.claude/statusline.ps1` and add to `~/.claude/settings.json`:
75
76
  ```json
76
77
  {
77
78
  "statusLine": {
78
79
  "type": "command",
79
- "command": "powershell -NoProfile -Command \"Get-Content -Raw | & 'C:\\path\\to\\statusline.ps1'\"",
80
+ "command": "powershell -NoProfile -ExecutionPolicy Bypass -File ~/.claude/statusline.ps1",
80
81
  "padding": 2
81
82
  }
82
83
  }
83
84
  ```
84
85
 
85
- Or copy `statusline.ps1` to `~/.claude/statusline.ps1` and reference it from settings.
86
+ `-ExecutionPolicy Bypass` (which must precede `-File`) lets the unsigned script run under a
87
+ `Restricted`/`AllSigned` machine policy — the common reason the status line silently fails to
88
+ appear. It does **not** override a policy enforced via Group Policy (`MachinePolicy`/`UserPolicy`);
89
+ run `Get-ExecutionPolicy -List` to check the scope, and if it's a GPO scope, that case needs IT.
86
90
 
87
91
  The statusline script is at: `portable-agent-layer/assets/statusline.ps1`
88
92
 
@@ -104,7 +108,7 @@ The statusline script is at: `portable-agent-layer/assets/statusline.ps1`
104
108
  ## Dependencies
105
109
 
106
110
  - **macOS/Linux:** `bash`, `jq`, `git` (for branch detection)
107
- - **Windows:** PowerShell 7+, `git` (for branch detection)
111
+ - **Windows:** Windows PowerShell 5.1 (invoked as `powershell`; the script is 5.1-compatible) or PowerShell 7, `git` (for branch detection)
108
112
 
109
113
  ## Customization
110
114
 
@@ -0,0 +1,54 @@
1
+ ---
2
+ name: skill-author
3
+ description: Authors a new personal PAL skill end-to-end — writes the SKILL.md (and any tools), links it into every installed agent, and runs the doctor. Invoked by the create-skill skill to delegate the creative authoring to a flagship model.
4
+
5
+ claude:
6
+ tools: Bash, Read, Write, Edit, Grep, Glob
7
+ model: fable
8
+
9
+ opencode:
10
+ mode: subagent
11
+ permission:
12
+ read: allow
13
+ write: allow
14
+ edit: allow
15
+ bash: allow
16
+
17
+ cursor:
18
+ model: inherit
19
+ readonly: false
20
+ is_background: false
21
+ ---
22
+
23
+ You author a single new personal skill for this user. You are handed a **skill name** and a **skill description**, and optionally hints about tooling or triggers.
24
+
25
+ ## Steps
26
+
27
+ 1. Read the authoring guide — it is the single source of truth for what a good skill is and the exact anatomy to follow:
28
+ ```bash
29
+ cat ~/.pal/skills/create-skill/authoring-guide.md
30
+ ```
31
+ 2. Validate the name: lowercase-kebab, no spaces, not colliding with an existing skill (check `~/.pal/skills/` and the active skill list). If it collides or is malformed, stop and report the conflict instead of overwriting.
32
+ 3. Create the skill and write its `SKILL.md`, populated per the guide's anatomy (frontmatter + Workflow + Output format + When to use):
33
+ ```bash
34
+ mkdir -p ~/.pal/skills/<name>
35
+ ```
36
+ 4. If the skill needs runtime tooling, scaffold a `tools/` subdir alongside `SKILL.md` and write the scripts there.
37
+ 5. Link the skill into every installed agent:
38
+ ```bash
39
+ pal cli skill link <name>
40
+ ```
41
+ 6. Run the doctor and fix every `✗` error it reports; weigh each `⚠`:
42
+ ```bash
43
+ pal cli skill doctor <name>
44
+ ```
45
+ A name/folder mismatch or a misnamed file makes the skill silently fail to load — never skip this.
46
+ 7. Hand-check what the doctor can't: trigger clarity, step concreteness (every step has a verb and an object), output specification, and scope discipline (one skill, one job).
47
+
48
+ ## Output
49
+
50
+ Return, concisely:
51
+ - The path of the created `SKILL.md` (under `~/.pal/skills/<name>/`).
52
+ - The agents it was linked into (from the `pal cli skill link` output).
53
+ - The doctor's final result (errors resolved).
54
+ - A 2-3 sentence summary of the trigger and workflow, and how to invoke it.
@@ -8,65 +8,28 @@ argument-hint: <skill name> <skill description>
8
8
 
9
9
  This scaffolds a personal skill into the user's own `~/.pal/skills/<name>/` and links it into every installed agent so it is immediately discoverable.
10
10
 
11
- ## What makes a good skill
11
+ The quality rules and the exact skill anatomy live in one place — read them before writing anything:
12
12
 
13
- 1. **Pointed at the assistant, not the user.** A skill is *instructions you (the assistant) follow*. Write in second person addressing yourself ("read X", "run Y", "output Z"). Prescriptive verbs, deterministic flow — not a tutorial or marketing blurb.
14
-
15
- 2. **One skill, one job.** A skill describes a single workflow. If it needs branches like "for case A do X, for case B do Y," it is two skills.
16
-
17
- 3. **Concise and concrete.** Assume the model is already smart — only add what it doesn't already know. Every step has a verb and an object; no "as needed" or "appropriately." Keep the SKILL.md body well under 500 lines; push long reference material into sibling files linked one level deep.
18
-
19
- A personal skill **may** contain this user's own context — their paths, project names, preferences, conventions. That is the point of a personal skill.
20
-
21
- ## Skill anatomy
22
-
23
- ```markdown
24
- ---
25
- name: <slug> # the slash-command name; lowercase-kebab
26
- description: <what it does + WHEN to invoke> # the dispatcher matches on this
27
- argument-hint: <args> # optional; how the user passes input
28
- ---
29
-
30
- ## Overview / Workflow
31
-
32
- Numbered, concrete steps the assistant follows on invocation.
33
-
34
- ## Output format
35
-
36
- Exactly what the assistant returns — structure if it will be parsed, tone if a human reads it.
37
-
38
- ## When to use / Do NOT use
39
-
40
- Two short lists; the "do not" list disambiguates this skill from neighbours.
13
+ ```bash
14
+ cat ~/.pal/skills/create-skill/authoring-guide.md
41
15
  ```
42
16
 
43
- The `description` should state **both what the skill does and when to invoke it**, in third person, with the trigger terms a model would match on. A vague description ("helps with documents") will not trigger reliably.
44
-
45
17
  ## Workflow when invoked with `<name> <description>`
46
18
 
47
- 1. Validate the name: lowercase-kebab, no spaces, not colliding with an existing skill (check `~/.pal/skills/` and the active skill list).
48
- 2. Confirm the trigger with the user if the description is ambiguous about *when* the skill should fire.
49
- 3. Create the directory and SKILL.md at the user's PAL home:
50
- ```bash
51
- mkdir -p ~/.pal/skills/<name>
52
- ```
53
- Write `~/.pal/skills/<name>/SKILL.md` populated from the anatomy above (frontmatter + Workflow + Output format + When to use).
54
- 4. If the skill needs runtime tooling, scaffold a `tools/` subdir alongside SKILL.md and write the scripts there.
55
- 5. Link the new skill into every installed agent so it is discoverable:
56
- ```bash
57
- pal cli skill link <name>
58
- ```
59
- This creates the per-skill discovery symlink in each installed agent's skills directory (Claude Code, Cursor, Copilot, Codex); opencode discovers it automatically via `~/.pal/skills/`.
60
- 6. Run the doctor and resolve every error it reports:
19
+ 1. Check whether a flagship authoring model is configured for the current agent:
61
20
  ```bash
62
- pal cli skill doctor <name>
21
+ pal cli skill author-model
63
22
  ```
64
- It checks the mechanical rules (folder/file-name match, name length/charset, description length, point-of-view, body length, reference depth). Fix all `✗` errors; weigh each `⚠` warning. A name/folder mismatch or a misnamed file makes the skill silently fail to load, so never skip this.
65
- 7. Validate the rest by hand the doctor can't judge these:
66
- - **Trigger clarity** could a model decide *not* to invoke this from the description alone? If so, tighten it.
67
- - **Step concreteness** every step has a verb and an object.
68
- - **Output specification** the caller knows what they get back.
69
- - **Scope discipline** one skill, one job.
23
+ 2. **If it prints a model** delegate the authoring to the `skill-author` subagent. That subagent is preconfigured to run on that flagship model; hand it the skill name, description, and any trigger/tooling hints, and let it write the SKILL.md, scaffold tools, run `pal cli skill link`, and run the doctor. Relay its result.
24
+ 3. **If it prints nothing** author the skill inline yourself:
25
+ - Read `authoring-guide.md` (above) and follow its anatomy.
26
+ - `mkdir -p ~/.pal/skills/<name>` and write `~/.pal/skills/<name>/SKILL.md`.
27
+ - If the skill needs runtime tooling, scaffold a `tools/` subdir and write the scripts there.
28
+ - Link it into every installed agent: `pal cli skill link <name>`.
29
+ - Run `pal cli skill doctor <name>` and fix every `✗`; weigh each `⚠`.
30
+ - Hand-check the items the doctor can't judge (see the guide's final section).
31
+
32
+ Either path: validate the name first (lowercase-kebab, no spaces, not colliding with an existing skill in `~/.pal/skills/` or the active skill list), and confirm the trigger with the user if the description is ambiguous about *when* the skill should fire.
70
33
 
71
34
  ## Output format
72
35
 
@@ -0,0 +1,46 @@
1
+ # Skill authoring guide
2
+
3
+ The canonical rules for authoring a personal PAL skill. Both the `create-skill`
4
+ dispatcher and the delegated `skill-author` subagent follow this file, so it is
5
+ the single source of truth for skill quality.
6
+
7
+ ## What makes a good skill
8
+
9
+ 1. **Pointed at the assistant, not the user.** A skill is *instructions you (the assistant) follow*. Write in second person addressing yourself ("read X", "run Y", "output Z"). Prescriptive verbs, deterministic flow — not a tutorial or marketing blurb.
10
+
11
+ 2. **One skill, one job.** A skill describes a single workflow. If it needs branches like "for case A do X, for case B do Y," it is two skills.
12
+
13
+ 3. **Concise and concrete.** Assume the model is already smart — only add what it doesn't already know. Every step has a verb and an object; no "as needed" or "appropriately." Keep the SKILL.md body well under 500 lines; push long reference material into sibling files linked one level deep.
14
+
15
+ A personal skill **may** contain this user's own context — their paths, project names, preferences, conventions. That is the point of a personal skill.
16
+
17
+ ## Skill anatomy
18
+
19
+ ```markdown
20
+ ---
21
+ name: <slug> # the slash-command name; lowercase-kebab
22
+ description: <what it does + WHEN to invoke> # the dispatcher matches on this
23
+ argument-hint: <args> # optional; how the user passes input
24
+ ---
25
+
26
+ ## Overview / Workflow
27
+
28
+ Numbered, concrete steps the assistant follows on invocation.
29
+
30
+ ## Output format
31
+
32
+ Exactly what the assistant returns — structure if it will be parsed, tone if a human reads it.
33
+
34
+ ## When to use / Do NOT use
35
+
36
+ Two short lists; the "do not" list disambiguates this skill from neighbours.
37
+ ```
38
+
39
+ The `description` should state **both what the skill does and when to invoke it**, in third person, with the trigger terms a model would match on. A vague description ("helps with documents") will not trigger reliably.
40
+
41
+ ## Hand-checks the doctor can't judge
42
+
43
+ - **Trigger clarity** — could a model decide *not* to invoke this from the description alone? If so, tighten it.
44
+ - **Step concreteness** — every step has a verb and an object.
45
+ - **Output specification** — the caller knows what they get back.
46
+ - **Scope discipline** — one skill, one job.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "portable-agent-layer",
3
- "version": "0.57.0",
3
+ "version": "0.58.0",
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
@@ -262,6 +262,7 @@ function showHelp() {
262
262
  (search · graph · stats · hubs · find · show · add · ls)
263
263
  pal cli skill link <name> Link a personal ~/.pal/skills/<name>/ into installed agents
264
264
  pal cli skill doctor <name> Evaluate a skill against the authoring best practices
265
+ pal cli skill author-model Print the flagship model that authors skills for the active agent
265
266
  pal cli debug [on|off] Enable/disable verbose hook debug logging (persisted)
266
267
 
267
268
  Environment:
package/src/cli/skill.ts CHANGED
@@ -5,9 +5,13 @@
5
5
  * every installed agent so it is discoverable.
6
6
  * pal cli skill doctor <name> Evaluate ~/.pal/skills/<name>/ against the
7
7
  * skill-authoring best practices.
8
+ * pal cli skill author-model Print the flagship model configured to author
9
+ * skills for the active agent (empty if none).
8
10
  */
9
11
 
10
12
  import { resolve } from "node:path";
13
+ import { getActiveAgent } from "../hooks/lib/agent";
14
+ import { flagshipAuthorModel } from "../hooks/lib/models";
11
15
  import { palHome } from "../hooks/lib/paths";
12
16
  import { linkPersonalSkill, log } from "../targets/lib";
13
17
  import { formatReport, lintSkill } from "../tools/skill-doctor";
@@ -15,6 +19,12 @@ import { formatReport, lintSkill } from "../tools/skill-doctor";
15
19
  export async function runSkill(args: string[]): Promise<number> {
16
20
  const [sub, name] = args;
17
21
 
22
+ if (sub === "author-model") {
23
+ const model = flagshipAuthorModel(getActiveAgent());
24
+ if (model) console.log(model);
25
+ return 0;
26
+ }
27
+
18
28
  if (sub === "doctor") {
19
29
  if (!name) {
20
30
  log.error("Usage: pal cli skill doctor <name>");
@@ -50,6 +60,6 @@ export async function runSkill(args: string[]): Promise<number> {
50
60
  }
51
61
  }
52
62
 
53
- log.error("Usage: pal cli skill <link|doctor> <name>");
63
+ log.error("Usage: pal cli skill <link|doctor|author-model> [name]");
54
64
  return 1;
55
65
  }
@@ -11,7 +11,7 @@
11
11
  * vars are used as secondary fallbacks for environments that forward them.
12
12
  */
13
13
 
14
- type AgentType = "claude" | "cursor" | "codex" | "copilot" | "opencode";
14
+ export type AgentType = "claude" | "cursor" | "codex" | "copilot" | "opencode";
15
15
 
16
16
  const KNOWN_AGENTS: ReadonlySet<AgentType> = new Set([
17
17
  "claude",
@@ -2,8 +2,29 @@
2
2
  * Single source of truth for model IDs and pricing.
3
3
  */
4
4
 
5
+ import type { AgentType } from "./agent";
6
+
5
7
  export const HAIKU_MODEL = "claude-haiku-4-5-20251001";
6
8
  export const SONNET_MODEL = "claude-sonnet-4-6";
9
+ export const FABLE_MODEL = "claude-fable-5";
10
+
11
+ /**
12
+ * Per-agent flagship model used to AUTHOR new skills (via `create-skill`).
13
+ *
14
+ * This is the single extension point for delegated skill authoring: an agent
15
+ * present here → `create-skill` spins up that agent's `skill-author` subagent on
16
+ * this model; an agent absent → `create-skill` authors inline. Add a provider by
17
+ * adding one entry (and a matching platform block in assets/agents/skill-author.md).
18
+ */
19
+ export const FLAGSHIP_AUTHOR_MODEL: Partial<Record<AgentType, string>> = {
20
+ claude: FABLE_MODEL,
21
+ // codex: "gpt-5.5", // enable once Codex ships a tool-capable flagship subagent
22
+ };
23
+
24
+ /** Flagship authoring model for an agent, or undefined if none is configured. */
25
+ export function flagshipAuthorModel(agent: AgentType): string | undefined {
26
+ return FLAGSHIP_AUTHOR_MODEL[agent];
27
+ }
7
28
 
8
29
  /** Pricing per million tokens (USD) — from https://platform.claude.com/docs/en/about-claude/pricing */
9
30
  export const MODEL_PRICING: Record<
@@ -1042,7 +1042,7 @@ function statuslineCommand(target: StatuslineTarget): string {
1042
1042
  : "~/.cursor/statusline.sh";
1043
1043
  }
1044
1044
  return isPlatformWin32
1045
- ? "powershell -NoProfile -File ~/.claude/statusline.ps1"
1045
+ ? "powershell -NoProfile -ExecutionPolicy Bypass -File ~/.claude/statusline.ps1"
1046
1046
  : "~/.claude/statusline.sh";
1047
1047
  }
1048
1048
 
@@ -1105,6 +1105,23 @@ export function removeStatusline(target: StatuslineTarget = "claude"): boolean {
1105
1105
  }
1106
1106
  }
1107
1107
 
1108
+ function isOldGetContentClaudeCommand(cmd: string): boolean {
1109
+ return cmd.includes("Get-Content -Raw");
1110
+ }
1111
+
1112
+ function isPalWindowsClaudeCommandMissingBypass(cmd: string): boolean {
1113
+ return (
1114
+ process.platform === "win32" &&
1115
+ isPalStatuslineCommand(cmd, "claude") &&
1116
+ cmd.includes("powershell") &&
1117
+ !cmd.includes("-ExecutionPolicy Bypass")
1118
+ );
1119
+ }
1120
+
1121
+ function claudeStatuslineNeedsRefresh(cmd: string): boolean {
1122
+ return isOldGetContentClaudeCommand(cmd) || isPalWindowsClaudeCommandMissingBypass(cmd);
1123
+ }
1124
+
1108
1125
  /** Add statusLine config if not already present or if using an old broken command */
1109
1126
  export function addStatuslineConfig(
1110
1127
  settings: Record<string, unknown>,
@@ -1115,8 +1132,7 @@ export function addStatuslineConfig(
1115
1132
  if (statusLine && typeof statusLine === "object" && statusLine.command) {
1116
1133
  const cmd = statusLine.command as string;
1117
1134
  if (target === "claude") {
1118
- // Keep existing config unless it's the old broken Get-Content pattern
1119
- if (!cmd.includes("Get-Content -Raw")) {
1135
+ if (!claudeStatuslineNeedsRefresh(cmd)) {
1120
1136
  return settings;
1121
1137
  }
1122
1138
  } else if (!isPalStatuslineCommand(cmd, "cursor")) {