pi-zellij 0.4.8 → 0.4.9

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/CHANGELOG.md CHANGED
@@ -4,6 +4,7 @@
4
4
 
5
5
  ### Added
6
6
 
7
+ - Added optional `pi-zellij.review.skill` settings for `/zrv` and `/zrh` to use an existing loaded skill, with project overrides and errors for unavailable or unreadable skills.
7
8
  - Initial `pi-zellij` release with zellij-powered pane workflows for Pi.
8
9
  - Added `/zv`, `/zj`, and `/zt` to open a new zellij pane or tab and start a fresh Pi session in the same working directory.
9
10
  - Added `/zo` and `/zoh` to open a new pane and run any shell command there.
@@ -19,6 +20,7 @@
19
20
 
20
21
  ### Changed
21
22
 
23
+ - `/zrv` and `/zrh` now use self-contained review instructions by default, injected only into the new review session. `/review` and `/review-diff` no longer refer to a bundled skill.
22
24
  - Explicit history inheritance now rejects branches with no conversation messages before creating a cloned session or opening a pane.
23
25
  - Expanded `zellij_open_terminal` prompt guidance so agents recognize requests to start another Pi session and prefer the dedicated `zellij_start_pi` interface when available.
24
26
  - Pi launch command construction now supports quoted provider, model, and thinking options and stops option parsing before initial prompts.
@@ -30,4 +32,5 @@
30
32
 
31
33
  ### Removed
32
34
 
35
+ - Removed the bundled `code-review` skill from the package and installer so terminal workflows do not register a global review skill.
33
36
  - Removed the bundled `zv-notify` extension so `pi-zellij` does not conflict with separate notification packages or user-specific notification setups.
package/README.md CHANGED
@@ -70,9 +70,7 @@ If pi is already running, use:
70
70
  - `/review <target>`, `/review-diff [focus-or-pr-url]`
71
71
  - expand bundled review prompts in the current pane
72
72
  - `/zrv`, `/zrh`, plus review flags
73
- - open review-focused Pi sessions in a split
74
- - `/skill:code-review`
75
- - loads the bundled structured review skill for files, directories, diffs, and PRs
73
+ - open review-focused Pi sessions in a split with built-in instructions or a configured skill
76
74
 
77
75
  ## Bundled extensions and resources
78
76
 
@@ -85,7 +83,6 @@ Extensions:
85
83
  - `zv-continue`
86
84
 
87
85
  Other bundled resources:
88
- - `code-review` skill
89
86
  - `/review` prompt template
90
87
  - `/review-diff` prompt template
91
88
 
@@ -317,7 +314,7 @@ Examples:
317
314
 
318
315
  ### Review helpers
319
316
 
320
- `pi-zellij` also bundles a reusable `code-review` skill plus prompt templates for in-place review:
317
+ `pi-zellij` includes built-in review instructions; no skill installation is required and no review skill is registered globally. It also bundles prompt templates for in-place review:
321
318
 
322
319
  - `/review <target>`
323
320
  - prompt template for reviewing a file, directory, or GitHub pull request URL in the current pane
@@ -356,3 +353,26 @@ Examples:
356
353
 
357
354
  If the target is a GitHub pull request URL, the review workflow switches to PR review and instructs pi to inspect the pull request with `gh pr view` and `gh pr diff`.
358
355
 
356
+ #### Use your own review skill
357
+
358
+ By default, `/zrv` and `/zrh` inject the built-in review instructions into the new session's initial prompt only. To use an existing skill instead, set `pi-zellij.review.skill` in `~/.pi/agent/settings.json` or the trusted project's `.pi/settings.json`:
359
+
360
+ ```json
361
+ {
362
+ "pi-zellij": {
363
+ "review": {
364
+ "skill": "my-code-review"
365
+ }
366
+ }
367
+ }
368
+ ```
369
+
370
+ Use the skill's name without the `/skill:` prefix. It must be loaded in the current Pi session. The commands expand its instructions before opening the pane, preserving its location for relative references and passing the review target and mode. The skill controls the workflow and output format; the request still tells Pi not to edit files unless asked.
371
+
372
+ - Omit the setting to use the built-in instructions.
373
+ - Project settings override global settings. Set `"skill": null` in the project to use the built-in instructions despite a global override.
374
+ - An unavailable or unreadable skill, or invalid review settings, produces an error without opening a pane. There is no silent fallback.
375
+ - Review settings are read on each invocation. After installing or enabling a skill, run `/reload` first.
376
+
377
+ This setting only affects `/zrv` and `/zrh`; `/review` and `/review-diff` remain self-contained prompt templates.
378
+
@@ -1,33 +1,15 @@
1
- ---
2
- name: code-review
3
- description: Structured code review workflow for files, directories, and git diffs. Use when reviewing code for bugs, regressions, maintainability, missing tests, or refactor opportunities.
4
- ---
5
-
6
1
  # Code Review
