Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .agents/plugins/marketplace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "nodesource",
"interface": {
"displayName": "NodeSource"
},
"plugins": [
{
"name": "nsolid-plugin",
"source": {
"source": "local",
"path": "./"
},
"policy": {
"installation": "AVAILABLE",
"authentication": "ON_USE",
"products": [
"CODEX"
]
},
"category": "Developer Tools"
}
]
}
25 changes: 25 additions & 0 deletions .claude-mcp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"mcpServers": {
"nsolid-console": {
"command": "node",
"args": [
"${CLAUDE_PLUGIN_ROOT}/scripts/mcp-wrapper.js",
"nsolid-console"
]
},
"ns-benchmark": {
"command": "node",
"args": [
"${CLAUDE_PLUGIN_ROOT}/scripts/mcp-wrapper.js",
"ns-benchmark"
]
},
"ncm": {
"command": "node",
"args": [
"${CLAUDE_PLUGIN_ROOT}/scripts/mcp-wrapper.js",
"ncm"
]
}
}
}
30 changes: 30 additions & 0 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "nodesource",
"owner": {
"name": "NodeSource"
},
"description": "NodeSource agent plugins",
"plugins": [
{
"name": "nsolid-plugin",
"source": "./",
"displayName": "N|Solid Plugin",
"version": "1.0.0",
"description": "N|Solid performance & security skills + MCP servers",
"author": {
"name": "NodeSource"
},
"homepage": "https://nodesource.com",
"repository": "https://github.com/NodeSource/nsolid-plugin",
"license": "MIT",
"category": "developer-tools",
"tags": [
"nodesource",
"nsolid",
"nodejs",
"performance",
"security"
]
}
]
}
32 changes: 32 additions & 0 deletions .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"$schema": "https://anthropic.com/claude-code/plugin.schema.json",
"name": "nsolid-plugin",
"displayName": "N|Solid Plugin",
"version": "1.0.0",
"description": "N|Solid performance & security skills + MCP servers",
"author": {
"name": "NodeSource"
},
"homepage": "https://nodesource.com",
"repository": "https://github.com/NodeSource/nsolid-plugin",
"license": "MIT",
"skills": [
"./skills/ns-advanced-memory-leak-hunter",
"./skills/ns-analyze-asset",
"./skills/ns-analyze-event",
"./skills/ns-analyze-tracing",
"./skills/ns-analyze-vulnerabilities",
"./skills/ns-audit-dependencies",
"./skills/ns-benchmark-run",
"./skills/ns-cpu-spike-analysis",
"./skills/ns-generate-asset",
"./skills/ns-generate-sbom",
"./skills/ns-memory-spike-analysis",
"./skills/ns-node-upgrade",
"./skills/ns-optimize-function",
"./skills/ns-replace-package",
"./skills/ns-upgrade-package",
"./skills/ns-validate-optimization"
],
"mcpServers": "./.claude-mcp.json"
}
27 changes: 27 additions & 0 deletions .codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"name": "nsolid-plugin",
"version": "1.0.0",
"description": "N|Solid Plugin — AI skills and MCP servers for Codex",
"author": {
"name": "NodeSource",
"url": "https://nodesource.com"
},
"homepage": "https://nodesource.com",
"repository": "https://github.com/NodeSource/nsolid-plugin",
"license": "MIT",
"keywords": [
"nodesource",
"nsolid",
"nodejs",
"performance",
"security"
],
"skills": "./skills/",
"mcpServers": "./.mcp.json",
"interface": {
"displayName": "N|Solid Plugin",
"shortDescription": "N|Solid performance & security",
"category": "Productivity",
"developerName": "NodeSource"
}
}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ dist/
test-results.log

# Generated plugin artifacts/materialized package skills
packages/core/skills/
packages/pi-plugin/skills/

