@lincoln504/pi-research 1.5.2 → 1.5.3

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
@@ -37,7 +37,7 @@ As a [Pi](https://github.com/earendil-works/pi) Coding Agent extension:
37
37
  pi install npm:@lincoln504/pi-research
38
38
  ```
39
39
 
40
- Standalone, as an [agent skill](docs/AGENT-SKILL.md) for Claude Code, Codex, and OpenClaw:
40
+ Standalone, as an [agent skill](docs/AGENT-SKILL.md) for Claude Code, Codex, and other skills-compatible agents:
41
41
 
42
42
  ```bash
43
43
  npm install -g @lincoln504/pi-research
@@ -57,7 +57,7 @@ Three depth levels (normal, deep, ultra) set the team size and number of rounds.
57
57
  ### Use cases
58
58
 
59
59
  - Researching for your pi. Plug and play with no API key needed.
60
- - Researching from Claude Code, Codex, OpenClaw, or another coding agent while a cheaper or local model drives the run so it doesn't spend your main agent's budget.
60
+ - Researching from Claude Code, Codex, or another coding agent while a cheaper or local model drives the run so it doesn't spend your main agent's budget.
61
61
  - Keeping a persistent and searchable knowledge store of findings, scoped globally or per project.
62
62
  - Building agent systems that find and read web content or populating a dataset of web sources.
63
63
 
@@ -3,8 +3,8 @@
3
3
  A portable [Agent Skill](https://agentskills.io/specification) that gives any
4
4
  coding agent multi-agent web research by driving the
5
5
  [pi-research](https://github.com/Lincoln504/pi-research) engine. It is the same
6
- engine the `pi` extension uses, packaged as a skill so Claude, Cursor,
7
- Codex, OpenClaw, and other Agent-Skills-compatible tools can use it.
6
+ engine the `pi` extension uses, packaged as a skill so Claude, Codex, and other
7
+ Agent-Skills-compatible tools can use it.
8
8
 
9
9
  ### What it exposes
10
10
 
@@ -50,9 +50,9 @@ node "<skill_dir>/scripts/run.mjs" status # verify detection
50
50
  ### Install the skill
51
51
 
52
52
  Recommended. From the pi extension, run `/research-config` and choose
53
- Install in External Agents. It detects Claude, Codex, and OpenClaw and
54
- symlinks this skill into each one that is installed. Remove from External Agents
55
- removes those symlinks.
53
+ Install in External Agents. It detects the supported agents set up on this machine
54
+ and symlinks this skill into each one. Remove from External Agents removes those
55
+ symlinks.
56
56
 
57
57
  Uninstalling the npm package does **not** remove them: npm 7 and newer do not run a
58
58
  package's own `preuninstall` script (verified against npm 11). Use Remove from
@@ -60,9 +60,6 @@ External Agents first, or run `node scripts/cleanup.cjs` from the package direct
60
60
  otherwise the symlinks, `~/.pi/research/state` and the `~/.cache/pi-research` model
61
61
  cache are all left behind.
62
62
 
63
- Cursor is not auto-installed — it has no global skills directory and only reads
64
- project-level `.cursor/skills/`. Symlink it per-project instead (see the table).
65
-
66
63
  Manual. Or symlink this `pi-research/` directory into your agent's skills folder:
67
64
 
68
65
  | Agent | Location |
@@ -71,7 +68,6 @@ Manual. Or symlink this `pi-research/` directory into your agent's skills folder
71
68
  | Claude (project) | `<project>/.claude/skills/pi-research/` |
72
69
  | Codex CLI (personal) | `~/.codex/skills/pi-research/` |
73
70
  | Codex CLI (project) | `<project>/.codex/skills/pi-research/` |
74
- | Cursor (project-only) | `<project>/.cursor/skills/pi-research/` |
75
71
  | OpenClaw (personal) | `~/.openclaw/skills/pi-research/` |
76
72
 
77
73
  Then ask your agent to pi-research something — its skill system matches the
@@ -2,15 +2,16 @@
2
2
  name: pi-research
3
3
  description: "Multi-agent web research for any coding agent. Use for anything requiring current information from the internet — news, trends, product/service/company facts, statistics, people, places, events, APIs, library behavior, or 'what is X / how does X work' questions. Also use to search a local knowledge store of previously researched findings before doing live research. Powered by the pi-research engine (search, stealth scraping, security databases, Stack Exchange). Not for reading local files, running project commands, or analyzing this repository's own source."
4
4
  license: MIT
5
- metadata: { "author": "Lincoln Deen", "version": "1.5.2", "package": "@lincoln504/pi-research", "engine": "pi-research-sdk", "openclaw": { "requires": { "bins": ["node"] } } }
5
+ metadata: { "author": "Lincoln Deen", "version": "1.5.3", "package": "@lincoln504/pi-research", "engine": "pi-research-sdk", "openclaw": { "requires": { "bins": ["node"] } } }
6
6
  allowed-tools: Bash(node:*)
7
7
  ---
8
8
 
9
9
  # pi-research skill
10
10
 
11
- Run via your shell tool — the **Bash** tool in Claude Code, the **`exec`** tool in
12
- OpenClaw. `<SKILL_DIR>` is this skill's own directory: substitute the absolute path
13
- your harness reports for this skill (in OpenClaw, `{baseDir}` resolves to it).
11
+ Run via your shell tool — the **Bash** tool in Claude Code, whatever equivalent
12
+ your harness exposes elsewhere. `<SKILL_DIR>` is this skill's own directory:
13
+ substitute the absolute path your harness reports for this skill (some harnesses
14
+ expose it as `{baseDir}`).
14
15
 
15
16
  ```
16
17
  node "<SKILL_DIR>/scripts/run.mjs" research "<query>" --depth 1
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- // skills/pi-research/scripts/run.ts
3
+ // agent-skill/pi-research/scripts/run.ts
4
4
  import { spawn } from "node:child_process";
5
5
  import { existsSync, readFileSync } from "node:fs";
6
6
  import { homedir, constants as osConstants } from "node:os";
package/dist/cli.mjs CHANGED
@@ -10157,7 +10157,8 @@ function resolveSkillSourceDir(explicit) {
10157
10157
  if (!start) continue;
10158
10158
  let dir = start;
10159
10159
  for (let i = 0; i < 8; i++) {
10160
- candidates.push(path18.join(dir, "skills", SKILL_NAME));
10160
+ candidates.push(path18.join(dir, SKILL_SOURCE_DIR, SKILL_NAME));
10161
+ candidates.push(path18.join(dir, LEGACY_SKILL_SOURCE_DIR, SKILL_NAME));
10161
10162
  const parent = path18.dirname(dir);
10162
10163
  if (parent === dir) break;
10163
10164
  dir = parent;
@@ -10169,7 +10170,7 @@ function resolveSkillSourceDir(explicit) {
10169
10170
  } catch {
10170
10171
  }
10171
10172
  }
10172
- throw new Error("Could not locate the bundled research skill (skills/pi-research/SKILL.md). Set PI_RESEARCH_SKILL_DIR to its path.");
10173
+ throw new Error("Could not locate the bundled research skill (agent-skill/pi-research/SKILL.md). Set PI_RESEARCH_SKILL_DIR to its path.");
10173
10174
  }
10174
10175
  function getManifestPath(opts) {
10175
10176
  return path18.join(homeDir(opts), ".pi", "research", "installed-skills.json");
@@ -10213,7 +10214,7 @@ function isOwnedSymlink(targetPath, expectedSource) {
10213
10214
  if (!st.isSymbolicLink()) return false;
10214
10215
  const dest = path18.resolve(path18.dirname(targetPath), fs16.readlinkSync(targetPath));
10215
10216
  if (expectedSource && path18.resolve(expectedSource) === dest) return true;
10216
- return /[/\\]pi-research[/\\]skills[/\\]pi-research$/.test(dest);
10217
+ return OWNED_SYMLINK_DEST.test(dest);
10217
10218
  } catch {
10218
10219
  return false;
10219
10220
  }
@@ -10564,20 +10565,28 @@ function copyDir(src, dest) {
10564
10565
  fs16.copyFileSync(src, dest);
10565
10566
  }
10566
10567
  }
10567
- var HARNESSES, SKILL_NAME, PACKAGE_NAME, SKILL_AGENT_TARGETS, manifestTmpSeq, isTarget;
10568
+ var HARNESSES, SKILL_NAME, PACKAGE_NAME, SKILL_SOURCE_DIR, LEGACY_SKILL_SOURCE_DIR, OWNED_SYMLINK_DEST, SKILL_AGENT_TARGETS, manifestTmpSeq, isTarget;
10568
10569
  var init_skill_installer = __esm({
10569
10570
  "src/skill-install/skill-installer.ts"() {
10570
10571
  "use strict";
10571
10572
  HARNESSES = [
10572
10573
  { id: "claude", label: "Claude", baseDir: ".claude", skillsDir: path18.join(".claude", "skills"), confidence: "confirmed" },
10573
10574
  { id: "openclaw", label: "OpenClaw", baseDir: ".openclaw", skillsDir: path18.join(".openclaw", "skills"), confidence: "confirmed", note: "OpenClaw reads ~/.openclaw/skills as a managed skill root and accepts symlinked skill folders (docs.openclaw.ai/tools/skills)." },
10574
- { id: "pi", label: "pi", baseDir: ".pi", skillsDir: path18.join(".pi", "skills"), confidence: "confirmed" },
10575
- { id: "cursor", label: "Cursor", baseDir: ".cursor", skillsDir: path18.join(".cursor", "skills"), confidence: "partial", note: "Cursor project-level skills are documented; the global ~/.cursor/skills path is community-reported." },
10575
+ // pi's own skill root is under its agent dir (~/.pi/agent/skills), NOT ~/.pi/skills.
10576
+ // Listed for DETECTION only — pi is never an install target (see SKILL_AGENT_TARGETS):
10577
+ // the host already exposes research as a native tool, so a skill there would just
10578
+ // duplicate it through a slower subprocess.
10579
+ { id: "pi", label: "pi", baseDir: ".pi", skillsDir: path18.join(".pi", "agent", "skills"), confidence: "confirmed" },
10576
10580
  { id: "codex", label: "OpenAI Codex CLI", baseDir: ".codex", skillsDir: path18.join(".codex", "skills"), confidence: "unverified", note: "Codex skills support is emerging; path not confirmed by official docs." },
10577
10581
  { id: "agents", label: "Cross-tool (~/.agents/skills)", baseDir: ".agents", skillsDir: path18.join(".agents", "skills"), confidence: "unverified", note: "Proposed Universal Agents convention; not yet a ratified standard." }
10578
10582
  ];
10579
10583
  SKILL_NAME = "pi-research";
10580
10584
  PACKAGE_NAME = "@lincoln504/pi-research";
10585
+ SKILL_SOURCE_DIR = "agent-skill";
10586
+ LEGACY_SKILL_SOURCE_DIR = "skills";
10587
+ OWNED_SYMLINK_DEST = new RegExp(
10588
+ `[/\\\\]${SKILL_NAME}[/\\\\](?:${SKILL_SOURCE_DIR}|${LEGACY_SKILL_SOURCE_DIR})[/\\\\]${SKILL_NAME}$`
10589
+ );
10581
10590
  SKILL_AGENT_TARGETS = ["claude", "codex", "openclaw"];
10582
10591
  manifestTmpSeq = 0;
10583
10592
  isTarget = (id) => SKILL_AGENT_TARGETS.includes(id);
@@ -1,9 +1,9 @@
1
1
  ## Agent Skill
2
2
 
3
3
  pi-research ships as a portable [Agent Skill](https://agentskills.io/specification)
4
- so any skills-compatible coding agent (Claude, OpenAI Codex CLI, OpenClaw, and
5
- others using the same `SKILL.md` directory model) can run web research through the
6
- pi-research software.
4
+ so any skills-compatible coding agent using the same `SKILL.md` directory model —
5
+ Claude, OpenAI Codex CLI and others — can run web research through the pi-research
6
+ software.
7
7
 
8
8
  ### Install
9
9
 
@@ -18,7 +18,7 @@ every coding agent detected on this machine:
18
18
 
19
19
  ```bash
20
20
  npm install -g @lincoln504/pi-research # the engine (puts `pi-research` on PATH)
21
- pi-research skill install # link the skill into Claude, Codex, OpenClaw
21
+ pi-research skill install # link the skill into every detected agent
22
22
  ```
23
23
 
24
24
  `skill install` targets only agents already set up under `$HOME`, never overwrites a
@@ -49,7 +49,7 @@ disabled"); or run `Set-ExecutionPolicy -Scope CurrentUser RemoteSigned` once.
49
49
  agent
50
50
  │ shells out (Bash / exec)
51
51
  ▼
52
- run.mjs — zero-dep launcher (skills/pi-research/scripts/)
52
+ run.mjs — zero-dep launcher (agent-skill/pi-research/scripts/)
53
53
  │ locates the installed engine, or fails fast with guidance
54
54
  ▼
55
55
  pi-research engine — the CLI (dist/cli.mjs)
@@ -70,19 +70,23 @@ is missing. It exposes four subcommands: `research "<query>"` (live research),
70
70
 
71
71
  ### Installation flow
72
72
 
73
- The skill source lives at `skills/pi-research/` inside the package. Installing means
74
- linking that directory into each agent's skills folder.
73
+ The skill source lives at `agent-skill/pi-research/` inside the package. Installing
74
+ means linking that directory into each agent's skills folder.
75
+
76
+ > The directory is deliberately **not** named `skills/`: `pi` treats a package-root
77
+ > `skills/` directory as one of its own resource roots and will load what it finds
78
+ > there, which would shadow the extension's native research tool with a slower
79
+ > subprocess copy of itself.
75
80
 
76
81
  One-click (recommended). From the `pi` extension, run `/research-config` →
77
82
  Install in External Agents. The installer:
78
83
 
79
84
  1. Detects which target agents are present under `$HOME` — currently Claude
80
- (`~/.claude/skills`), OpenClaw (`~/.openclaw/skills`, OpenClaw's managed
81
- skill root, which accepts symlinked skill folders), and OpenAI Codex CLI
82
- (`~/.codex/skills` — unlike the other two, this path is not confirmed by
83
- Codex's official docs; Codex skills support is still emerging).
84
- 2. Symlinks `skills/pi-research/` into each present agent, never overwriting an
85
- unrelated skill already in that slot.
85
+ (`~/.claude/skills`), OpenAI Codex CLI (`~/.codex/skills` — this path is not
86
+ confirmed by Codex's official docs; Codex skills support is still emerging)
87
+ and OpenClaw (`~/.openclaw/skills`).
88
+ 2. Symlinks `agent-skill/pi-research/` into each present agent, never overwriting
89
+ an unrelated skill already in that slot.
86
90
  3. Records what it created in a manifest, so Remove from External Agents
87
91
  removes only its own links. Stale links are also garbage-collected on startup.
88
92
 
@@ -99,29 +103,12 @@ do exactly the same from the CLI — same agent detection, same manifest, same
99
103
  never-clobber-a-foreign-skill guarantee — for people who installed the engine with
100
104
  `npm install -g` and never open the interactive extension.
101
105
 
102
- **OpenClaw without `pi`**
103
-
104
- If you run OpenClaw but not the `pi` extension, register the skill with OpenClaw's
105
- own CLI after installing the engine — OpenClaw copies the `SKILL.md` folder into its
106
- managed skill root and reads it on the next session:
107
-
108
- ```bash
109
- npm install -g @lincoln504/pi-research
110
- openclaw skills install "$(npm root -g)/@lincoln504/pi-research/skills/pi-research" --global
111
- ```
112
-
113
- OpenClaw drives the skill through its `exec` tool, gated on `node` being on `PATH`
114
- (`metadata.openclaw.requires.bins`). A bare `openclaw skills install git:…` is *not*
115
- used here: OpenClaw expects `SKILL.md` at a repo root, whereas this package nests it
116
- under `skills/pi-research/` — install the engine from npm and point OpenClaw at that
117
- folder, as above.
118
-
119
- Cursor is intentionally excluded from the one-click flow — it has no global skills
120
- directory and reads only project-level `.cursor/skills/`. Link it per project:
121
-
122
- ```bash
123
- ln -s "$(npm root -g)/@lincoln504/pi-research/skills/pi-research" .cursor/skills/pi-research
124
- ```
106
+ An agent with its own skill-registration CLI can be pointed at the shipped folder
107
+ instead of symlinking it. Install the engine, then register
108
+ `$(npm root -g)/@lincoln504/pi-research/agent-skill/pi-research` with that agent —
109
+ it holds `SKILL.md` at its root, which is the layout such tools expect. Agents that
110
+ copy rather than link pick up engine upgrades on the next `skill install`, not
111
+ automatically.
125
112
 
126
113
  Manual. Symlink the directory into any agent's skills folder yourself:
127
114
 
@@ -130,7 +117,6 @@ Manual. Symlink the directory into any agent's skills folder yourself:
130
117
  | Claude | `~/.claude/skills/pi-research/` | `<project>/.claude/skills/pi-research/` |
131
118
  | OpenAI Codex CLI | `~/.codex/skills/pi-research/` | `<project>/.codex/skills/pi-research/` |
132
119
  | OpenClaw | `~/.openclaw/skills/pi-research/` | `<workspace>/skills/pi-research/` |
133
- | Cursor | — (no global dir) | `<project>/.cursor/skills/pi-research/` |
134
120
 
135
121
  ### Prerequisites
136
122
 
@@ -146,6 +132,6 @@ node "<skill_dir>/scripts/run.mjs" status # verify the engine is detected
146
132
  ![One-command health and readiness check](https://raw.githubusercontent.com/Lincoln504/pi-research/main/docs/media/06-health-check.gif)
147
133
 
148
134
  Once installed, ask the agent to research something — its skill system activates
149
- pi-research automatically. The in-package readme (`skills/pi-research/README.md`) and
150
- `skills/pi-research/references/configuration.md` carry the same detail for anyone
151
- browsing the skill directly.
135
+ pi-research automatically. The in-package readme (`agent-skill/pi-research/README.md`)
136
+ and `agent-skill/pi-research/references/configuration.md` carry the same detail for
137
+ anyone browsing the skill directly.
@@ -4,7 +4,7 @@ pi-research is a pi TUI extension for multi-agent web research. It runs inside t
4
4
  process, registers its tools and commands, and manages its own browser worker pool,
5
5
  service registry, and local knowledge store. One engine backs every front-end: besides
6
6
  the pi extension it is exposed as a standalone CLI, a portable agent skill (the same
7
- skill any skills-aware host runs, including OpenClaw) and a programmatic SDK
7
+ skill any skills-aware host runs) and a programmatic SDK
8
8
  (`src/sdk.ts`).
9
9
 
10
10
  ```
package/docs/CHANGELOG.md CHANGED
@@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.5.3] - 2026-08-22
9
+
10
+ ### Fixed
11
+
12
+ - **The shipped agent skill moved from `skills/` to `agent-skill/` inside the package, so `pi` can no longer load it as one of its own agent skills.** `pi` reserves four package-root resource directory names (`extensions`, `skills`, `prompts`, `themes`) and convention-scans any of them a package's `pi` manifest does not explicitly declare. This package declares `extensions` only, so its root-level `skills/` was scanned and `SKILL.md` registered as a pi agent skill — a slower subprocess duplicate of the extension's own native `research` tool, plus a redundant `/skill:pi-research` command. Nothing fired on a plain install, a plain update, or `npm install`ing the package into a project (pi never scans project `node_modules`, and a settings entry written as a plain string takes the manifest-only path). The trap was `pi config`: toggling **any** pi-research resource rewrites the settings entry from a string into an object, after which pi resolves each resource type separately and falls back to the convention scan for the undeclared `skills` — permanently, since the TUI's revert-to-string branch is unreachable, and irrespective of whether the toggle *enabled* or *disabled* the extension. Renaming the directory removes the scanned path entirely, which needs no `pi.skills` manifest key and so cannot mislabel the package as a skill provider in the pi.dev gallery (`agent-skill/`, `package.json`).
13
+ - **Ownership detection now recognises both the current and the pre-1.5.3 skill source directories, so existing installs survive the move.** Installed links are symlinks into the package, and three of the four ownership call sites pass no expected source — they match the link destination's shape instead. Accepting only the new name would have stranded every link created before this release (reconcile refusing to re-point it, uninstall refusing to remove it, `skill status` reporting a foreign skill); accepting only the legacy name would have made each link unmanageable the moment it was successfully re-pointed, a failure that looks like a clean migration until the *next* upgrade. `reconcileSkillInstalls` runs on every CLI invocation and every extension activation, so a pre-1.5.3 link is re-pointed automatically with no user action. Both failure directions are pinned by a new regression suite, and the false-positive guard for lookalike paths (`…/pi-researcher/…`) is retained (`src/skill-install/skill-installer.ts`, `scripts/cleanup.cjs`, `test/unit/skill-install/legacy-source-dir-migration.test.ts`).
14
+ - The installer's `pi` harness entry pointed at `~/.pi/skills`, but pi's skill root is `~/.pi/agent/skills` — the entry had never matched anything. Corrected to the real path. It remains detection-only and is deliberately not an install target: pi already exposes research natively, so a skill there would only add a slower duplicate (`src/skill-install/skill-installer.ts`).
15
+
16
+ ### Changed
17
+
18
+ - **Cursor is no longer documented or defined as a harness.** It was never an install target — it exposes no personal/global skills directory, so the one-click flow could not serve it — and its only presence was manual per-project symlink instructions plus an unused entry in the harness table. Nothing installed to it, so there is no behavioural change (`src/skill-install/skill-installer.ts`, `docs/AGENT-SKILL.md`, `agent-skill/pi-research/README.md`).
19
+ - **OpenClaw is de-emphasised throughout the documentation**, becoming one supported agent among others rather than a separately-branded integration: its dedicated install section, per-harness prose and README callouts are gone, and it now appears only where the supported-agent set is enumerated factually. Support is unchanged — it remains a first-class install target with its `SKILL.md` preflight metadata intact, and existing installs are untouched. (Removing it from the target list was considered and rejected: uninstall and status are both target-filtered, so a formerly-supported harness would have become permanently unremovable through any user-facing command while reconcile kept maintaining the orphan.) The generic copy-install route it used is still documented, without naming a specific agent (`README.md`, `docs/`, `agent-skill/pi-research/`).
20
+ - **npm `keywords` trimmed from 25 to 13**, dropping the entries that blurred what pi actually loads from this package (`skills`, `agent-skills`, plus generic SEO filler: `ai-research`, `research`, `scraping`, `browser-automation`, `stealth-browser`, `camoufox`, `duckduckgo`, `llm-tools`, `web-access`, `agent`). Retained: the pi-ecosystem flags (`pi`, `pi-package` — load-bearing for pi.dev gallery inclusion — `pi-extension`, `pi-coding-agent`), the harnesses the standalone skill genuinely targets (`agent-skill`, `claude-code`, `codex`, `openclaw`), and the core function words (`web-research`, `deep-research`, `web-search`, `web-scraping`, `knowledge-store`). Cosmetic only: pi never reads npm keywords — resource loading is driven entirely by the `pi` manifest keys, and the pi.dev type chips derive from those same keys (`package.json`).
21
+
8
22
  ## [1.5.2] - 2026-08-22
9
23
 
10
24
  ### Fixed
@@ -1,6 +1,6 @@
1
1
  ## Configuration
2
2
 
3
- Every front-end (the pi extension, the standalone CLI / agent skill that OpenClaw
3
+ Every front-end (the pi extension, the standalone CLI / agent skill that Claude Code
4
4
  and other skills-aware hosts run, and the SDK) shares one configuration
5
5
  model. This document covers the
6
6
  settings exposed in the `/research-config` TUI first, then the complete
@@ -159,7 +159,7 @@ Diagnostics & platform
159
159
  | `CAMOUFOX_INSTALL_DIR` | _(user cache)_ | camoufox-js's own variable, and the only one that can relocate the browser. Sets where pi-research looks the binary up, and is exported to the postinstall fetch and to browser workers. **Not effective on the currently pinned camoufox-js (0.10.x), which hardcodes its cache directory and honours no variable** — so relocating the browser is unsupported until that pin can advance (see ARCHITECTURE.md). |
160
160
  | `PLAYWRIGHT_BROWSERS_PATH` | _(user cache)_ | Alias for the above, accepted for compatibility and exported onward as `CAMOUFOX_INSTALL_DIR`. Same caveat: on the pinned camoufox-js it moves only where pi-research looks, not where the download lands, so setting it reports the browser missing from the custom path after a successful install. |
161
161
  | `XDG_CACHE_HOME` | `~/.cache` | Standard XDG variable. When set, every `~/.cache/pi-research/...` path below is rooted at `$XDG_CACHE_HOME/pi-research/...` instead. |
162
- | `PI_RESEARCH_BIN` (alias `PI_RESEARCH_PATH`) | _(auto)_ | Agent-skill launcher only: explicit path to the pi-research engine binary when auto-resolution (PATH → local install → npx) should be bypassed. See [skills/pi-research/references/configuration.md](../skills/pi-research/references/configuration.md). |
162
+ | `PI_RESEARCH_BIN` (alias `PI_RESEARCH_PATH`) | _(auto)_ | Agent-skill launcher only: explicit path to the pi-research engine binary when auto-resolution (PATH → local install → npx) should be bypassed. See [agent-skill/pi-research/references/configuration.md](../agent-skill/pi-research/references/configuration.md). |
163
163
  | `PLAYWRIGHT_INSTALL_DEPS` | _(unset)_ | Linux only. Set `true` during `npm install` to also install system libraries via `npx playwright install-deps` (same as `npm run install:system-deps`). |
164
164
  | `PI_RESEARCH_STRICT_SETUP` | _(unset)_ | Read by the bundled `scripts/setup.cjs` during `npm install`. Set `1`/`true` to make a failed browser download fail the install instead of deferring it to first use. |
165
165
  | `PI_RESEARCH_CONFIG_DIR_NAME` | `.pi` | Override the host config-directory name under your home dir (advanced; e.g. set to share another harness's config root). |
@@ -196,8 +196,8 @@ layered over the shared base, so they can be configured independently. Exactly t
196
196
  exist:
197
197
 
198
198
  - `~/.pi/research/pi.env` — the pi extension
199
- - `~/.pi/research/cli.env` — the standalone CLI / agent skill (the surface OpenClaw
200
- and other skills-aware hosts run)
199
+ - `~/.pi/research/cli.env` — the standalone CLI / agent skill (the surface
200
+ skills-aware hosts run)
201
201
 
202
202
  The overlay files do not exist by default; create the one you need by hand. There is
203
203
  intentionally no `sdk.env`: the SDK is a library configured from code (see
@@ -78,7 +78,7 @@ environment-variable list live in [CONFIGURATION.md](CONFIGURATION.md).
78
78
  ### Coding-agent skill installer
79
79
 
80
80
  The `/research-config` menu can install the `pi-research` skill into your other
81
- coding agents (Claude, Codex, OpenClaw) so they can run web research through the
81
+ coding agents detected on this machine so they can run web research through the
82
82
  CLI, and remove it again — with exact, manifest-tracked cleanup. See
83
83
  [AGENT-SKILL.md](AGENT-SKILL.md) for the full installation flow.
84
84
 
package/docs/SDK.md CHANGED
@@ -141,7 +141,7 @@ exit code is the part you can rely on.
141
141
 
142
142
  Treat any code ≥ 128 as a cancellation; `pi-research --help` lists the full set, and
143
143
  the agent-facing contract is the exit-code table in
144
- [`SKILL.md`](../skills/pi-research/SKILL.md).
144
+ [`SKILL.md`](../agent-skill/pi-research/SKILL.md).
145
145
 
146
146
  These are deliberately not the `70` runtime-error code and never carry
147
147
  `retryable: true` — a cancel is a completed intention, not a fault to retry. The
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lincoln504/pi-research",
3
- "version": "1.5.2",
3
+ "version": "1.5.3",
4
4
  "description": "Web research for your agents with smart and safe tooling + knowledge store",
5
5
  "type": "module",
6
6
  "private": false,
@@ -20,8 +20,8 @@
20
20
  "dist/thread-worker.mjs",
21
21
  "dist/webgpu-probe.mjs",
22
22
  "dist/prompts/",
23
- "skills/",
24
- "!skills/pi-research/scripts/run.ts",
23
+ "agent-skill/",
24
+ "!agent-skill/pi-research/scripts/run.ts",
25
25
  "!src/.env",
26
26
  "!src/.env.local",
27
27
  "!src/.env.*.local",
@@ -53,27 +53,15 @@
53
53
  "pi-package",
54
54
  "pi-extension",
55
55
  "pi-coding-agent",
56
+ "agent-skill",
56
57
  "claude-code",
57
- "openclaw",
58
58
  "codex",
59
- "agent-skills",
60
- "agent-skill",
61
- "skills",
62
- "web-search",
59
+ "openclaw",
63
60
  "web-research",
64
61
  "deep-research",
65
- "ai-research",
66
- "research",
62
+ "web-search",
67
63
  "web-scraping",
68
- "scraping",
69
- "browser-automation",
70
- "stealth-browser",
71
- "camoufox",
72
- "duckduckgo",
73
- "knowledge-store",
74
- "llm-tools",
75
- "web-access",
76
- "agent"
64
+ "knowledge-store"
77
65
  ],
78
66
  "author": "Lincoln Deen",
79
67
  "contributors": [
@@ -105,7 +93,7 @@
105
93
  "build": "node scripts/build.cjs all",
106
94
  "prepublishOnly": "node scripts/build.cjs all && node scripts/verify-package.cjs manifest",
107
95
  "prepare": "node scripts/prepare.cjs",
108
- "version": "node scripts/sync-skill-version.cjs && git add skills/pi-research/SKILL.md",
96
+ "version": "node scripts/sync-skill-version.cjs && git add agent-skill/pi-research/SKILL.md",
109
97
  "postinstall": "node scripts/setup.cjs",
110
98
  "preuninstall": "node scripts/cleanup.cjs",
111
99
  "cleanup": "node scripts/cleanup.cjs",
package/scripts/build.cjs CHANGED
@@ -12,7 +12,7 @@
12
12
  * Targets (dispatch by argv, or build all when no/`all` arg):
13
13
  * worker -> src/infrastructure/browser/thread-worker.mjs (browser worker)
14
14
  * cli -> dist/cli.mjs (+ dist/prompts, dist/thread-worker.mjs, dist/webgpu-probe.mjs)
15
- * skill -> skills/pi-research/scripts/run.mjs (skill launcher, shebang)
15
+ * skill -> agent-skill/pi-research/scripts/run.mjs (skill launcher, shebang)
16
16
  *
17
17
  * Note: `packages: 'external'` already externalizes every bare/`node:` import,
18
18
  * so the old `--external:node:*` flag was redundant — output is identical.
@@ -114,10 +114,10 @@ const TARGETS = {
114
114
  copyPrompts();
115
115
  },
116
116
  skill: () => {
117
- const entry = p('skills', 'pi-research', 'scripts', 'run.ts');
118
- const outfile = p('skills', 'pi-research', 'scripts', 'run.mjs');
117
+ const entry = p('agent-skill', 'pi-research', 'scripts', 'run.ts');
118
+ const outfile = p('agent-skill', 'pi-research', 'scripts', 'run.mjs');
119
119
  // The published package ships the BUILT run.mjs and deliberately excludes its
120
- // run.ts source (package.json "files": "!skills/pi-research/scripts/run.ts"),
120
+ // run.ts source (package.json "files": "!agent-skill/pi-research/scripts/run.ts"),
121
121
  // yet it also ships prepare.cjs + build.cjs — and `prepare` runs `build.cjs all`.
122
122
  // On any install that executes prepare against the shipped tree (npm install
123
123
  // <dir>, file:, npm link, pi install <dir>) this target had no entry point and
@@ -28,9 +28,14 @@ const projectRoot = path.join(__dirname, '..');
28
28
  * coding-agent harnesses, so `npm uninstall` is symmetric with the in-app
29
29
  * installer (the /research-config "Install Skill in Coding Agents" action).
30
30
  * Reads the manifest written by the installer and removes ONLY entries we still
31
- * own (a symlink pointing into a pi-research skills dir, or a copy carrying our
32
- * package marker). Foreign directories are never touched. Best-effort; never
31
+ * own (a symlink pointing into a pi-research skill source dir, or a copy carrying
32
+ * our package marker). Foreign directories are never touched. Best-effort; never
33
33
  * throws (preuninstall must not fail the uninstall).
34
+ *
35
+ * The ownership regex below duplicates src/skill-install/skill-installer.ts's:
36
+ * preuninstall runs as a plain CJS script with no access to the built module.
37
+ * Both accept the current `agent-skill/` source dir AND the pre-1.5.3 `skills/`
38
+ * one, so a link created by an older version is still recognised and removed.
34
39
  */
35
40
  function removeInstalledSkills() {
36
41
  const manifestPath = path.join(os.homedir(), '.pi', 'research', 'installed-skills.json');
@@ -58,7 +63,7 @@ function removeInstalledSkills() {
58
63
  try {
59
64
  if (lst.isSymbolicLink()) {
60
65
  const dest = path.resolve(path.dirname(p), readlinkSync(p));
61
- owned = /[/\\]pi-research[/\\]skills[/\\]pi-research$/.test(dest);
66
+ owned = /[/\\]pi-research[/\\](?:agent-skill|skills)[/\\]pi-research$/.test(dest);
62
67
  } else {
63
68
  const md = readFileSync(path.join(p, 'SKILL.md'), 'utf-8');
64
69
  owned = md.includes('@lincoln504/pi-research');
@@ -10,7 +10,7 @@
10
10
  * Artifacts built:
11
11
  * - dist/thread-worker.mjs (browser worker, via build:worker)
12
12
  * - dist/cli.mjs (+ dist/prompts, dist/webgpu-probe.mjs) (pi-research CLI binary, via build:cli)
13
- * - skills/pi-research/scripts/run.mjs (skill launcher, via build:skill)
13
+ * - agent-skill/pi-research/scripts/run.mjs (skill launcher, via build:skill)
14
14
  */
15
15
 
16
16
  'use strict';
package/src/cli.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  * pi-research — standalone CLI
3
3
  *
4
4
  * A thin, dependency-free command line over the pi-research programmatic SDK
5
- * (src/sdk.ts). It lets any tool — Claude, Cursor, a shell script, CI — run
5
+ * (src/sdk.ts). It lets any tool — Claude, Codex, a shell script, CI — run
6
6
  * multi-agent web research without the pi CLI or TUI.
7
7
  *
8
8
  * pi-research research "<query>" [--depth N] [--model provider/id]
@@ -49,8 +49,11 @@ export interface HarnessDef {
49
49
  export const HARNESSES: readonly HarnessDef[] = [
50
50
  { id: 'claude', label: 'Claude', baseDir: '.claude', skillsDir: path.join('.claude', 'skills'), confidence: 'confirmed' },
51
51
  { id: 'openclaw', label: 'OpenClaw', baseDir: '.openclaw', skillsDir: path.join('.openclaw', 'skills'), confidence: 'confirmed', note: 'OpenClaw reads ~/.openclaw/skills as a managed skill root and accepts symlinked skill folders (docs.openclaw.ai/tools/skills).' },
52
- { id: 'pi', label: 'pi', baseDir: '.pi', skillsDir: path.join('.pi', 'skills'), confidence: 'confirmed' },
53
- { id: 'cursor', label: 'Cursor', baseDir: '.cursor', skillsDir: path.join('.cursor', 'skills'), confidence: 'partial', note: 'Cursor project-level skills are documented; the global ~/.cursor/skills path is community-reported.' },
52
+ // pi's own skill root is under its agent dir (~/.pi/agent/skills), NOT ~/.pi/skills.
53
+ // Listed for DETECTION only — pi is never an install target (see SKILL_AGENT_TARGETS):
54
+ // the host already exposes research as a native tool, so a skill there would just
55
+ // duplicate it through a slower subprocess.
56
+ { id: 'pi', label: 'pi', baseDir: '.pi', skillsDir: path.join('.pi', 'agent', 'skills'), confidence: 'confirmed' },
54
57
  { id: 'codex', label: 'OpenAI Codex CLI', baseDir: '.codex', skillsDir: path.join('.codex', 'skills'), confidence: 'unverified', note: 'Codex skills support is emerging; path not confirmed by official docs.' },
55
58
  { id: 'agents', label: 'Cross-tool (~/.agents/skills)', baseDir: '.agents', skillsDir: path.join('.agents', 'skills'), confidence: 'unverified', note: 'Proposed Universal Agents convention; not yet a ratified standard.' },
56
59
  ] as const;
@@ -58,6 +61,31 @@ export const HARNESSES: readonly HarnessDef[] = [
58
61
  const SKILL_NAME = 'pi-research';
59
62
  const PACKAGE_NAME = '@lincoln504/pi-research';
60
63
 
64
+ /**
65
+ * Directory inside this package that holds the shipped skill.
66
+ *
67
+ * Deliberately NOT `skills/`: pi treats a package-root `skills/` directory as a
68
+ * resource root and convention-scans it whenever its manifest omits a `skills`
69
+ * key, so the old name made pi load this skill — a slower duplicate of the
70
+ * extension's own native research tool — as soon as anything rewrote the
71
+ * package's settings entry into object form (which `pi config` does on any
72
+ * toggle). The name must stay outside pi's reserved resource types
73
+ * (extensions, skills, prompts, themes).
74
+ */
75
+ const SKILL_SOURCE_DIR = 'agent-skill';
76
+ /** Pre-1.5.3 location. Still recognised so existing installs stay manageable. */
77
+ const LEGACY_SKILL_SOURCE_DIR = 'skills';
78
+
79
+ /**
80
+ * Shape an owned symlink's destination must have: `…/pi-research/<dir>/pi-research`
81
+ * where `<dir>` is the current or the legacy source directory. Kept in sync with
82
+ * the duplicate in scripts/cleanup.cjs, which runs on preuninstall without this
83
+ * module available.
84
+ */
85
+ const OWNED_SYMLINK_DEST = new RegExp(
86
+ `[/\\\\]${SKILL_NAME}[/\\\\](?:${SKILL_SOURCE_DIR}|${LEGACY_SKILL_SOURCE_DIR})[/\\\\]${SKILL_NAME}$`,
87
+ );
88
+
61
89
  /**
62
90
  * This package's version, used to stamp manifest entries so a stale COPY can be
63
91
  * detected and refreshed. Read from the SKILL.md we are about to install rather
@@ -77,18 +105,17 @@ function readSkillVersion(sourceDir: string): string | null {
77
105
  }
78
106
 
79
107
  /**
80
- * The coding agents the in-app installer (the /research-config TUI) targets:
81
- * Claude, Codex, and OpenClaw. Each loads skills from a home-directory
82
- * `~/.<agent>/skills/` path — OpenClaw reads `~/.openclaw/skills` as a managed
83
- * skill root that accepts symlinked skill folders — so a single global symlink
84
- * works. Every target is gated on the agent's config dir already existing (see
85
- * skillInstallCandidates), so a tool that isn't set up is never offered and we
108
+ * The coding agents the in-app installer (the /research-config TUI) targets. Each
109
+ * loads skills from a home-directory `~/.<agent>/skills/` path, so a single global
110
+ * symlink works. Every target is gated on the agent's config dir already existing
111
+ * (see skillInstallCandidates), so a tool that isn't set up is never offered and we
86
112
  * never create its home dir.
87
113
  *
88
- * Cursor is deliberately excluded: it has no personal/global skills directory —
89
- * Cursor only loads skills from a project-level `.cursor/skills/`, so a global
90
- * `~/.cursor/skills` symlink would never be read. `pi` (the host itself) and the
91
- * speculative `~/.agents` convention are likewise excluded from the one-click flow.
114
+ * `pi` (the host itself) and the speculative `~/.agents` convention are excluded:
115
+ * pi already exposes research as a native tool, and a skill in either root would
116
+ * only add a slower duplicate. Agents that expose no personal/global skills
117
+ * directory — only project-level ones — cannot be served by a global symlink and
118
+ * are likewise not targeted.
92
119
  */
93
120
  export const SKILL_AGENT_TARGETS = ['claude', 'codex', 'openclaw'] as const;
94
121
 
@@ -166,7 +193,11 @@ function homeDir(opts?: { home?: string }): string {
166
193
  * Locate the bundled skill source directory (the one containing SKILL.md).
167
194
  * Robust across both the bundled CLI (dist/cli.mjs) and unbundled test runs:
168
195
  * honors PI_RESEARCH_SKILL_DIR, then walks up from this module and from cwd
169
- * looking for `skills/pi-research/SKILL.md`.
196
+ * looking for `agent-skill/pi-research/SKILL.md`.
197
+ *
198
+ * The legacy `skills/` location is still probed, after the current one, so a
199
+ * mixed tree (an older package still on disk beside a newer one) resolves rather
200
+ * than throwing. It is deliberately second: the current layout always wins.
170
201
  */
171
202
  export function resolveSkillSourceDir(explicit?: string): string {
172
203
  const candidates: string[] = [];
@@ -181,7 +212,8 @@ export function resolveSkillSourceDir(explicit?: string): string {
181
212
  if (!start) continue;
182
213
  let dir = start;
183
214
  for (let i = 0; i < 8; i++) {
184
- candidates.push(path.join(dir, 'skills', SKILL_NAME));
215
+ candidates.push(path.join(dir, SKILL_SOURCE_DIR, SKILL_NAME));
216
+ candidates.push(path.join(dir, LEGACY_SKILL_SOURCE_DIR, SKILL_NAME));
185
217
  const parent = path.dirname(dir);
186
218
  if (parent === dir) break;
187
219
  dir = parent;
@@ -193,7 +225,7 @@ export function resolveSkillSourceDir(explicit?: string): string {
193
225
  if (fs.existsSync(path.join(c, 'SKILL.md'))) return path.resolve(c);
194
226
  } catch { /* next */ }
195
227
  }
196
- throw new Error('Could not locate the bundled research skill (skills/pi-research/SKILL.md). Set PI_RESEARCH_SKILL_DIR to its path.');
228
+ throw new Error('Could not locate the bundled research skill (agent-skill/pi-research/SKILL.md). Set PI_RESEARCH_SKILL_DIR to its path.');
197
229
  }
198
230
 
199
231
  export function getManifestPath(opts?: { home?: string }): string {
@@ -251,7 +283,7 @@ function upsertEntry(manifest: Manifest, entry: ManifestEntry): void {
251
283
  // Ownership checks (never delete what isn't ours)
252
284
  // ---------------------------------------------------------------------------
253
285
 
254
- /** A symlink we own points at the skill source (our package's skills/pi-research). */
286
+ /** A symlink we own points at the skill source (our package's agent-skill/pi-research). */
255
287
  function isOwnedSymlink(targetPath: string, expectedSource?: string): boolean {
256
288
  try {
257
289
  const st = fs.lstatSync(targetPath);
@@ -259,11 +291,17 @@ function isOwnedSymlink(targetPath: string, expectedSource?: string): boolean {
259
291
  const dest = path.resolve(path.dirname(targetPath), fs.readlinkSync(targetPath));
260
292
  if (expectedSource && path.resolve(expectedSource) === dest) return true;
261
293
  // Fallback: own it only if it points at OUR package layout, i.e. the dest
262
- // ends in `pi-research/skills/pi-research`. Requiring `pi-research` to be the
263
- // immediate parent segment of `skills/pi-research` avoids the substring false
264
- // positive where a foreign path like `/home/pi-researcher/.../skills/pi-research`
265
- // (note: pi-researcher) would otherwise be misclassified as owned and deleted.
266
- return /[/\\]pi-research[/\\]skills[/\\]pi-research$/.test(dest);
294
+ // ends in `pi-research/<source-dir>/pi-research`. Requiring `pi-research` to be
295
+ // the immediate parent segment avoids the substring false positive where a
296
+ // foreign path like `/home/pi-researcher/.../skills/pi-research` (note:
297
+ // pi-researcher) would otherwise be misclassified as owned and deleted.
298
+ //
299
+ // BOTH the current and legacy source-dir names are accepted. Three of this
300
+ // function's four call sites pass no expectedSource and rely on this branch
301
+ // alone, so dropping the legacy name would strand every link created before
302
+ // 1.5.3: reconcile would stop re-pointing it, uninstall would refuse to
303
+ // remove it, and status would report it as a foreign skill.
304
+ return OWNED_SYMLINK_DEST.test(dest);
267
305
  } catch { return false; }
268
306
  }
269
307