7
2
 
8
- Use this skill for targeted code review requests, including file reviews, module reviews, and current diff reviews.
9
-
10
3
  ## Review goals
11
4
 
12
5
  - Find the most important issues first.
13
6
  - Prefer concrete, evidence-based findings over broad stylistic commentary.
14
7
  - Call out missing tests or risky edge cases when they matter.
15
- - Do not edit files unless the user explicitly asks for changes.
16
-
17
- ## Review modes
18
-
19
- Infer the mode from the user request:
20
- - **General review** — correctness, readability, maintainability, and missing tests
21
- - **Bug-focused review** — correctness, runtime failures, invalid assumptions, edge cases, regressions
22
- - **Refactor review** — simplification, structure, naming, duplication, cohesion, maintainability
23
- - **Test review** — missing coverage, brittle assertions, edge cases, regression protection
24
- - **Diff review** — review the current git diff or requested change set for regressions and missing validation
25
- - **GitHub PR review** — when given a GitHub pull request URL, inspect it with `gh pr view` and `gh pr diff` before concluding
26
8
 
27
9
  ## Workflow
28
10
 
29
11
  1. Identify the exact review scope.
30
- - If the user named a file, directory, symbol, or diff, stick to that scope.
12
+ - Stick to the requested file, directory, symbol, diff, or pull request.
31
13
  - If the scope is ambiguous, ask one concise clarifying question.
32
14
 
33
15
  2. Inspect the relevant code before concluding.
@@ -44,11 +26,8 @@ Infer the mode from the user request:
44
26
  - If there are no meaningful issues, say so clearly.
45
27
 
46
28
  5. Make findings actionable.
47
- - For each finding, explain:
48
- - what is wrong
49
- - why it matters
50
- - where it occurs
51
- - what change would improve it
29
+ - Explain what is wrong, why it matters, where it occurs, and what change would improve it.
30
+ - Include file paths and line numbers where possible.
52
31
 
53
32
  ## Output format
54
33
 
@@ -61,13 +40,11 @@ Summary
61
40
 
62
41
  Findings
63
42
  1. Severity: <high|medium|low>
64
- - Location: <file or diff area>
43
+ - Location: <file and line or diff area>
65
44
  - Issue: <what is wrong>
66
45
  - Impact: <why it matters>
67
46
  - Fix: <concrete suggestion>
68
47
 
69
- 2. ...
70
-
71
48
  Test gaps
72
49
  - <missing test or "None noted">