# OpenCode
Expand Down
28 changes: 28 additions & 0 deletions .mcp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"mcpServers": {
"nsolid-console": {
"command": "node",
"args": [
"-e",
"const fs=require('node:fs');const os=require('node:os');const path=require('node:path');const {pathToFileURL}=require('node:url');const serverName=process.argv[1];const rel=['scripts','mcp-wrapper.js'];const roots=[path.join(os.homedir(),'.codex','plugins','cache'),process.cwd()];const candidates=[];for(const root of roots){try{const stack=[root];while(stack.length){const dir=stack.pop();if(!fs.existsSync(dir))continue;const direct=path.join(dir,...rel);if(fs.existsSync(direct))candidates.push(direct);for(const entry of fs.readdirSync(dir,{withFileTypes:true})){if(entry.isDirectory())stack.push(path.join(dir,entry.name))}}}catch{}}const wrapper=candidates.find((p)=>p.includes(`${path.sep}nsolid-plugin${path.sep}`));if(!wrapper){console.error('[nsolid-plugin] Could not locate Codex MCP wrapper. Reinstall with: codex plugin marketplace add NodeSource/nsolid-plugin && codex plugin add nsolid-plugin@nodesource');process.exit(1)}process.argv=[process.execPath,wrapper,serverName];import(pathToFileURL(wrapper).href)",
"nsolid-console"
]
},
"ns-benchmark": {
"command": "node",
"args": [
"-e",
"const fs=require('node:fs');const os=require('node:os');const path=require('node:path');const {pathToFileURL}=require('node:url');const serverName=process.argv[1];const rel=['scripts','mcp-wrapper.js'];const roots=[path.join(os.homedir(),'.codex','plugins','cache'),process.cwd()];const candidates=[];for(const root of roots){try{const stack=[root];while(stack.length){const dir=stack.pop();if(!fs.existsSync(dir))continue;const direct=path.join(dir,...rel);if(fs.existsSync(direct))candidates.push(direct);for(const entry of fs.readdirSync(dir,{withFileTypes:true})){if(entry.isDirectory())stack.push(path.join(dir,entry.name))}}}catch{}}const wrapper=candidates.find((p)=>p.includes(`${path.sep}nsolid-plugin${path.sep}`));if(!wrapper){console.error('[nsolid-plugin] Could not locate Codex MCP wrapper. Reinstall with: codex plugin marketplace add NodeSource/nsolid-plugin && codex plugin add nsolid-plugin@nodesource');process.exit(1)}process.argv=[process.execPath,wrapper,serverName];import(pathToFileURL(wrapper).href)",
"ns-benchmark"
]
},
"ncm": {
"command": "node",
"args": [
"-e",
"const fs=require('node:fs');const os=require('node:os');const path=require('node:path');const {pathToFileURL}=require('node:url');const serverName=process.argv[1];const rel=['scripts','mcp-wrapper.js'];const roots=[path.join(os.homedir(),'.codex','plugins','cache'),process.cwd()];const candidates=[];for(const root of roots){try{const stack=[root];while(stack.length){const dir=stack.pop();if(!fs.existsSync(dir))continue;const direct=path.join(dir,...rel);if(fs.existsSync(direct))candidates.push(direct);for(const entry of fs.readdirSync(dir,{withFileTypes:true})){if(entry.isDirectory())stack.push(path.join(dir,entry.name))}}}catch{}}const wrapper=candidates.find((p)=>p.includes(`${path.sep}nsolid-plugin${path.sep}`));if(!wrapper){console.error('[nsolid-plugin] Could not locate Codex MCP wrapper. Reinstall with: codex plugin marketplace add NodeSource/nsolid-plugin && codex plugin add nsolid-plugin@nodesource');process.exit(1)}process.argv=[process.execPath,wrapper,serverName];import(pathToFileURL(wrapper).href)",
"ncm"
]
}
}
}
77 changes: 41 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ Cross-harness plugin distribution for NodeSource AI skills and MCP servers. The

| Harness | Plugin model | Trigger |
|---|---|---|
| **Claude Code** | Generated marketplace/local artifact + `.claude-plugin/plugin.json` | Native plugin install, then explicit setup |
| **Codex CLI** | Generated marketplace/local artifact + `.codex-plugin/plugin.json` | Native plugin install, then explicit setup |
| **Claude Code** | Root GitHub marketplace/plugin + `.claude-plugin/plugin.json` | Native plugin install, then explicit setup |
| **Codex CLI** | Root GitHub marketplace/plugin + `.codex-plugin/plugin.json` | Native plugin install, then explicit setup |
| **OpenCode** | CLI-only (user-level skills + MCP config) | `nsolid-plugin setup --harness opencode` (auth + direct install) |
| **Antigravity CLI** | Generated local artifact + `plugin.json` | `agy plugin install <target>`, then `nsolid-plugin setup --harness antigravity` |
| **Pi Agent** | npm package + `pi.skills` | `pi install npm:@nodesource/pi-plugin`, `nsolid-plugin setup --harness pi`, then `pi install npm:pi-mcp-adapter` |
| **Antigravity CLI** | Root GitHub plugin + `plugin.json` | `agy plugin install <repo-url>`, then explicit setup |
| **Pi Agent** | npm package + `pi.skills` | `pi install npm:nsolid-pi-plugin`, `nsolid-plugin setup --harness pi`, then `pi install npm:pi-mcp-adapter` |

No harness relies on npm `postinstall` hooks. See `openspec/changes/cross-harness-plugin-installer/design.md` and `openspec/changes/cross-harness-plugin-installer/specs/installation-and-auth.md` for the full design rationale.

