Repository navigation
Ship Pi and OpenCode plugins that list NodeSpace's skills in the session, and an instructions block for harnesses without one #3546
Description
Overview
The Claude Code plugin puts NodeSpace's skill list and orientation into a session from the start. Pi and OpenCode have their own plugin systems with the same hooks, and Codex and Antigravity have none we use. This issue ships a Pi extension and an OpenCode plugin that do what the Claude Code plugin does, and has the installer write a short instructions block for harnesses without a plugin.
Problem Statement
- In Pi and OpenCode the graph's skills are invisible until the model decides to fetch, the same gap the Claude Code plugin closes.
- The installer looks for OpenCode in
~/.opencode, which OpenCode does not use; its configuration, plugins and skills live under~/.config/opencode/. An OpenCode user is therefore not detected. - Pi loads extensions from
~/.pi/agent/extensions/, a different folder from the skills folder the installer writes to, so nothing placed beside the skill is ever loaded as code. - A harness with no plugin has nothing that tells the agent to consult NodeSpace before starting work except the static skill, which the model may never open.
scripts/uninstall.shkeeps its own list of harness folders, which omits Pi and has the wrong Antigravity path.
Proposed Solution
Pi extension and OpenCode plugin. Each does the four things of ADR-093 §5 through its harness's own hooks: check the CLI and daemon and resolve the project at session start; add the orientation, consent rules and skill list to the system prompt; note skill-list changes on a prompt; show status where the harness has a place for it. Both run nodespace commands for everything and hold no logic of their own.
Instructions block. For Codex and Antigravity, the installer writes a marked block into the harness's user-level instructions file, with the same orientation and consent rules and an instruction to list skills before starting work. The installer owns only that block: it updates it on reinstall and removes it on uninstall, and leaves the rest of the file untouched.
Installer. Detect OpenCode at its real location; install each plugin where its harness loads code from; record every file and the block in the install record.
Documentation
- ADR-093 §5 - what a plugin does and each harness's location; §6 - the instructions block and its ownership; §7 - procedure, not permission
- ADR-064 §5 (revised) - the skill file is the entry point for an agent without a plugin
- ADR-081 - shipped text names no other product
- Updates:
architecture/agent-session.md(which harness gets which delivery)
Architecture Impact
Implements ADR-093 §5 and §6. Writing into a user's own instructions file is new behaviour for the installer; ADR-093 §6 decides it and bounds it to one marked block.
Acceptance Criteria
Pi
- The extension installs to
~/.pi/agent/extensions/(honouringPI_CODING_AGENT_DIR) and Pi loads it with no flag - At session start it checks the CLI and daemon and resolves the project
- The system prompt carries the orientation, the consent rules and the marked skill list on every agent run, read fresh each run
- It sets a status entry with reachability and the project, only when the session has a UI
OpenCode
- The installer detects OpenCode by
~/.config/opencodeand installs the skill and the plugin under it; the plugin loads from~/.config/opencode/plugins/with no configuration - The plugin adds the orientation, the consent rules and the marked skill list to the system prompt on each request
- The NodeSpace skill is listed to the agent once, not twice, when OpenCode also reads the Claude skills folder
Both plugins
- A skill that changed since the session last read the list is named to the agent before it acts on the next prompt
- During a turn, before a tool call and at most once in a set interval, each plugin compares the version of the context read for the item the session is working on, refuses further tool calls with the reason if the item was finished, cancelled or changed under the session, and adds a note if only its governing nodes or skills changed
- With no matching project only reachability is shown; with the daemon unreachable it is said once and nothing else is added
-
NODESPACE_DATABASEin the environment selects the database for every command - The orientation and consent text are the same as the Claude Code plugin's, from one source in the package; a test fails if the three copies differ
- Each plugin type-checks against its harness's published plugin types
Instructions block
- For Codex and Antigravity the installer writes one marked block into the harness's user-level instructions file, creating the file if absent
- Reinstall replaces the block in place; uninstall removes it and leaves every other byte of the file unchanged; a test covers a file with user content before and after the block
- The block is recorded in the install record
- An agent given only the block and the static skill lists skills before its first write; the live skill-fetch test covers it
Installer
-
nodespace skill statusreports, per harness, whether the plugin or the block is installed -
scripts/uninstall.shremoves what the installer installs for all five harnesses, or is replaced by a call to the installer's uninstall -
scripts/check-pro-boundary.tspasses - Docs updated as listed under Documentation
- Code passes
bun run quality:fix - Tests pass (
bun run test:changed)
Technical Specifications
Reference Files
packages/skill/src/agents.ts- harness detection and install targetspackages/skill/src/installer.ts- install record, uninstall safetypackages/skill/src/tests/installer.test.ts- installer tests, including the guard on the places that enumerate the skillpackages/cli/src/commands/skill.rs,packages/desktop-app/app-lib/src/skill_setup.rs- the two callers that run the installer and parse its outputscripts/uninstall.sh,scripts/build-skill.ts,scripts/publish-skill-repo.ts
Implementation Details
Verify each harness's API against its current documentation before writing; these were read from the docs and source on 2026-10-04 and both projects change quickly.
- Pi (
earendil-works/pi, package@earendil-works/pi-coding-agent): an extension is a default-exported function taking the extension API. Use the session-start event, the before-agent-start event (which exposes system prompt sections to add to), the extension API's command runner, and the UI's status setter. Do not start processes in the factory itself. - OpenCode (
anomalyco/opencode, package@opencode-ai/plugin): a plugin is a named export returning hooks. Session start is thesession.createdevent; the system prompt hook and the message hook carry anexperimental.prefix and are documented only in source, so isolate them and fail quietly if absent. Commands run through the Bun shell the plugin receives. - Codex reads
~/.codex/AGENTS.md(CODEX_HOMEmoves it). Antigravity's user-level instructions path must be confirmed against its documentation; if it has none, say so in the PR and leave Antigravity on the static skill alone. - Codex has a hooks system of its own. Whether to use it instead of the block is out of scope here.
- Block markers are comment lines that survive Markdown rendering and are unlikely to appear in a user's own text.
- Plugin code cannot run in the merge gate. Test the installer and the shared text in the gate; test each plugin against its harness outside it and say how in the package.
Dependencies
- Ship a Claude Code plugin that lists NodeSpace's skills in the session and tracks changes; slim the static skill and remove the tool shims #3545 (the Claude Code plugin, whose behaviour and shared text these follow)
Related Issues
- Give each built-in tool its CLI command and return it with fetched skills; fetch one skill by name; version the skill list #3540 (the skill list version the change note uses)
- Run a saved query by id or title, narrow it at run time, negate filters, and filter into link and object values #3554 (the query that finds the project)
- Declare context paths on a schema, derive a node's skills from the node and the queries it matches, and return a versioned context read #3557 (the versioned context read)
Non-Goals
- A Codex plugin through Codex's own hooks
- Registering tools in any harness
Activity
malibio commentedon Oct 5, 2026
Frontend baseline: 322 test files passed, 5875 tests passed
malibio commentedon Oct 5, 2026
From #3547 (merged as #3647), three things the Pi and OpenCode plugins need to match the Claude Code plugin in a session NodeSpace launches (ADR-093 §8; see
packages/skill/plugins/claude-code/hooks/register.ts:readLaunch,dropLaunchVariables,reportSession,launchedItem):nodespace session report-harness-session <harness id> --session <PTY session id>. The PTY session id is inNODESPACE_SESSION. The command's JSON answersnode_id, the chat node the session is a view onto.NODESPACE_LAUNCHED_FORnames the task, or the session's own chat node when no task was named. Open only when it differs from thenode_idthe report answered, and open with nothing when the report is not answered: the chat node is not work, and watching it would stop the session when the app writes to it.Without 1, a Pi or OpenCode session's chat node keeps an empty
session_id: the directory-based lookup is gone. The variables and their meaning are inarchitecture/agent-session.md(Environment).