73
50
  ```
@@ -1,4 +1,13 @@
1
- import type { ExtensionAPI, ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
1
+ import {
2
+ CONFIG_DIR_NAME,
3
+ getAgentDir,
4
+ stripFrontmatter,
5
+ type ExtensionAPI,
6
+ type ExtensionCommandContext,
7
+ } from "@earendil-works/pi-coding-agent";
8
+ import { readFileSync } from "node:fs";
9
+ import { dirname, join } from "node:path";
10
+ import { fileURLToPath } from "node:url";
2
11
  import {
3
12
  buildPiCommand,
4
13
  formatPaneSuccessMessage,
@@ -7,6 +16,8 @@ import {
7
16
  type SplitDirection,
8
17
  } from "./zv-core.ts";
9
18
 
19
+ const REVIEW_TEMPLATE_PATH = join(dirname(fileURLToPath(import.meta.url)), "templates", "review.md");
20
+
10
21
  type ReviewMode = "general" | "bugs" | "refactor" | "tests" | "diff";
11
22
 
12
23
  interface ReviewRequest {
@@ -61,13 +72,56 @@ function getGitHubPullRequestUrl(value: string | undefined): string | undefined
61
72
  return /^https:\/\/github\.com\/[^/]+\/[^/]+\/pull\/\d+(?:[/?#].*)?$/.test(trimmed) ? trimmed : undefined;
62
73
  }
63
74
 
64
- function buildReviewPrompt(request: ReviewRequest): string {
65
- const commonInstructions = [
66
- "Use the bundled code-review skill if it is available.",
67
- "Start with a concise summary ordered by severity.",
68
- "Then list concrete findings with suggested fixes and any missing tests.",
69
- "Do not edit files unless asked.",
70
- ].join(" ");
75
+ function isRecord(value: unknown): value is Record<string, unknown> {
76
+ return typeof value === "object" && value !== null && !Array.isArray(value);
77
+ }
78
+
79
+ function readReviewSkillSetting(settingsPath: string): string | null | undefined {
80
+ let settings: unknown;
81
+ try {
82
+ settings = JSON.parse(readFileSync(settingsPath, "utf8"));
83
+ } catch (error) {
84
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") return undefined;
85
+ const message = error instanceof Error ? error.message : String(error);
86
+ throw new Error(`Failed to read settings from ${settingsPath}: ${message}`);
87
+ }
88
+
89
+ if (!isRecord(settings)) {
90
+ throw new Error(`Expected a settings object in ${settingsPath}`);
91
+ }
92
+ const section = settings["pi-zellij"];
93
+ if (section === undefined) return undefined;
94
+ if (!isRecord(section)) {
95
+ throw new Error(`pi-zellij must be an object in ${settingsPath}`);
96
+ }
97
+ const review = section.review;
98
+ if (review === undefined) return undefined;
99
+ if (!isRecord(review)) {
100
+ throw new Error(`pi-zellij.review must be an object in ${settingsPath}`);
101
+ }
102
+ const skill = review.skill;
103
+ if (skill === undefined || skill === null) return skill;
104
+ if (typeof skill !== "string" || !skill.trim()) {
105
+ throw new Error(`pi-zellij.review.skill must be a non-empty skill name or null in ${settingsPath}`);
106
+ }
107
+ return skill.trim();
108
+ }
109
+
110
+ function loadReviewSkill(ctx: ExtensionCommandContext): string | undefined {
111
+ const settingsPaths = [join(getAgentDir(), "settings.json")];
112
+ if (ctx.isProjectTrusted()) {
113
+ settingsPaths.push(join(ctx.cwd, CONFIG_DIR_NAME, "settings.json"));
114
+ }
115
+
116
+ let skill: string | null | undefined;
117
+ for (const settingsPath of settingsPaths) {
118
+ const value = readReviewSkillSetting(settingsPath);
119
+ if (value !== undefined) skill = value;
120
+ }
121
+ return skill ?? undefined;
122
+ }
123
+
124
+ function buildReviewScope(request: ReviewRequest): string {
71
125
  const pullRequestUrl = getGitHubPullRequestUrl(request.targetOrFocus);
72
126
  const modeInstruction =
73
127
  request.mode === "bugs"
@@ -79,15 +133,43 @@ function buildReviewPrompt(request: ReviewRequest): string {
79
133
  : "Focus on correctness, readability, maintainability, and missing tests.";
80
134
 
81
135
  if (pullRequestUrl) {
82
- return `Review GitHub pull request ${pullRequestUrl}. Use the gh CLI to inspect it, including gh pr view ${pullRequestUrl} and gh pr diff ${pullRequestUrl}. ${modeInstruction} Prioritize the changed code, likely regressions, and missing tests before adding lower-priority notes. ${commonInstructions}`;
136
+ return `Review GitHub pull request ${pullRequestUrl}. Use the gh CLI to inspect it, including gh pr view ${pullRequestUrl} and gh pr diff ${pullRequestUrl}. ${modeInstruction} Prioritize the changed code, likely regressions, and missing tests before adding lower-priority notes.`;
83
137
  }
84
138
 
85
139
  if (request.mode === "diff") {
86
140
  const focus = request.targetOrFocus ? ` Extra focus: ${request.targetOrFocus}.` : "";
87
- return `Review the current git diff in this repository.${focus} Prioritize regressions, correctness issues, risky edge cases, and missing tests. ${commonInstructions}`;
141
+ return `Review the current git diff in this repository.${focus} Prioritize regressions, correctness issues, risky edge cases, and missing tests.`;
88
142
  }
89
143
 
90
- return `Review ${request.targetOrFocus} from the current project. ${modeInstruction} If the target is a directory, review the most relevant files within that scope. ${commonInstructions}`;
144
+ return `Review ${request.targetOrFocus} from the current project. ${modeInstruction} If the target is a directory, review the most relevant files within that scope.`;
145
+ }
146
+
147
+ function buildReviewPrompt(request: ReviewRequest, ctx: ExtensionCommandContext): string {
148
+ const scope = `${buildReviewScope(request)} Do not edit files unless asked.`;
149
+ const skillName = loadReviewSkill(ctx);
150
+ if (!skillName) {
151
+ return `${readFileSync(REVIEW_TEMPLATE_PATH, "utf8").trim()}\n\n${scope}`;
152
+ }
153
+
154
+ const skill = ctx.getSystemPromptOptions().skills?.find((entry) => entry.name === skillName);
155
+ if (!skill) {
156
+ throw new Error(
157
+ `Review skill "${skillName}" is not available in this session. Enable or install it and run /reload, or set pi-zellij.review.skill to null.`,
158
+ );
159
+ }
160
+
161
+ let body: string;
162
+ try {
163
+ body = stripFrontmatter(readFileSync(skill.filePath, "utf8")).trim();
164
+ if (!body) throw new Error("Skill instructions are empty");
165
+ } catch (error) {
166
+ const message = error instanceof Error ? error.message : String(error);
167
+ throw new Error(`Cannot load review skill "${skillName}" from ${skill.filePath}: ${message}`);
168
+ }
169
+
170
+ // Expand before launching, as Pi does for /skill:name. This validates the file
171
+ // and carries even CLI-only skills into the child without rediscovering them.
172
+ return `<skill name="${skill.name}" location="${skill.filePath}">\nReferences are relative to ${skill.baseDir}.\n\n${body}\n</skill>\n\n${scope}`;
91
173
  }
92
174
 
93
175
  async function openReviewSplit(
@@ -96,7 +178,12 @@ async function openReviewSplit(
96
178
  direction: SplitDirection,
97
179
  request: ReviewRequest,
98
180
  ): Promise<PaneOpenResult> {
99
- return openCommandInNewSplit(pi, direction, buildPiCommand(ctx.cwd, { prompt: buildReviewPrompt(request) }));
181
+ try {
182
+ const prompt = buildReviewPrompt(request, ctx);
183
+ return await openCommandInNewSplit(pi, direction, buildPiCommand(ctx.cwd, { prompt }));
184
+ } catch (error) {
185
+ return { ok: false, error: error instanceof Error ? error.message : String(error) };
186
+ }
100
187
  }
101
188
 
102
189
  function registerReviewCommand(
package/install.mjs CHANGED
@@ -14,7 +14,7 @@ const PACKAGE_DIR = path.join(AGENT_DIR, "packages", PACKAGE_NAME);
14
14
  const PACKAGE_SETTINGS_ENTRY = `./packages/${PACKAGE_NAME}`;
15
15
  const SOURCE_DIR = path.dirname(fileURLToPath(import.meta.url));
16
16
  const FILES_TO_COPY = ["package.json", "README.md", "CHANGELOG.md"];
17
- const DIRECTORIES_TO_COPY = ["extensions", "skills", "prompts"];
17
+ const DIRECTORIES_TO_COPY = ["extensions", "prompts"];
18
18
 
19
19
  const args = process.argv.slice(2);
20
20
  const isRemove = args.includes("--remove") || args.includes("-r");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-zellij",
3
- "version": "0.4.8",
3
+ "version": "0.4.9",
4
4
  "description": "Pi package with zellij-powered terminal integrations",
5
5
  "author": "Javi Molina",
6
6
  "license": "MIT",
@@ -28,7 +28,6 @@
28
28
  },
29
29
  "files": [
30
30
  "extensions/",
31
- "skills/",
32
31
  "prompts/",
33
32
  "install.mjs",
34
33
  "README.md",
@@ -41,9 +40,6 @@
41
40
  "extensions": [
42
41
  "./extensions/index.ts"
43
42
  ],
44
- "skills": [
45
- "./skills"
46
- ],
47
43
  "prompts": [
48
44
  "./prompts"
49
45
  ]
@@ -1,8 +1,6 @@
1
1
  ---
2
2
  description: Review the current git diff for regressions and missing tests
3
3
  ---
4
- Use the bundled `code-review` skill if it is available.
5
-
6
4
  Review the current git diff in this repository. If `${@:1}` is a GitHub pull request URL, inspect that pull request instead using `gh pr view <url>` and `gh pr diff <url>`. ${@:1} Prioritize regressions, correctness issues, risky edge cases, and missing tests.
7
5
 
8
6
  Start with a concise summary ordered by severity. Then list concrete findings with suggested fixes. Do not edit files unless asked.
package/prompts/review.md CHANGED
@@ -1,8 +1,6 @@
1
1
  ---
2
2
  description: Review a file or directory for bugs, maintainability issues, and missing tests
3
3
  ---
4
- Use the bundled `code-review` skill if it is available.
5
-
6
4
  Review `$1` from the current project. If the target is a GitHub pull request URL, inspect it with `gh pr view <url>` and `gh pr diff <url>`. Focus on correctness, readability, maintainability, and missing tests. If the target is a directory, review the most relevant files within that scope.
7
5
 
8
6
  Start with a concise summary ordered by severity. Then list concrete findings with suggested fixes. Do not edit files unless asked.