Expand All @@ -19,28 +19,30 @@ No harness relies on npm `postinstall` hooks. See `openspec/changes/cross-harnes
```text
nsolid-plugin/
├── packages/
│ ├── core/ # Shared CLI/setup/fallback logic + canonical skills
│ ├── core/ # Shared CLI/setup/fallback logic + npm CLI package
│ └── pi-plugin/ # Pi Agent package
├── plugins/templates/ # Source templates for generated native artifacts
├── dist/plugins/ # Generated plugin directories (not committed)
├── dist/artifacts/ # Generated .tgz artifacts (not committed)
├── .claude-plugin/ # Claude marketplace + plugin manifest
├── .agents/plugins/ # Codex marketplace manifest
├── .codex-plugin/ # Codex plugin manifest
├── skills/ # Canonical N|Solid skills and root plugin payload
├── skill-assets/ # Shared helper sources copied into skills/package artifacts
├── bundle.json # Canonical skill + MCP server descriptor
├── plugin.json # Antigravity root plugin manifest
└── pnpm-workspace.yaml
```

## Skill distribution model

Skills are canonical in `packages/core/skills/`. Claude, Codex, and Antigravity receive materialized skill copies only when `pnpm plugin:artifacts` generates self-contained release/local-install artifacts under `dist/`. Pi receives materialized skills only during package `prepack`.
Skills are canonical in the repository-root `skills/` directory. The repo root is also the GitHub-installable plugin payload for Claude, Codex, and Antigravity. Pi and the npm CLI package receive materialized skills during package `prepack`.

| Harness | Skill owner | Installer responsibility |
|---|---|---|
| **Claude** | Generated artifact | Native plugin artifact; `setup` for auth |
| **Codex** | Generated artifact | Native plugin artifact; `setup` for auth |
| **Antigravity** | Generated artifact | Native install script stages artifact assets; `setup` for auth |
| **Claude** | Root plugin | Native marketplace/plugin install; `setup` for auth |
| **Codex** | Root plugin | Native marketplace/plugin install; `setup` for auth |
| **Antigravity** | Root plugin | `agy plugin install <repo-url>`; `setup` for auth |
| **Pi** | Pi npm package (`pi.skills`) | Pi package owns skills; `setup` writes auth/MCP config |
| **OpenCode** | CLI-only harness copy | `setup` authenticates and copies skills/MCP config locally; `install` is no-browser fallback |

Codex artifacts currently include both a root `.codex-plugin/plugin.json` local marketplace container and a nested `plugins/nsolid-plugin/` plugin package. Both declare `skills: './skills/'` and both get materialized skill copies.

## Quick start

Expand Down Expand Up @@ -85,35 +87,39 @@ On setup:

## Per-harness install

The commands below use local pre-release artifact directories generated by `pnpm plugin:artifacts`. Released native artifacts are `.tgz` files; extract an archive to a plugin-root directory before passing it to a harness CLI:
The GitHub marketplace flow installs from the repository root.

The setup step requires the `nsolid-plugin` CLI on your PATH:

```bash
mkdir -p ./nsolid-claude-plugin
tar -xzf nsolid-claude-plugin.tgz -C ./nsolid-claude-plugin --strip-components=1
claude plugin marketplace add ./nsolid-claude-plugin
npm i -g nsolid-plugin # stable release
# during pre-release:
npm i -g nsolid-plugin@next
```

Or invoke it once-off with `npx -y nsolid-plugin setup --harness <harness>` (`npx -y nsolid-plugin@next ...` during pre-release).

### Claude Code

```bash
pnpm plugin:artifacts
claude plugin marketplace add ./dist/plugins/claude/nsolid-plugin
claude plugin install nsolid-plugin@nodesource-local
claude plugin marketplace add NodeSource/nsolid-plugin
claude plugin install nsolid-plugin@nodesource
nsolid-plugin setup --harness claude
```

Claude installs plugins through marketplaces, including local marketplace directories. The generated artifact root includes `.claude-plugin/marketplace.json`, so a downloaded/unpacked artifact can be added as a local marketplace before installing `nsolid-plugin@nodesource-local`. If marketplace/local plugin install is unavailable, `nsolid-plugin install --harness claude` is the fallback direct installer and does not open a browser.
Claude installs plugins through marketplaces. The repository root includes `.claude-plugin/marketplace.json`, so GitHub install works directly. If marketplace/local plugin install is unavailable, `nsolid-plugin install --harness claude` is the fallback direct installer and does not open a browser.

> `nsolid-plugin` must be available on your PATH. Once published, install it globally (`npm i -g nsolid-plugin`) or invoke it via npx (`npx -y nsolid-plugin setup --harness claude`). During the pre-release window, use the prerelease tag (`npx -y nsolid-plugin@next ...` or `npm i -g nsolid-plugin@next`).

### Codex CLI

```bash
pnpm plugin:artifacts
codex plugin marketplace add ./dist/plugins/codex/nsolid-plugin
codex plugin add nsolid-plugin@codex-plugin
codex plugin marketplace add NodeSource/nsolid-plugin
codex plugin add nsolid-plugin@nodesource
nsolid-plugin setup --harness codex
```

Codex is marketplace/artifact-owned. A NodeSource-owned Git/local marketplace can be used as fallback if OpenAI curation is unavailable. Authentication remains explicit through `nsolid-plugin setup --harness codex`.
Codex is marketplace-owned. A NodeSource-owned Git/local marketplace can be used as fallback if OpenAI curation is unavailable. Authentication remains explicit through `nsolid-plugin setup --harness codex` (or `npx -y nsolid-plugin setup --harness codex`).

### OpenCode

Expand All @@ -128,18 +134,17 @@ Use `nsolid-plugin install --harness opencode` only as a no-browser fallback/rep
### Antigravity CLI

```bash
pnpm plugin:artifacts
agy plugin install ./dist/plugins/antigravity/nsolid-plugin
agy plugin install https://github.com/NodeSource/nsolid-plugin.git
nsolid-plugin setup --harness antigravity
```

Antigravity uses artifact-owned skills and MCP wrappers from `~/.gemini/antigravity-cli/plugins/nsolid-plugin/`. The generated native install script stages the artifact bundle and prints the explicit setup command; it does not start auth.
Antigravity installs the repository root as a native plugin and stages skills/MCP wrappers under `~/.gemini/config/plugins/nsolid-plugin/`. Install does not start auth.

### Pi Agent

```bash
# 1. Install the Pi package (skills are package-owned)
pi install npm:@nodesource/pi-plugin
pi install npm:nsolid-pi-plugin

