From ebf5edd8f33e8bddebf50c7948bc381cd5ae8cfb Mon Sep 17 00:00:00 2001 From: Diogo Esteves Date: Fri, 16 Oct 2026 11:17:01 +0100 Subject: [PATCH 1/2] docs(clients): lead with the setup; add Antigravity, Gemini folder trust, Copilot via the marketplace and one .mcp.json /docs/clients opened with a 253-word paragraph on protocol eras and roots before any setup. It now opens with one line ("Run it from the project, or pass --root"), a box with the one .mcp.json that Claude Code, VS Code, GitHub Copilot CLI and Grok Build read, and moves how the server finds the project to a closing section. - Gemini CLI: a gemini mcp add -s user one-liner, and the trusted-folder rule (an untrusted folder lists the server as Disabled, user-level ones too). - Antigravity (CLI and IDE): its own mcp_config.json paths, and a README badge. - Copilot CLI: install the plugin through the marketplace; the direct install from a repository path prints a deprecation warning. - The hook runs in Claude Code and Codex CLI, on apply_patch edits in Codex. OS2-28 --- README.md | 3 +- docs/clients.md | 76 ++++++++++++++++++------ site/test/clients-page.test.ts | 56 ++++++++++++++++++ test/clients-docs.test.ts | 102 +++++++++++++++++++++++++++++++++ 4 files changed, 217 insertions(+), 20 deletions(-) create mode 100644 site/test/clients-page.test.ts create mode 100644 test/clients-docs.test.ts diff --git a/README.md b/README.md index 12ac9c52..1b7d3d9b 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ Using the GitHub Action? `uses: dgesteves/onsystem@v0` checks the lines a pull r **Also works with** [![Codex CLI](https://img.shields.io/badge/Codex_CLI-0d0f12?style=flat-square)](https://onsystem.vercel.app/docs/clients#codex-cli) [![Gemini CLI](https://img.shields.io/badge/Gemini_CLI-0d0f12?style=flat-square&logo=googlegemini&logoColor=white)](https://onsystem.vercel.app/docs/clients#gemini-cli) +[![Antigravity](https://img.shields.io/badge/Antigravity-0d0f12?style=flat-square)](https://onsystem.vercel.app/docs/clients#antigravity-cli-and-ide) [![Grok Build](https://img.shields.io/badge/Grok_Build-0d0f12?style=flat-square)](https://onsystem.vercel.app/docs/clients#grok-build) [![GitHub Copilot CLI](https://img.shields.io/badge/GitHub_Copilot_CLI-0d0f12?style=flat-square&logo=githubcopilot&logoColor=white)](https://onsystem.vercel.app/docs/clients#github-copilot-cli) [![Claude Desktop](https://img.shields.io/badge/Claude_Desktop-0d0f12?style=flat-square&logo=claude&logoColor=white)](https://onsystem.vercel.app/docs/clients#claude-desktop) @@ -91,7 +92,7 @@ After each Write or Edit of a `.tsx` or `.jsx` file, the hook runs `onsystem che **Other agents.** `npx skills add dgesteves/onsystem` adds the skill to any agent with Agent Skills, and there are [plugins for Codex, GitHub Copilot CLI, VS Code and Cursor](https://onsystem.vercel.app/docs/clients#plugins-for-other-agents). -**Any MCP client.** Run `npx -y onsystem` as a stdio server. There are [configs for Claude Desktop, Codex CLI, GitHub Copilot CLI, Windsurf, JetBrains IDEs, Zed, Gemini CLI and Grok Build](https://onsystem.vercel.app/docs/clients#other-clients). +**Any MCP client.** Run `npx -y onsystem` as a stdio server. There are [configs for Claude Desktop, Codex CLI, GitHub Copilot CLI, Windsurf, JetBrains IDEs, Zed, Gemini CLI, Antigravity and Grok Build](https://onsystem.vercel.app/docs/clients#other-clients). **CI.** Install it as a dev dependency, accept the findings the codebase already has once, and fail pull requests only on new ones: diff --git a/docs/clients.md b/docs/clients.md index 64a26109..23e95483 100644 --- a/docs/clients.md +++ b/docs/clients.md @@ -1,12 +1,28 @@ # Set up your agent -The server speaks MCP over stdio, in both protocol eras: the 2026-07-28 revision (stateless, with `server/discover`) and the 2025 one (the `initialize` handshake), the era chosen by the client's first message. It finds the project from `--root`, a config file in the working directory, or the working directory itself when it holds a project (a `package.json` or `components.json`). MCP roots, which 2026-07-28 deprecates, are the fallback: when the working directory is none of those (Claude Desktop starts servers in `/`), a 2025-era client that reports roots has its first `file://` root used. When none of these gives a project (a client that starts servers in your home or the plugin's folder and reports no roots), each tool call's project is found from the absolute path it names, `path` (or `filename`, for `check_ui` with `code`): the nearest folder at or above it with a `package.json`, `components.json` or config, or the monorepo root above that, but never your home folder or the filesystem root. A project found this way loads a JSON config (`onsystem.config.json`) only: the server runs a JavaScript or TypeScript config only in a project it was started in. Until a call names one, the tools return an error that asks for it; after that, a call without one answers from the project found, as long as only one has been. Started at a [monorepo root](configuration.md#monorepo-roots), it serves every app and design-system package in it: the tools take the `path` of the file the agent is editing and answer for that file's project. +Pick your client below and add the server. Run it from the project, or pass `--root` with the app's absolute path: [how the server finds your project](#how-the-server-finds-your-project) has the rest. Every client gets the same five tools, including `check_ui`, which the agent runs on its own output. Claude Code and Codex CLI also run the [plugin](plugin.md)'s hook, which checks each edit as it happens, so there use the plugin instead; with other agents, add the [CI check](ci.md) so what the agent skips still gets caught. +> [!TIP] +> **One `.mcp.json` for the team.** Commit this file at the repository root, and Claude Code, VS Code, GitHub Copilot CLI and Grok Build start the server from it once each person trusts the folder or approves the server: +> +> ```json +> { +> "mcpServers": { +> "onsystem": { +> "command": "npx", +> "args": ["-y", "onsystem"] +> } +> } +> } +> ``` +> +> It needs no `--root`: the server finds the project from the folder it starts in, the roots the client reports, or the files the tools are given. In Claude Code it registers the same tools as the plugin, so use it there instead of the plugin, not next to it; [Roll out to a team](rollout.md#give-every-agent-the-design-system) commits the plugin, hook included. Cursor and the other clients read their own files, below. + ## Plugins for other agents -The skill and the MCP server also come packaged for other agents, pinned to the same release as the Claude Code plugin. Only the Claude Code plugin has the hook that checks each edit, and Codex runs it too; elsewhere, the [CI check](ci.md) catches what the agent skips. +The skill and the MCP server also come packaged for other agents, pinned to the same release as the Claude Code plugin. The hook that checks each edit runs in Claude Code and Codex CLI; elsewhere, the [CI check](ci.md) catches what the agent skips. - **Any agent with Agent Skills** (Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, OpenCode and others): the skill, from the repository. It goes to `.agents/skills/onsystem`, which most agents read, and is linked into `.claude/skills` for Claude Code. Add the MCP server with your client's config below. @@ -21,13 +37,14 @@ The skill and the MCP server also come packaged for other agents, pinned to the codex plugin add onsystem@dgesteves ``` -- **GitHub Copilot CLI:** the [Agent Plugins 1.0](https://github.com/agentplugins/agent-plugins-spec) package, with the server and the skill: +- **GitHub Copilot CLI:** Copilot CLI reads the same marketplace as Claude Code and installs that plugin's server and skill. Install it from the marketplace: Copilot CLI has deprecated installing a plugin straight from a repository. ```sh - copilot plugin install dgesteves/onsystem:plugins/onsystem-agent + copilot plugin marketplace add dgesteves/onsystem + copilot plugin install onsystem@dgesteves ``` -- **VS Code** (GitHub Copilot agent plugins): run **Chat: Install Plugin From Source** from the Command Palette and enter `dgesteves/onsystem`. VS Code reads the same marketplace as Claude Code and installs that plugin's server and skill. To use the Agent Plugins package instead, add a clone's `plugins/onsystem-agent` folder to the `chat.pluginLocations` setting. +- **VS Code** (GitHub Copilot agent plugins): run **Chat: Install Plugin From Source** from the Command Palette and enter `dgesteves/onsystem`. VS Code reads the same marketplace as Claude Code and installs that plugin's server and skill. To use the [Agent Plugins 1.0](https://github.com/agentplugins/agent-plugins-spec) package instead, add a clone's `plugins/onsystem-agent` folder to the `chat.pluginLocations` setting. - **Cursor:** the Cursor plugin, in `plugins/onsystem-cursor`. Until it is listed in the Cursor Marketplace, copy that folder to `~/.cursor/plugins/local/onsystem` and run **Developer: Reload Window**. A client that loads the Agent Plugins format starts the server in the plugin's folder rather than in your project, so the server finds the project through the workspace roots the client reports, as VS Code and Cursor do. If a client reports none, the server finds the project from the absolute path of the file the agent passes to the tools, and asks for one when a call has none. To have it found from the start, add the server with the client's MCP config below instead. @@ -138,7 +155,7 @@ That writes `~/.copilot/mcp-config.json`: } ``` -In a session, `/mcp show onsystem` lists its tools. +In a session, `/mcp show onsystem` lists its tools. Copilot CLI also reads the team's `.mcp.json` (or `.github/mcp.json`) in a folder you trust. @@ -206,7 +223,31 @@ In Zed's `settings.json`:
Gemini CLI -`.gemini/settings.json` in the project, or `~/.gemini/settings.json` for every project: +```sh +gemini mcp add -s user onsystem npx -y onsystem --root /absolute/path/to/app +``` + +That writes `~/.gemini/settings.json`, for every project; without `-s user`, it writes `.gemini/settings.json` in the project: + +```json +{ + "mcpServers": { + "onsystem": { + "command": "npx", + "args": ["-y", "onsystem", "--root", "/absolute/path/to/app"] + } + } +} +``` + +Gemini CLI starts MCP servers only in trusted folders: trust the project when Gemini CLI asks, or later with `/permissions`. Until then, `gemini mcp list` shows onsystem as Disabled, even from the user file. A headless run (`gemini -p`) cannot ask: pass `--skip-trust`, or set `GEMINI_CLI_TRUST_WORKSPACE=true`. + +
+ +
+Antigravity (CLI and IDE) + +Antigravity CLI replaced Gemini CLI for unpaid-tier and Google One users in June 2026, and it keeps MCP servers in a different file: the CLI and the IDE both read `~/.gemini/config/mcp_config.json` for every project, or `.agents/mcp_config.json` in the project. In the IDE, open the file from the **…** menu of the agent panel: **MCP Servers**, then **Manage MCP Servers**, then **View raw config**. In the CLI, `/mcp` opens the MCP manager. ```json { @@ -249,21 +290,18 @@ Use this instead of the plugin, not next to it: both register the same tools. claude mcp add onsystem -- npx -y onsystem ``` -To share it with your team, add `--scope project`, which writes `.mcp.json` at the repository root: - -```json -{ - "mcpServers": { - "onsystem": { - "command": "npx", - "args": ["-y", "onsystem"] - } - } -} -``` +To share it with your team, add `--scope project`, which writes the same entry to `.mcp.json` at the repository root: the file at the top of this page.
Any other MCP client: run `npx -y onsystem --root /absolute/path/to/app` as a stdio server. On native Windows, wrap it as `cmd /c npx ...`. The server sends usage instructions in its `initialize` result and in `server/discover`. Clients that ignore them benefit from one line in `CLAUDE.md`, `AGENTS.md` or `.cursor/rules`: _"Before writing UI, use the onsystem tools. Run check_ui on every file you change and fix all errors."_ Run in a terminal, `onsystem init` offers to add a short section that says so to the project's `AGENTS.md` or `CLAUDE.md`, with `npx -y onsystem check ` for agents without the tools. It sits between `BEGIN:onsystem-agent-rules` and `END:onsystem-agent-rules` comment markers, which a later run updates in place. + +## How the server finds your project + +The server finds the project from `--root`, a config file in the working directory, or the working directory itself when it holds a project (a `package.json` or `components.json`). Started at a [monorepo root](configuration.md#monorepo-roots), it serves every app and design-system package in it: the tools take the `path` of the file the agent is editing and answer for that file's project. + +MCP roots, which the 2026-07-28 protocol revision deprecates, are the fallback: when the working directory holds no project (Claude Desktop starts servers in `/`), a 2025-era client that reports roots has its first `file://` root used. When none of these gives a project (a client that starts servers in your home or the plugin's folder and reports no roots), each tool call's project is found from the absolute path it names, `path` (or `filename`, for `check_ui` with `code`): the nearest folder at or above it with a `package.json`, `components.json` or config, or the monorepo root above that, but never your home folder or the filesystem root. A project found this way loads a JSON config (`onsystem.config.json`) only: the server runs a JavaScript or TypeScript config only in a project it was started in. Until a call names one, the tools return an error that asks for it; after that, a call without one answers from the project found, as long as only one has been. + +The server speaks MCP over stdio, in both protocol eras: the 2026-07-28 revision (stateless, with `server/discover`) and the 2025 one (the `initialize` handshake), the era chosen by the client's first message. diff --git a/site/test/clients-page.test.ts b/site/test/clients-page.test.ts new file mode 100644 index 00000000..81b39d44 --- /dev/null +++ b/site/test/clients-page.test.ts @@ -0,0 +1,56 @@ +import { createElement } from 'react'; +import { renderToStaticMarkup } from 'react-dom/server'; +import { describe, expect, it, vi } from 'vitest'; + +import ClientsPage from '@/app/docs/clients/page'; + +vi.mock('next/navigation', () => ({ usePathname: () => '/docs/clients' })); + +// /docs/clients is the setup page for every agent but Claude Code with the plugin: after the +// install buttons comes the setup, and how the server finds the project waits for the end. + +const html = renderToStaticMarkup(createElement(ClientsPage)); +const text = (fragment: string) => + fragment + .replace(/<[^>]+>/g, ' ') + .replace(/'/g, "'") + .replace(/"/g, '"') + .replace(/&/g, '&') + .replace(/\s+/g, ' ') + .trim(); +const at = (id: string) => { + const index = html.indexOf(`id="${id}"`); + if (index === -1) throw new Error(`no element with id ${id}`); + return index; +}; + +describe('/docs/clients', () => { + it('opens with the setup, right after the install buttons', () => { + // From the install buttons, the page's first links, to its first section. + const body = html.slice(html.indexOf('Install in VS Code'), at('plugins-for-other-agents')); + const lead = text(/

([\s\S]*?)<\/p>/.exec(body)?.[1] ?? ''); + expect(lead).toContain('Run it from the project, or pass --root'); + expect(lead.split(' ').length).toBeLessThanOrEqual(50); + expect(text(body)).not.toContain('2026-07-28'); + // The one .mcp.json, as a box above the first section. + expect(body).toMatch(/role="note"[\s\S]*\.mcp\.json/); + }); + + it('explains how the server finds the project after every client, before the docs search', () => { + const ids = [...html.matchAll(/

m[1]); + expect(ids.slice(-2)).toEqual([ + 'how-the-server-finds-your-project', + 'search-these-docs-from-your-agent', + ]); + const protocol = html.indexOf('2026-07-28'); + expect(protocol).toBeGreaterThan(at('how-the-server-finds-your-project')); + expect(at('other-clients')).toBeLessThan(at('how-the-server-finds-your-project')); + }); + + it('has the Antigravity and Gemini CLI setups under other clients', () => { + expect(at('antigravity-cli-and-ide')).toBeGreaterThan(at('other-clients')); + const gemini = text(html.slice(at('gemini-cli'), at('antigravity-cli-and-ide'))); + expect(gemini).toContain('gemini mcp add -s user onsystem npx -y onsystem'); + expect(gemini).toContain('only in trusted folders'); + }); +}); diff --git a/test/clients-docs.test.ts b/test/clients-docs.test.ts new file mode 100644 index 00000000..88280897 --- /dev/null +++ b/test/clients-docs.test.ts @@ -0,0 +1,102 @@ +import fs from 'node:fs'; +import path from 'node:path'; + +import { describe, expect, it } from 'vitest'; + +import { blocks, section } from './markdown.js'; + +// docs/clients.md (/docs/clients on the website) is the setup page for every agent but Claude +// Code with the plugin. It opens with the setup, offers one committed file that several clients +// read, and keeps each client's commands to what that client runs today. + +const root = path.resolve(import.meta.dirname, '..'); +const read = (file: string) => + fs.readFileSync(path.join(root, file), 'utf8').replace(/\r\n/g, '\n'); +const clients = read('docs/clients.md'); +const readme = read('README.md'); + +/** What the page says before its first `##` heading. */ +const intro = clients.slice(0, clients.indexOf('\n## ')); + +/** The body of the `
` block whose summary is `title`. */ +function details(title: string): string { + const start = clients.indexOf(`${title}`); + if (start === -1) throw new Error(`no
block for ${title}`); + return clients.slice(start, clients.indexOf('
', start)); +} + +/** The first JSON code block in `markdown`, parsed. */ +function json(markdown: string): unknown { + const [block] = blocks(markdown, 'json'); + if (block === undefined) throw new Error('no JSON code block'); + return JSON.parse(block); +} + +describe('docs/clients.md', () => { + it('opens with the setup, and leaves how the server finds the project for the end', () => { + const lead = intro.split('\n\n')[1] ?? ''; + expect(lead.split(/\s+/).length).toBeLessThanOrEqual(50); + expect(lead).toContain('Run it from the project, or pass `--root`'); + expect([...clients.matchAll(/^## (.+)$/gm)].map((m) => m[1]).at(-1)).toBe( + 'How the server finds your project', + ); + // The protocol eras and the roots fallback come after every client's setup. + const finding = section(clients, 'How the server finds your project'); + for (const detail of ['2026-07-28', '`initialize`', '`file://`', 'MCP roots']) { + expect(intro, detail).not.toContain(detail); + expect(finding, detail).toContain(detail); + } + }); + + it('offers one .mcp.json to commit, at the top, naming the clients that read it', () => { + const box = /^> \[!TIP\]\n((?:>.*\n)+)/m.exec(intro)?.[1]?.replace(/^> ?/gm, '') ?? ''; + expect(box).toContain('`.mcp.json`'); + for (const client of ['Claude Code', 'VS Code', 'GitHub Copilot CLI', 'Grok Build']) { + expect(box, client).toContain(client); + } + expect(json(box)).toEqual({ + mcpServers: { onsystem: { command: 'npx', args: ['-y', 'onsystem'] } }, + }); + // The Claude Code plugin registers the same tools: one or the other, not both. + expect(box).toMatch(/instead of the plugin/); + }); + + it('installs the Copilot CLI plugin from the marketplace, not by the deprecated direct install', () => { + const plugins = section(clients, 'Plugins for other agents'); + expect(plugins).toContain( + '```sh\n copilot plugin marketplace add dgesteves/onsystem\n copilot plugin install onsystem@dgesteves\n ```', + ); + expect(clients).not.toMatch(/copilot plugin install dgesteves\//); + }); + + it('says the hook runs in Codex too, on the files apply_patch changes', () => { + expect(clients).not.toMatch(/only (?:the )?Claude Code(?: plugin)? has the hook/i); + expect(intro).toContain('Claude Code and Codex CLI'); + expect(section(clients, 'Plugins for other agents')).toContain('`apply_patch`'); + }); + + it('adds Gemini CLI from the terminal, and says it starts servers only in trusted folders', () => { + const gemini = details('Gemini CLI'); + expect(gemini).toContain( + 'gemini mcp add -s user onsystem npx -y onsystem --root /absolute/path/to/app', + ); + expect(gemini).toContain('only in trusted folders'); + expect(gemini).toContain('`/permissions`'); + expect(gemini).toContain('`--skip-trust`'); + }); + + it('has a block for Antigravity, which reads its own file, with the same server entry', () => { + const antigravity = details('Antigravity (CLI and IDE)'); + expect(antigravity).toContain('`~/.gemini/config/mcp_config.json`'); + expect(antigravity).toContain('`.agents/mcp_config.json`'); + expect(json(antigravity)).toEqual(json(details('Gemini CLI'))); + }); +}); + +describe('the README', () => { + it('lists Antigravity with the other clients', () => { + const top = readme.slice(0, readme.indexOf('')); + expect(top).toContain('](https://onsystem.vercel.app/docs/clients#antigravity-cli-and-ide)'); + expect(readme).toMatch(/\[configs for [^\]]*Antigravity[^\]]*\]/); + }); +}); From ffd8a7ec3847082fd820af8457a3f3587cff8b34 Mon Sep 17 00:00:00 2001 From: Diogo Esteves Date: Wed, 21 Oct 2026 09:38:03 +0100 Subject: [PATCH 2/2] docs(clients): keep the Claude Code plugin next to the team's .mcp.json The .mcp.json box told Claude Code teams to use the file instead of the plugin, which drops the hook. Claude Code now keeps the plugin and turns the .mcp.json entry off with "disabledMcpjsonServers": ["onsystem"] in the same .claude/settings.json, so a mixed team gets the hook without the tools registered twice. docs/rollout.md says the same next to its settings file. --- docs/clients.md | 6 ++++-- docs/rollout.md | 2 +- test/clients-docs.test.ts | 8 ++++++-- test/rollout-docs.test.ts | 3 +++ 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/docs/clients.md b/docs/clients.md index 23e95483..5f30c4c1 100644 --- a/docs/clients.md +++ b/docs/clients.md @@ -5,7 +5,7 @@ Pick your client below and add the server. Run it from the project, or pass `--r Every client gets the same five tools, including `check_ui`, which the agent runs on its own output. Claude Code and Codex CLI also run the [plugin](plugin.md)'s hook, which checks each edit as it happens, so there use the plugin instead; with other agents, add the [CI check](ci.md) so what the agent skips still gets caught. > [!TIP] -> **One `.mcp.json` for the team.** Commit this file at the repository root, and Claude Code, VS Code, GitHub Copilot CLI and Grok Build start the server from it once each person trusts the folder or approves the server: +> **One `.mcp.json` for the team.** Commit this file at the repository root, and VS Code, GitHub Copilot CLI and Grok Build start the server from it once each person trusts the folder or approves the server: > > ```json > { @@ -18,7 +18,9 @@ Every client gets the same five tools, including `check_ui`, which the agent run > } > ``` > -> It needs no `--root`: the server finds the project from the folder it starts in, the roots the client reports, or the files the tools are given. In Claude Code it registers the same tools as the plugin, so use it there instead of the plugin, not next to it; [Roll out to a team](rollout.md#give-every-agent-the-design-system) commits the plugin, hook included. Cursor and the other clients read their own files, below. +> It needs no `--root`: the server finds the project from the folder it starts in, the roots the client reports, or the files the tools are given. Cursor and the other clients read their own files, below. +> +> Claude Code reads this file too, but there the plugin gives the same tools plus the hook. A team on Claude Code commits the plugin ([Roll out to a team](rollout.md#give-every-agent-the-design-system)) and adds `"disabledMcpjsonServers": ["onsystem"]` to the same `.claude/settings.json`, so Claude Code does not register the tools twice. ## Plugins for other agents diff --git a/docs/rollout.md b/docs/rollout.md index be4fc52d..e00f1457 100644 --- a/docs/rollout.md +++ b/docs/rollout.md @@ -64,7 +64,7 @@ Commit these at the repository root. } ``` -Claude Code adds the marketplace once each teammate accepts its trust dialog for the folder, and ignores it without a message until then. The plugin then loads from the marketplace, with no `/plugin install`. Claude Code reads this file from the folder it starts in, so start it at the root. Cloud sessions (Claude Code on the web) do not load plugins from a repository's settings; the pull request check still covers what they push. No `.mcp.json` entry for onsystem goes next to it: the plugin and that entry register the same tools ([plugin](plugin.md)). +Claude Code adds the marketplace once each teammate accepts its trust dialog for the folder, and ignores it without a message until then. The plugin then loads from the marketplace, with no `/plugin install`. Claude Code reads this file from the folder it starts in, so start it at the root. Cloud sessions (Claude Code on the web) do not load plugins from a repository's settings; the pull request check still covers what they push. No `.mcp.json` entry for onsystem goes next to it: the plugin and that entry register the same tools ([plugin](plugin.md)). If the repository commits [one `.mcp.json`](clients.md) for the other clients, add `"disabledMcpjsonServers": ["onsystem"]` to this file, so Claude Code skips that entry. **Cursor** and **VS Code** get the MCP server, started in the workspace folder, which at a monorepo root serves every project ([set up your agent](clients.md#cursor-and-vs-code)): diff --git a/test/clients-docs.test.ts b/test/clients-docs.test.ts index 88280897..8c2b2d09 100644 --- a/test/clients-docs.test.ts +++ b/test/clients-docs.test.ts @@ -57,8 +57,12 @@ describe('docs/clients.md', () => { expect(json(box)).toEqual({ mcpServers: { onsystem: { command: 'npx', args: ['-y', 'onsystem'] } }, }); - // The Claude Code plugin registers the same tools: one or the other, not both. - expect(box).toMatch(/instead of the plugin/); + // Claude Code reads the file too, but keeps the plugin, which adds the hook, and turns this + // entry off so it does not register the same tools twice. + expect(box).not.toMatch(/instead of the plugin/); + expect(box).toContain('`"disabledMcpjsonServers": ["onsystem"]`'); + expect(box).toContain('rollout.md#give-every-agent-the-design-system'); + expect(intro).toContain('so there use the plugin instead'); }); it('installs the Copilot CLI plugin from the marketplace, not by the deprecated direct install', () => { diff --git a/test/rollout-docs.test.ts b/test/rollout-docs.test.ts index ce350c00..9be1b7d5 100644 --- a/test/rollout-docs.test.ts +++ b/test/rollout-docs.test.ts @@ -118,6 +118,9 @@ describe('the team rollout page (docs/rollout.md)', () => { expect(agents).toContain('start it at the root'); // The plugin and a .mcp.json entry register the same tools twice. expect(agents).toContain('No `.mcp.json` entry for onsystem'); + // A .mcp.json committed for the other clients is turned off for Claude Code, as + // docs/clients.md says. + expect(agents).toContain('`"disabledMcpjsonServers": ["onsystem"]`'); }); it('commits the Cursor and VS Code configs that docs/clients.md shows', () => {