pi-local-agents-only 0.1.4 → 0.1.6
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 +17 -0
- package/README.md +2 -0
- package/extensions/local-agents-only.js +230 -18
- package/package.json +24 -5
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.6 - 2026-04-07
|
|
4
|
+
|
|
5
|
+
- add dev-time static checking with `tsc --noEmit`
|
|
6
|
+
- add a local `check` script that runs tests plus typechecking
|
|
7
|
+
- keep pi core typing support in `devDependencies` only so this stays a lightweight published package
|
|
8
|
+
- annotate the extension with `// @ts-check` and JSDoc types for earlier local error detection
|
|
9
|
+
|
|
10
|
+
## 0.1.5 - 2026-04-07
|
|
11
|
+
|
|
12
|
+
- strip already-loaded global `AGENTS.md` / `CLAUDE.md` context reliably instead of rereading live files from disk
|
|
13
|
+
- remove the now-empty `# Project Context` section when only global context was loaded
|
|
14
|
+
- handle prompts whose custom prompt text also mentions the `# Project Context` heading
|
|
15
|
+
- make `/local-agents-only off` report when the repo is still enabled via the global allowlist or `PI_LOCAL_AGENTS_ONLY`
|
|
16
|
+
- document the repo-marker-only behavior of `/local-agents-only off`
|
|
17
|
+
- add integration tests against pi's real system prompt builder and command UX regressions
|
package/README.md
CHANGED
|
@@ -30,6 +30,8 @@ Disable for the current repo:
|
|
|
30
30
|
/local-agents-only off
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
+
`/local-agents-only off` clears the repo marker only. If the repo is still enabled via `/local-agents-only global-on` or `PI_LOCAL_AGENTS_ONLY=1`, it remains enabled until you also run `/local-agents-only global-off` or unset the env var.
|
|
34
|
+
|
|
33
35
|
Enable or disable via the global allowlist:
|
|
34
36
|
|
|
35
37
|
```bash
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Purpose: Strip pi's global AGENTS.md and CLAUDE.md blocks from the effective prompt for opted-in projects.
|
|
3
5
|
* Responsibilities: Detect repo and worktree opt-in state, manage repo and global toggles, add a local-only guardrail, and remove matching global context blocks before model calls.
|
|
@@ -11,12 +13,25 @@ import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node
|
|
|
11
13
|
import { homedir } from "node:os";
|
|
12
14
|
import { dirname, join, resolve } from "node:path";
|
|
13
15
|
|
|
16
|
+
/** @typedef {import("@mariozechner/pi-coding-agent").ExtensionAPI} ExtensionAPI */
|
|
17
|
+
/** @typedef {import("@mariozechner/pi-coding-agent").ExtensionContext} ExtensionContext */
|
|
18
|
+
/** @typedef {{ projects: string[]; repositories: string[] }} LocalAgentsOnlyConfig */
|
|
19
|
+
/** @typedef {{ start: string; projectRoot: string; repoId: string; worktreeRoots: string[] }} ProjectState */
|
|
20
|
+
/** @typedef {{ enabled: boolean; source: "env" | "marker" | "global-config" | "default" }} Mode */
|
|
21
|
+
/** @typedef {{ path: string; start: number; end: number }} ContextBlock */
|
|
22
|
+
/** @typedef {{ prompt: string; removedPaths: string[] }} StripResult */
|
|
23
|
+
|
|
14
24
|
const COMMAND = "local-agents-only";
|
|
15
25
|
const MARKER = join(".pi", COMMAND);
|
|
16
26
|
const GLOBAL_CONTEXT_FILES = ["AGENTS.md", "CLAUDE.md"];
|
|
17
27
|
const ENV_TRUE = ["1", "true", "yes", "on"];
|
|
18
28
|
const ENV_FALSE = ["0", "false", "no", "off"];
|
|
29
|
+
const PROJECT_CONTEXT_HEADER = "\n\n# Project Context\n\nProject-specific instructions and guidelines:\n\n";
|
|
30
|
+
const SKILLS_HEADER = "\n\nThe following skills provide specialized instructions for specific tasks.";
|
|
31
|
+
const DATE_HEADER = "\nCurrent date:";
|
|
32
|
+
const CONTEXT_BLOCK_HEADER = /^## ([^\n]+(?:AGENTS|CLAUDE)\.md)\n\n/gm;
|
|
19
33
|
|
|
34
|
+
/** @returns {string} */
|
|
20
35
|
const getAgentDir = () => {
|
|
21
36
|
const env = process.env.PI_CODING_AGENT_DIR;
|
|
22
37
|
if (env === "~") {
|
|
@@ -27,10 +42,24 @@ const getAgentDir = () => {
|
|
|
27
42
|
}
|
|
28
43
|
return env || join(homedir(), ".pi", "agent");
|
|
29
44
|
};
|
|
45
|
+
|
|
46
|
+
/** @param {string} path */
|
|
30
47
|
const normalizePath = (path) => resolve(path).replace(/\\/g, "/");
|
|
48
|
+
|
|
49
|
+
/** @returns {string} */
|
|
31
50
|
const CONFIG = () => join(getAgentDir(), `${COMMAND}.json`);
|
|
51
|
+
|
|
52
|
+
/** @param {string} projectRoot */
|
|
32
53
|
const getMarkerPath = (projectRoot) => join(projectRoot, MARKER);
|
|
54
|
+
|
|
55
|
+
/** @param {string[]} values */
|
|
33
56
|
const uniqueSorted = (values) => [...new Set(values.map(normalizePath))].sort();
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* @param {string} start
|
|
60
|
+
* @param {(dir: string) => boolean} predicate
|
|
61
|
+
* @returns {string | undefined}
|
|
62
|
+
*/
|
|
34
63
|
const walkUp = (start, predicate) => {
|
|
35
64
|
let current = resolve(start);
|
|
36
65
|
while (true) {
|
|
@@ -39,11 +68,17 @@ const walkUp = (start, predicate) => {
|
|
|
39
68
|
}
|
|
40
69
|
const parent = dirname(current);
|
|
41
70
|
if (parent === current) {
|
|
42
|
-
return;
|
|
71
|
+
return undefined;
|
|
43
72
|
}
|
|
44
73
|
current = parent;
|
|
45
74
|
}
|
|
46
75
|
};
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* @param {string} start
|
|
79
|
+
* @param {string[]} args
|
|
80
|
+
* @returns {string | undefined}
|
|
81
|
+
*/
|
|
47
82
|
const runGit = (start, args) => {
|
|
48
83
|
try {
|
|
49
84
|
return execFileSync("git", args, {
|
|
@@ -52,20 +87,33 @@ const runGit = (start, args) => {
|
|
|
52
87
|
stdio: ["ignore", "pipe", "ignore"],
|
|
53
88
|
}).trim();
|
|
54
89
|
} catch {
|
|
55
|
-
return;
|
|
90
|
+
return undefined;
|
|
56
91
|
}
|
|
57
92
|
};
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* @param {string} [configPath]
|
|
96
|
+
* @returns {LocalAgentsOnlyConfig}
|
|
97
|
+
*/
|
|
58
98
|
const readConfig = (configPath = CONFIG()) => {
|
|
59
99
|
try {
|
|
60
|
-
const { projects
|
|
100
|
+
const parsed = /** @type {{ projects?: unknown; repositories?: unknown }} */ (
|
|
101
|
+
JSON.parse(readFileSync(configPath, "utf8"))
|
|
102
|
+
);
|
|
103
|
+
const { projects = [], repositories = [] } = parsed;
|
|
61
104
|
return {
|
|
62
|
-
projects: Array.isArray(projects) ? projects.map(normalizePath) : [],
|
|
63
|
-
repositories: Array.isArray(repositories) ? repositories.map(normalizePath) : [],
|
|
105
|
+
projects: Array.isArray(projects) ? projects.map((value) => normalizePath(String(value))) : [],
|
|
106
|
+
repositories: Array.isArray(repositories) ? repositories.map((value) => normalizePath(String(value))) : [],
|
|
64
107
|
};
|
|
65
108
|
} catch {
|
|
66
109
|
return { projects: [], repositories: [] };
|
|
67
110
|
}
|
|
68
111
|
};
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* @param {LocalAgentsOnlyConfig} config
|
|
115
|
+
* @param {string} [configPath]
|
|
116
|
+
*/
|
|
69
117
|
const writeConfig = ({ projects, repositories }, configPath = CONFIG()) => {
|
|
70
118
|
mkdirSync(dirname(configPath), { recursive: true });
|
|
71
119
|
writeFileSync(
|
|
@@ -80,6 +128,11 @@ const writeConfig = ({ projects, repositories }, configPath = CONFIG()) => {
|
|
|
80
128
|
) + "\n",
|
|
81
129
|
);
|
|
82
130
|
};
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* @param {string | undefined} [value]
|
|
134
|
+
* @returns {boolean | undefined}
|
|
135
|
+
*/
|
|
83
136
|
const getEnvToggle = (value = process.env.PI_LOCAL_AGENTS_ONLY) => {
|
|
84
137
|
const toggle = `${value ?? ""}`.trim().toLowerCase();
|
|
85
138
|
if (ENV_TRUE.includes(toggle)) {
|
|
@@ -88,19 +141,107 @@ const getEnvToggle = (value = process.env.PI_LOCAL_AGENTS_ONLY) => {
|
|
|
88
141
|
if (ENV_FALSE.includes(toggle)) {
|
|
89
142
|
return false;
|
|
90
143
|
}
|
|
144
|
+
return undefined;
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
/** @param {string} [agentDir] */
|
|
148
|
+
const getGlobalContextPaths = (agentDir = getAgentDir()) => GLOBAL_CONTEXT_FILES.map((name) => join(agentDir, name));
|
|
149
|
+
|
|
150
|
+
/** @param {string} [agentDir] */
|
|
151
|
+
const getExistingGlobalContextPaths = (agentDir = getAgentDir()) =>
|
|
152
|
+
getGlobalContextPaths(agentDir).filter((path) => existsSync(path));
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* @param {string} prompt
|
|
156
|
+
* @param {number} offset
|
|
157
|
+
* @returns {number}
|
|
158
|
+
*/
|
|
159
|
+
const getContextSectionEnd = (prompt, offset) => {
|
|
160
|
+
const candidates = [prompt.indexOf(SKILLS_HEADER, offset), prompt.indexOf(DATE_HEADER, offset)].filter(
|
|
161
|
+
(index) => index !== -1,
|
|
162
|
+
);
|
|
163
|
+
return candidates.length > 0 ? Math.min(...candidates) : prompt.length;
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* @param {string} contextSection
|
|
168
|
+
* @returns {ContextBlock[]}
|
|
169
|
+
*/
|
|
170
|
+
const getContextBlocks = (contextSection) => {
|
|
171
|
+
const matches = [...contextSection.matchAll(CONTEXT_BLOCK_HEADER)];
|
|
172
|
+
return matches.map((match, index) => ({
|
|
173
|
+
path: match[1],
|
|
174
|
+
start: match.index ?? 0,
|
|
175
|
+
end: index + 1 < matches.length ? (matches[index + 1].index ?? contextSection.length) : contextSection.length,
|
|
176
|
+
}));
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* @param {string} prompt
|
|
181
|
+
* @param {string[]} [globalPaths]
|
|
182
|
+
* @returns {StripResult}
|
|
183
|
+
*/
|
|
184
|
+
const stripGlobalContext = (prompt, globalPaths = getGlobalContextPaths()) => {
|
|
185
|
+
const sectionStart = prompt.lastIndexOf(PROJECT_CONTEXT_HEADER);
|
|
186
|
+
if (sectionStart === -1) {
|
|
187
|
+
return { prompt, removedPaths: [] };
|
|
188
|
+
}
|
|
189
|
+
const contextStart = sectionStart + PROJECT_CONTEXT_HEADER.length;
|
|
190
|
+
const sectionEnd = getContextSectionEnd(prompt, contextStart);
|
|
191
|
+
const contextSection = prompt.slice(contextStart, sectionEnd);
|
|
192
|
+
const blocks = getContextBlocks(contextSection);
|
|
193
|
+
if (blocks.length === 0) {
|
|
194
|
+
return { prompt, removedPaths: [] };
|
|
195
|
+
}
|
|
196
|
+
const globalPathKeys = new Set(globalPaths.map(normalizePath));
|
|
197
|
+
/** @type {string[]} */
|
|
198
|
+
const keptBlocks = [];
|
|
199
|
+
/** @type {string[]} */
|
|
200
|
+
const removedPaths = [];
|
|
201
|
+
for (const block of blocks) {
|
|
202
|
+
const blockText = contextSection.slice(block.start, block.end);
|
|
203
|
+
if (globalPathKeys.has(normalizePath(block.path))) {
|
|
204
|
+
removedPaths.push(block.path);
|
|
205
|
+
} else {
|
|
206
|
+
keptBlocks.push(blockText);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
if (removedPaths.length === 0) {
|
|
210
|
+
return { prompt, removedPaths: [] };
|
|
211
|
+
}
|
|
212
|
+
const prefix = prompt.slice(0, sectionStart);
|
|
213
|
+
const suffix = prompt.slice(sectionEnd);
|
|
214
|
+
if (keptBlocks.length === 0) {
|
|
215
|
+
return { prompt: `${prefix}${suffix}`, removedPaths: uniqueSorted(removedPaths) };
|
|
216
|
+
}
|
|
217
|
+
return {
|
|
218
|
+
prompt: `${prefix}${PROJECT_CONTEXT_HEADER}${keptBlocks.join("")}${suffix}`,
|
|
219
|
+
removedPaths: uniqueSorted(removedPaths),
|
|
220
|
+
};
|
|
91
221
|
};
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* @param {string} start
|
|
225
|
+
* @returns {string | undefined}
|
|
226
|
+
*/
|
|
96
227
|
const getGitTopLevel = (start) => {
|
|
97
228
|
const topLevel = runGit(start, ["rev-parse", "--show-toplevel"]);
|
|
98
229
|
return topLevel ? normalizePath(topLevel) : undefined;
|
|
99
230
|
};
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* @param {string} start
|
|
234
|
+
* @returns {string | undefined}
|
|
235
|
+
*/
|
|
100
236
|
const getGitCommonDir = (start) => {
|
|
101
237
|
const commonDir = runGit(start, ["rev-parse", "--git-common-dir"]);
|
|
102
238
|
return commonDir ? normalizePath(resolve(start, commonDir)) : undefined;
|
|
103
239
|
};
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* @param {string} start
|
|
243
|
+
* @returns {string[]}
|
|
244
|
+
*/
|
|
104
245
|
const getWorktreeRoots = (start) => {
|
|
105
246
|
const list = runGit(start, ["worktree", "list", "--porcelain"]);
|
|
106
247
|
if (!list) {
|
|
@@ -113,6 +254,11 @@ const getWorktreeRoots = (start) => {
|
|
|
113
254
|
.map((line) => line.slice("worktree ".length)),
|
|
114
255
|
);
|
|
115
256
|
};
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* @param {string} [start]
|
|
260
|
+
* @returns {ProjectState}
|
|
261
|
+
*/
|
|
116
262
|
const getProjectState = (start = process.cwd()) => {
|
|
117
263
|
const normalizedStart = normalizePath(start);
|
|
118
264
|
const gitTopLevel = getGitTopLevel(normalizedStart);
|
|
@@ -130,21 +276,33 @@ const getProjectState = (start = process.cwd()) => {
|
|
|
130
276
|
worktreeRoots.length > 0 ? uniqueSorted([projectRoot, ...worktreeRoots]) : [normalizePath(projectRoot)],
|
|
131
277
|
};
|
|
132
278
|
};
|
|
279
|
+
|
|
280
|
+
/** @param {ProjectState} state */
|
|
133
281
|
const getMarkerRoots = (state) => uniqueSorted([state.projectRoot, ...state.worktreeRoots]);
|
|
282
|
+
|
|
283
|
+
/** @param {ProjectState} state */
|
|
134
284
|
const hasMarker = (state) => getMarkerRoots(state).some((root) => existsSync(getMarkerPath(root)));
|
|
285
|
+
|
|
286
|
+
/** @param {ProjectState} state */
|
|
135
287
|
const writeMarkers = (state) => {
|
|
136
288
|
for (const root of getMarkerRoots(state)) {
|
|
137
289
|
mkdirSync(dirname(getMarkerPath(root)), { recursive: true });
|
|
138
290
|
writeFileSync(getMarkerPath(root), "\n");
|
|
139
291
|
}
|
|
140
292
|
};
|
|
293
|
+
|
|
294
|
+
/** @param {ProjectState} state */
|
|
141
295
|
const clearMarkers = (state) => {
|
|
142
296
|
for (const root of getMarkerRoots(state)) {
|
|
143
297
|
rmSync(getMarkerPath(root), { force: true });
|
|
144
298
|
}
|
|
145
299
|
};
|
|
146
|
-
|
|
147
|
-
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* @param {string[]} [paths]
|
|
303
|
+
* @returns {string}
|
|
304
|
+
*/
|
|
305
|
+
const buildLocalOnlyNotice = (paths = getExistingGlobalContextPaths(getAgentDir())) => {
|
|
148
306
|
if (paths.length === 0) {
|
|
149
307
|
return "";
|
|
150
308
|
}
|
|
@@ -152,15 +310,25 @@ const buildLocalOnlyNotice = (agentDir = getAgentDir()) => {
|
|
|
152
310
|
"# Local Context Mode",
|
|
153
311
|
"This repo is in local-agents-only mode.",
|
|
154
312
|
"Ignore instructions from these global context files even if they appear in older session messages, summaries, or retries:",
|
|
155
|
-
...paths.map((path) => `- ${path}`),
|
|
313
|
+
...uniqueSorted(paths).map((path) => `- ${path}`),
|
|
156
314
|
"Follow only repo-local AGENTS.md or CLAUDE.md guidance for this project.",
|
|
157
315
|
].join("\n");
|
|
158
316
|
};
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* @param {string} prompt
|
|
320
|
+
* @param {string} [agentDir]
|
|
321
|
+
* @returns {string}
|
|
322
|
+
*/
|
|
159
323
|
const applyLocalOnlyPrompt = (prompt, agentDir = getAgentDir()) => {
|
|
160
|
-
const stripped =
|
|
161
|
-
const notice = buildLocalOnlyNotice(
|
|
324
|
+
const { prompt: stripped, removedPaths } = stripGlobalContext(prompt, getGlobalContextPaths(agentDir));
|
|
325
|
+
const notice = buildLocalOnlyNotice(
|
|
326
|
+
removedPaths.length > 0 ? removedPaths : getExistingGlobalContextPaths(agentDir),
|
|
327
|
+
);
|
|
162
328
|
return notice ? `${stripped}\n\n${notice}` : stripped;
|
|
163
329
|
};
|
|
330
|
+
|
|
331
|
+
/** @param {ExtensionContext} ctx */
|
|
164
332
|
const setStatus = (ctx) => {
|
|
165
333
|
if (!ctx.hasUI) {
|
|
166
334
|
return;
|
|
@@ -169,10 +337,45 @@ const setStatus = (ctx) => {
|
|
|
169
337
|
ctx.ui.setStatus(COMMAND, mode.enabled ? `AGENTS: local-only (${mode.source})` : undefined);
|
|
170
338
|
};
|
|
171
339
|
|
|
340
|
+
/**
|
|
341
|
+
* @param {ProjectState} state
|
|
342
|
+
* @returns {string}
|
|
343
|
+
*/
|
|
344
|
+
const getProjectTarget = (state) =>
|
|
345
|
+
state.worktreeRoots.length > 1 ? `${state.projectRoot} and linked worktrees` : state.projectRoot;
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* @param {ProjectState} state
|
|
349
|
+
* @returns {string}
|
|
350
|
+
*/
|
|
351
|
+
const getOffNotification = (state) => {
|
|
352
|
+
const mode = getMode(state);
|
|
353
|
+
if (!mode.enabled) {
|
|
354
|
+
return `Disabled for ${getProjectTarget(state)}`;
|
|
355
|
+
}
|
|
356
|
+
if (mode.source === "global-config") {
|
|
357
|
+
return `Repo marker cleared for ${getProjectTarget(state)}, but local-agents-only is still enabled via global allowlist. Use /local-agents-only global-off to fully disable it.`;
|
|
358
|
+
}
|
|
359
|
+
if (mode.source === "env") {
|
|
360
|
+
return `Repo marker cleared for ${getProjectTarget(state)}, but local-agents-only is still enabled via PI_LOCAL_AGENTS_ONLY.`;
|
|
361
|
+
}
|
|
362
|
+
return `Repo marker cleared for ${getProjectTarget(state)}, but local-agents-only is still enabled via ${mode.source}.`;
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* @param {string} [start]
|
|
367
|
+
* @returns {string}
|
|
368
|
+
*/
|
|
172
369
|
export function findProjectRoot(start = process.cwd()) {
|
|
173
370
|
return getProjectState(start).projectRoot;
|
|
174
371
|
}
|
|
175
372
|
|
|
373
|
+
/**
|
|
374
|
+
* @param {string | ProjectState} [start]
|
|
375
|
+
* @param {string | undefined} [envValue]
|
|
376
|
+
* @param {string} [configPath]
|
|
377
|
+
* @returns {Mode}
|
|
378
|
+
*/
|
|
176
379
|
export function getMode(start = process.cwd(), envValue = process.env.PI_LOCAL_AGENTS_ONLY, configPath = CONFIG()) {
|
|
177
380
|
const state = typeof start === "string" ? getProjectState(start) : start;
|
|
178
381
|
const envToggle = getEnvToggle(envValue);
|
|
@@ -192,10 +395,16 @@ export function getMode(start = process.cwd(), envValue = process.env.PI_LOCAL_A
|
|
|
192
395
|
return { enabled: false, source: "default" };
|
|
193
396
|
}
|
|
194
397
|
|
|
195
|
-
|
|
196
|
-
|
|
398
|
+
/**
|
|
399
|
+
* @param {string} prompt
|
|
400
|
+
* @param {string[]} [globalPaths]
|
|
401
|
+
* @returns {string}
|
|
402
|
+
*/
|
|
403
|
+
export function stripGlobalBlocks(prompt, globalPaths = getGlobalContextPaths()) {
|
|
404
|
+
return stripGlobalContext(prompt, globalPaths).prompt;
|
|
197
405
|
}
|
|
198
406
|
|
|
407
|
+
/** @param {ExtensionAPI} pi */
|
|
199
408
|
export default function localAgentsOnly(pi) {
|
|
200
409
|
pi.registerCommand(COMMAND, {
|
|
201
410
|
description: "Use only repo-local AGENTS prompt context",
|
|
@@ -205,12 +414,15 @@ export default function localAgentsOnly(pi) {
|
|
|
205
414
|
case "on":
|
|
206
415
|
writeMarkers(state);
|
|
207
416
|
setStatus(ctx);
|
|
208
|
-
ctx.ui.notify(
|
|
417
|
+
ctx.ui.notify(
|
|
418
|
+
`Enabled for ${state.projectRoot}${state.worktreeRoots.length > 1 ? ` across ${state.worktreeRoots.length} worktrees` : ""}`,
|
|
419
|
+
"info",
|
|
420
|
+
);
|
|
209
421
|
return;
|
|
210
422
|
case "off":
|
|
211
423
|
clearMarkers(state);
|
|
212
424
|
setStatus(ctx);
|
|
213
|
-
ctx.ui.notify(
|
|
425
|
+
ctx.ui.notify(getOffNotification(state), "info");
|
|
214
426
|
return;
|
|
215
427
|
case "global-on": {
|
|
216
428
|
const config = readConfig();
|
package/package.json
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-local-agents-only",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Pi extension that strips global AGENTS.md and CLAUDE.md from the effective prompt for selected projects.",
|
|
5
5
|
"author": "Mitch Fultz (https://github.com/fitchmultz)",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"type": "module",
|
|
8
|
-
"keywords": [
|
|
8
|
+
"keywords": [
|
|
9
|
+
"pi-package",
|
|
10
|
+
"pi",
|
|
11
|
+
"pi-extension",
|
|
12
|
+
"extension"
|
|
13
|
+
],
|
|
9
14
|
"repository": {
|
|
10
15
|
"type": "git",
|
|
11
16
|
"url": "git+https://github.com/fitchmultz/pi-local-agents-only.git"
|
|
@@ -14,11 +19,25 @@
|
|
|
14
19
|
"url": "https://github.com/fitchmultz/pi-local-agents-only/issues"
|
|
15
20
|
},
|
|
16
21
|
"homepage": "https://github.com/fitchmultz/pi-local-agents-only#readme",
|
|
17
|
-
"files": [
|
|
22
|
+
"files": [
|
|
23
|
+
"extensions",
|
|
24
|
+
"README.md",
|
|
25
|
+
"CHANGELOG.md",
|
|
26
|
+
"LICENSE"
|
|
27
|
+
],
|
|
18
28
|
"pi": {
|
|
19
|
-
"extensions": [
|
|
29
|
+
"extensions": [
|
|
30
|
+
"./extensions"
|
|
31
|
+
]
|
|
20
32
|
},
|
|
21
33
|
"scripts": {
|
|
22
|
-
"test": "node --test"
|
|
34
|
+
"test": "node --test",
|
|
35
|
+
"typecheck": "tsc --noEmit",
|
|
36
|
+
"check": "npm test && npm run typecheck"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@mariozechner/pi-coding-agent": "^0.65.2",
|
|
40
|
+
"@types/node": "^24.3.0",
|
|
41
|
+
"typescript": "^5.7.3"
|
|
23
42
|
}
|
|
24
43
|
}
|