# 2. Authenticate and write Pi MCP config
nsolid-plugin setup --harness pi
Expand Down Expand Up @@ -190,16 +195,16 @@ pnpm lint # Lint all packages
### Bundle and plugin asset sync checks

```bash
pnpm --filter @nodesource/plugin-core bundle:check # Check if core bundle.json is in sync
pnpm --filter @nodesource/plugin-core bundle:sync # Copy root bundle.json into core
pnpm --filter nsolid-plugin bundle:check # Check if core bundle.json is in sync
pnpm --filter nsolid-plugin bundle:sync # Copy root bundle.json into core
pnpm plugin:check # Check generated manifests/configs and verify no package skill copies are committed
pnpm plugin:sync # Regenerate manifests/configs and remove materialized package skill copies
pnpm plugin:materialize # Copy core skills into plugin packages for pack/release artifacts
pnpm plugin:artifacts # Generate Claude/Codex/Antigravity plugin dirs and .tgz archives
pnpm plugin:artifacts:check # Verify generated plugin artifacts are current
pnpm plugin:materialize # Copy root skills into the Pi package for pack/release
pnpm plugin:root # Refresh root marketplace/plugin manifests from bundle.json
pnpm plugin:root:check # Fail if committed root manifests drift from bundle.json
```

Run `pnpm plugin:check` in CI and before release. The source tree keeps one canonical skill copy under `packages/core/skills/`; package-local `skills/` directories are materialized only for pack/release artifacts and cleaned afterward by package `postpack` scripts.
Run `pnpm plugin:check` in CI and before release. The source tree keeps one canonical skill copy under root `skills/`; package-local `skills/` directories are materialized only for npm package release and cleaned afterward by package sync scripts.

## Troubleshooting

Expand Down Expand Up @@ -257,7 +262,7 @@ nsolid-plugin restore --harness <harness> --backup ~/.agents/.config-backup/<har

### Install vs setup

`nsolid-plugin install --harness <harness>` is a no-browser fallback/direct installer. Claude, Codex, and Antigravity should normally use their generated native artifacts. OpenCode uses `nsolid-plugin setup --harness opencode` as its primary onboarding command because it authenticates and then performs the direct install; `install --harness opencode` is for repair/offline staging. Pi is package-owned: `pi install npm:@nodesource/pi-plugin` installs skills, while `nsolid-plugin install/setup --harness pi` only writes Pi MCP config.
`nsolid-plugin install --harness <harness>` is a no-browser fallback/direct installer. Claude, Codex, and Antigravity should normally use native GitHub plugin install from the repository root. OpenCode uses `nsolid-plugin setup --harness opencode` as its primary onboarding command because it authenticates and then performs the direct install; `install --harness opencode` is for repair/offline staging. Pi is package-owned: `pi install npm:nsolid-pi-plugin` installs skills, while `nsolid-plugin install/setup --harness pi` only writes Pi MCP config.

### Verbose logging

Expand Down
Loading
Loading