Problem
Pi's extension loader warns about gentle-pi/package.json on every startup:
Warning: Extension package "…/node_modules/gentle-pi/package.json":
Host-provided extension packages must be declared in peerDependencies with a "*" range, not dependencies:
@earendil-works/pi-tui. Installed copies can bypass the extension loader and create duplicate runtime modules.
@earendil-works/pi-tui is in the host's own allowlist of host-provided extension packages (the HOST_PROVIDED_EXTENSION_PACKAGES set in the Pi coding agent's resource loader), together with @earendil-works/pi-ai, @earendil-works/pi-coding-agent, typebox, @sinclair/typebox, and the @mariozechner/* equivalents. Pi already supplies every one of them to extensions.
Published gentle-pi@3.7.0 (current latest) declares:
"dependencies": {
"@earendil-works/pi-tui": "0.85.1",
"@heyhuynhgiabuu/pi-pretty": "0.6.27"
},
"peerDependencies": {
"@earendil-works/pi-coding-agent": ">=0.85.1",
"typebox": "*"
}
@earendil-works/pi-coding-agent and typebox are already declared correctly as peers, so the remaining hard dependency on a host-provided module reads as an oversight rather than intent. @heyhuynhgiabuu/pi-pretty is genuinely third-party and correctly stays a regular dependency.
package.json on main has the same problem and is worse: it also hard-depends on @earendil-works/pi-ai, which is in the same host-provided allowlist, so the same warning and the same hoisting will ship with the next release.
Why this matters beyond the warning
Declaring a host-provided package as a dependency gives npm a reason to hoist the extension-local copy into the shared tree root, where it is resolved instead of the host's. Observed in a ~/.pi/agent/npm tree, same session:
| module |
tree copy |
host copy (pi-coding-agent 0.99.1) |
@earendil-works/pi-tui |
0.85.1 |
0.99.1 |
require.resolve("@earendil-works/pi-tui") executed from the tree root returns the tree copy, not the host's, so the tree copy is the one on the resolution path for anything inside that tree. gentle-pi imports @earendil-works/pi-tui from 61 sites, which is what turns a 14-minor version skew into a live divergence rather than a theoretical one; the loader's own warning wording ("bypass the extension loader and create duplicate runtime modules") is describing exactly this.
Steps to reproduce
- Install
gentle-pi@3.7.0 into a Pi agent npm tree managed by npm (~/.pi/agent/npm), e.g. as a dependency of that tree's root package.json.
- Start
pi.
- Observe the loader warning naming
@earendil-works/pi-tui.
- Compare the hoisted copy against the host's:
- from the tree root:
node -p "require('./node_modules/@earendil-works/pi-tui/package.json').version"
- from the
pi-coding-agent install tree: node -p "require('./node_modules/@earendil-works/pi-tui/package.json').version"
Expected and actual behavior
Expected: no loader warning, and gentle-pi resolving the host's single @earendil-works/pi-tui and @earendil-works/pi-ai instances, with no extension-local copy hoisted into the shared tree.
Actual: the loader warns on every startup, and the tree root holds a @earendil-works/pi-tui copy at 0.85.1 while the host runs 0.99.1.
gentle-pi version
3.7.0 (published, current latest)
Pi version
0.99.1 (host ships @earendil-works/pi-tui 0.99.1)
Operating system
macOS
Relevant logs or error output (optional)
Warning: Extension package "…/node_modules/gentle-pi/package.json":
Host-provided extension packages must be declared in peerDependencies with a "*" range, not dependencies:
@earendil-works/pi-tui. Installed copies can bypass the extension loader and create duplicate runtime modules.
{
"dependencies": { "@earendil-works/pi-tui": "0.85.1", "@heyhuynhgiabuu/pi-pretty": "0.6.27" },
"peerDependencies": { "typebox": "*", "@earendil-works/pi-coding-agent": ">=0.85.1" }
}
Suggested fix
Move @earendil-works/pi-tui — and @earendil-works/pi-ai on main — from dependencies to peerDependencies, mirroring how @earendil-works/pi-coding-agent and typebox are already declared here. Add peerDependenciesMeta.optional for both if gentle-pi should stay installable outside a Pi host.
This is the same defect class as Gentleman-Programming/engram#853, which was fixed for gentle-engram's @earendil-works/pi-tui; the identical remaining entry for gentle-engram's typebox is noted there.
Before submitting
Problem
Pi's extension loader warns about
gentle-pi/package.jsonon every startup:@earendil-works/pi-tuiis in the host's own allowlist of host-provided extension packages (theHOST_PROVIDED_EXTENSION_PACKAGESset in the Pi coding agent's resource loader), together with@earendil-works/pi-ai,@earendil-works/pi-coding-agent,typebox,@sinclair/typebox, and the@mariozechner/*equivalents. Pi already supplies every one of them to extensions.Published
gentle-pi@3.7.0(current latest) declares:@earendil-works/pi-coding-agentandtypeboxare already declared correctly as peers, so the remaining hard dependency on a host-provided module reads as an oversight rather than intent.@heyhuynhgiabuu/pi-prettyis genuinely third-party and correctly stays a regular dependency.package.jsononmainhas the same problem and is worse: it also hard-depends on@earendil-works/pi-ai, which is in the same host-provided allowlist, so the same warning and the same hoisting will ship with the next release.Why this matters beyond the warning
Declaring a host-provided package as a dependency gives npm a reason to hoist the extension-local copy into the shared tree root, where it is resolved instead of the host's. Observed in a
~/.pi/agent/npmtree, same session:@earendil-works/pi-tuirequire.resolve("@earendil-works/pi-tui")executed from the tree root returns the tree copy, not the host's, so the tree copy is the one on the resolution path for anything inside that tree.gentle-piimports@earendil-works/pi-tuifrom 61 sites, which is what turns a 14-minor version skew into a live divergence rather than a theoretical one; the loader's own warning wording ("bypass the extension loader and create duplicate runtime modules") is describing exactly this.Steps to reproduce
gentle-pi@3.7.0into a Pi agent npm tree managed by npm (~/.pi/agent/npm), e.g. as a dependency of that tree's rootpackage.json.pi.@earendil-works/pi-tui.node -p "require('./node_modules/@earendil-works/pi-tui/package.json').version"pi-coding-agentinstall tree:node -p "require('./node_modules/@earendil-works/pi-tui/package.json').version"Expected and actual behavior
Expected: no loader warning, and
gentle-piresolving the host's single@earendil-works/pi-tuiand@earendil-works/pi-aiinstances, with no extension-local copy hoisted into the shared tree.Actual: the loader warns on every startup, and the tree root holds a
@earendil-works/pi-tuicopy at 0.85.1 while the host runs 0.99.1.gentle-pi version
3.7.0 (published, current latest)
Pi version
0.99.1 (host ships
@earendil-works/pi-tui0.99.1)Operating system
macOS
Relevant logs or error output (optional)
{ "dependencies": { "@earendil-works/pi-tui": "0.85.1", "@heyhuynhgiabuu/pi-pretty": "0.6.27" }, "peerDependencies": { "typebox": "*", "@earendil-works/pi-coding-agent": ">=0.85.1" } }Suggested fix
Move
@earendil-works/pi-tui— and@earendil-works/pi-aionmain— fromdependenciestopeerDependencies, mirroring how@earendil-works/pi-coding-agentandtypeboxare already declared here. AddpeerDependenciesMeta.optionalfor both ifgentle-pishould stay installable outside a Pi host.This is the same defect class as Gentleman-Programming/engram#853, which was fixed for
gentle-engram's@earendil-works/pi-tui; the identical remaining entry forgentle-engram'stypeboxis noted there.Before submitting