From fa300ff22022b4c29bf5824b0e9138769815b0cf Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Fri, 23 Oct 2026 20:16:29 -0700 Subject: [PATCH 1/7] fix(byo): use configured API URL in connect commands Co-authored-by: Polish Agent-Model: codex/gpt-6-sol/medium --- .../V2AgentBYOListenSnippet.test.tsx | 24 +++++++++++++++++++ frontend/src/v2/components/V2AgentBYO.tsx | 5 ++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/frontend/src/v2/__tests__/V2AgentBYOListenSnippet.test.tsx b/frontend/src/v2/__tests__/V2AgentBYOListenSnippet.test.tsx index a7bc5db42d..8e82cb220c 100644 --- a/frontend/src/v2/__tests__/V2AgentBYOListenSnippet.test.tsx +++ b/frontend/src/v2/__tests__/V2AgentBYOListenSnippet.test.tsx @@ -64,6 +64,30 @@ const issueToken = async () => { }; describe('BYO listener snippet', () => { + test('connect commands use the configured staging API instead of production', async () => { + const previousApiUrl = process.env.REACT_APP_API_URL; + process.env.REACT_APP_API_URL = 'https://api-staging.commonly.me/'; + try { + await issueToken(); + const commands = Array.from(document.querySelectorAll('.v2-byo__pre')) + .map((el) => el.textContent || '') + .filter((text) => text.includes('COMMONLY_API_URL=')); + expect(commands).toHaveLength(2); + commands.forEach((command) => { + expect(command).toContain('COMMONLY_API_URL=https://api-staging.commonly.me'); + expect(command).not.toContain('api.commonly.me'); + }); + const cursorConfig = Array.from(document.querySelectorAll('.v2-byo__pre')) + .map((el) => el.textContent || '') + .find((text) => text.includes('mcpServers')); + expect(JSON.parse(cursorConfig || '').mcpServers.commonly.env.COMMONLY_API_URL) + .toBe('https://api-staging.commonly.me'); + } finally { + if (previousApiUrl === undefined) delete process.env.REACT_APP_API_URL; + else process.env.REACT_APP_API_URL = previousApiUrl; + } + }); + // QA BYO walk 1 (2026-10-16): four equal Copy boxes, and the one titled // "Claude Code" was the MCP line, which does not make the agent answer. The // command that does is THE box: first, and the only one not marked optional diff --git a/frontend/src/v2/components/V2AgentBYO.tsx b/frontend/src/v2/components/V2AgentBYO.tsx index 5d34d92787..ba5d6c043b 100644 --- a/frontend/src/v2/components/V2AgentBYO.tsx +++ b/frontend/src/v2/components/V2AgentBYO.tsx @@ -19,6 +19,7 @@ import React, { useEffect, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import axios from '../../utils/axiosConfig'; +import getApiBaseUrl from '../../utils/apiBaseUrl'; import V2FeaturePage from './V2FeaturePage'; import V2Avatar from './V2Avatar'; import V2Hint from './V2Hint'; @@ -855,9 +856,7 @@ const V2AgentBYO: React.FC = () => { const chooseMode = (nextMode: 'hosted' | 'byo' | 'machine') => setMode(nextMode); - const apiUrl = typeof window !== 'undefined' && /api-dev|api\./.test(window.location.hostname) - ? `https://${window.location.hostname.replace(/^app/, 'api')}` - : 'https://api.commonly.me'; + const apiUrl = getApiBaseUrl().replace(/\/+$/, ''); const claudeSnippet = issued ? `claude mcp add commonly \\\n -e COMMONLY_API_URL=${apiUrl} \\\n -e COMMONLY_AGENT_TOKEN=${issued.token} \\\n -- npx -y @commonlyai/mcp` From ab5824a0118e37e4593043c3d3c890291eb0c006 Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Fri, 23 Oct 2026 20:17:56 -0700 Subject: [PATCH 2/7] fix(connect): use instance API in MCP command Co-authored-by: Polish Agent-Model: codex/gpt-6-sol/medium --- frontend/src/v2/__tests__/V2ConnectPage.test.tsx | 14 ++++++++++++++ frontend/src/v2/components/V2ConnectPage.tsx | 10 +++++----- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/frontend/src/v2/__tests__/V2ConnectPage.test.tsx b/frontend/src/v2/__tests__/V2ConnectPage.test.tsx index 2dc93c1b0c..1564d23802 100644 --- a/frontend/src/v2/__tests__/V2ConnectPage.test.tsx +++ b/frontend/src/v2/__tests__/V2ConnectPage.test.tsx @@ -40,6 +40,20 @@ const CurrentPath = () =>
{useLocation().pathnam afterEach(() => jest.clearAllMocks()); describe('V2ConnectPage', () => { + test('the MCP command targets this instance API', () => { + const previousApiUrl = process.env.REACT_APP_API_URL; + process.env.REACT_APP_API_URL = 'https://api.example.test/'; + try { + renderConnect(); + const snippet = screen.getByText(/COMMONLY_AGENT_TOKEN=cm_agent_…/).textContent || ''; + expect(snippet).toContain('COMMONLY_API_URL=https://api.example.test'); + expect(snippet).not.toContain('api.commonly.me'); + } finally { + if (previousApiUrl === undefined) delete process.env.REACT_APP_API_URL; + else process.env.REACT_APP_API_URL = previousApiUrl; + } + }); + test('gives every member a copyable CLI/MCP start and does not tease instance keys', async () => { const clipboard = { writeText: jest.fn().mockResolvedValue(undefined) }; Object.assign(navigator, { clipboard }); diff --git a/frontend/src/v2/components/V2ConnectPage.tsx b/frontend/src/v2/components/V2ConnectPage.tsx index 2015680141..42f6c9195b 100644 --- a/frontend/src/v2/components/V2ConnectPage.tsx +++ b/frontend/src/v2/components/V2ConnectPage.tsx @@ -1,17 +1,13 @@ import React, { useState } from 'react'; import { Link } from 'react-router-dom'; import axios from '../../utils/axiosConfig'; +import getApiBaseUrl from '../../utils/apiBaseUrl'; import { useAuth } from '../../context/AuthContext'; type CopyKey = 'cli' | 'mcp' | 'gateway'; const cliSnippet = 'npm install -g @commonlyai/cli\ncommonly login'; -const mcpSnippet = `claude mcp add commonly \\ - -e COMMONLY_API_URL=https://api.commonly.me \\ - -e COMMONLY_AGENT_TOKEN=cm_agent_… \\ - -- npx -y @commonlyai/mcp`; - const CopyButton: React.FC<{ value: string; copyKey: CopyKey; copied: CopyKey | null; onCopy: (key: CopyKey, value: string) => void }> = ({ value, copyKey, copied, onCopy, }) => ( @@ -21,6 +17,10 @@ const CopyButton: React.FC<{ value: string; copyKey: CopyKey; copied: CopyKey | ); const V2ConnectPage: React.FC = () => { + const mcpSnippet = `claude mcp add commonly \\ + -e COMMONLY_API_URL=${getApiBaseUrl().replace(/\/+$/, '')} \\ + -e COMMONLY_AGENT_TOKEN=cm_agent_… \\ + -- npx -y @commonlyai/mcp`; const { currentUser } = useAuth(); const isAdmin = currentUser?.role === 'admin'; const [copied, setCopied] = useState(null); From 5ccf0aca163d7f79a031258f02fae86bd2bd4bac Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Fri, 23 Oct 2026 20:21:24 -0700 Subject: [PATCH 3/7] fix(connect): target instance in CLI login command Co-authored-by: Polish Agent-Model: codex/gpt-6-sol/medium --- .../src/v2/__tests__/V2ConnectPage.test.tsx | 17 ++++++++++++----- frontend/src/v2/components/V2ConnectPage.tsx | 6 +++--- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/frontend/src/v2/__tests__/V2ConnectPage.test.tsx b/frontend/src/v2/__tests__/V2ConnectPage.test.tsx index 1564d23802..88df75318a 100644 --- a/frontend/src/v2/__tests__/V2ConnectPage.test.tsx +++ b/frontend/src/v2/__tests__/V2ConnectPage.test.tsx @@ -40,14 +40,21 @@ const CurrentPath = () =>
{useLocation().pathnam afterEach(() => jest.clearAllMocks()); describe('V2ConnectPage', () => { - test('the MCP command targets this instance API', () => { + test('the CLI and MCP commands target this instance API', async () => { const previousApiUrl = process.env.REACT_APP_API_URL; process.env.REACT_APP_API_URL = 'https://api.example.test/'; try { + const clipboard = { writeText: jest.fn().mockResolvedValue(undefined) }; + Object.assign(navigator, { clipboard }); renderConnect(); - const snippet = screen.getByText(/COMMONLY_AGENT_TOKEN=cm_agent_…/).textContent || ''; - expect(snippet).toContain('COMMONLY_API_URL=https://api.example.test'); - expect(snippet).not.toContain('api.commonly.me'); + const cliSnippet = screen.getByText(/commonly login --instance/).textContent || ''; + const mcpSnippet = screen.getByText(/COMMONLY_AGENT_TOKEN=cm_agent_…/).textContent || ''; + expect(cliSnippet).toContain('commonly login --instance https://api.example.test'); + expect(mcpSnippet).toContain('COMMONLY_API_URL=https://api.example.test'); + expect(cliSnippet).not.toContain('api.commonly.me'); + expect(mcpSnippet).not.toContain('api.commonly.me'); + fireEvent.click(screen.getAllByRole('button', { name: 'Copy' })[0]); + await waitFor(() => expect(clipboard.writeText).toHaveBeenCalledWith(cliSnippet)); } finally { if (previousApiUrl === undefined) delete process.env.REACT_APP_API_URL; else process.env.REACT_APP_API_URL = previousApiUrl; @@ -69,7 +76,7 @@ describe('V2ConnectPage', () => { expect(screen.queryByRole('link', { name: 'Open global integrations' })).not.toBeInTheDocument(); fireEvent.click(screen.getAllByRole('button', { name: 'Copy' })[0]); - await waitFor(() => expect(clipboard.writeText).toHaveBeenCalledWith('npm install -g @commonlyai/cli\ncommonly login')); + await waitFor(() => expect(clipboard.writeText).toHaveBeenCalledWith(expect.stringMatching(/^npm install -g @commonlyai\/cli\ncommonly login --instance https?:\/\//))); }); test('shows the existing gateway action and global integrations only to admins', async () => { diff --git a/frontend/src/v2/components/V2ConnectPage.tsx b/frontend/src/v2/components/V2ConnectPage.tsx index 42f6c9195b..c046746795 100644 --- a/frontend/src/v2/components/V2ConnectPage.tsx +++ b/frontend/src/v2/components/V2ConnectPage.tsx @@ -6,8 +6,6 @@ import { useAuth } from '../../context/AuthContext'; type CopyKey = 'cli' | 'mcp' | 'gateway'; -const cliSnippet = 'npm install -g @commonlyai/cli\ncommonly login'; - const CopyButton: React.FC<{ value: string; copyKey: CopyKey; copied: CopyKey | null; onCopy: (key: CopyKey, value: string) => void }> = ({ value, copyKey, copied, onCopy, }) => ( @@ -17,8 +15,10 @@ const CopyButton: React.FC<{ value: string; copyKey: CopyKey; copied: CopyKey | ); const V2ConnectPage: React.FC = () => { + const apiBaseUrl = getApiBaseUrl().replace(/\/+$/, ''); + const cliSnippet = `npm install -g @commonlyai/cli\ncommonly login --instance ${apiBaseUrl}`; const mcpSnippet = `claude mcp add commonly \\ - -e COMMONLY_API_URL=${getApiBaseUrl().replace(/\/+$/, '')} \\ + -e COMMONLY_API_URL=${apiBaseUrl} \\ -e COMMONLY_AGENT_TOKEN=cm_agent_… \\ -- npx -y @commonlyai/mcp`; const { currentUser } = useAuth(); From eacdc506232e80532c8a0940f7fa6cdd22008e67 Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Fri, 23 Oct 2026 21:06:12 -0700 Subject: [PATCH 4/7] Add Cursor MCP install links for each instance Co-authored-by: Polish Agent-Model: codex/gpt-6-sol/medium --- .cursor/rules/commonly.mdc | 10 ++++++++++ .gitignore | 5 ++++- frontend/src/i18n/locales/en.json | 4 +++- frontend/src/i18n/locales/zh-CN.json | 4 +++- .../V2AgentBYOListenSnippet.test.tsx | 19 +++++++++++++++++++ .../src/v2/__tests__/V2ConnectPage.test.tsx | 8 ++++++++ frontend/src/v2/components/V2AgentBYO.tsx | 4 ++++ frontend/src/v2/components/V2ConnectPage.tsx | 6 ++++++ frontend/src/v2/utils/cursorMcpInstallLink.ts | 18 ++++++++++++++++++ frontend/src/v2/v2.css | 18 ++++++++++++++++++ 10 files changed, 93 insertions(+), 3 deletions(-) create mode 100644 .cursor/rules/commonly.mdc create mode 100644 frontend/src/v2/utils/cursorMcpInstallLink.ts diff --git a/.cursor/rules/commonly.mdc b/.cursor/rules/commonly.mdc new file mode 100644 index 0000000000..5d7f8c1b2c --- /dev/null +++ b/.cursor/rules/commonly.mdc @@ -0,0 +1,10 @@ +--- +description: Commonly repository guidance for Cursor +alwaysApply: true +--- + +Read [AGENTS.md](../../AGENTS.md) before changing this repository. It defines the product model, required architecture documents, review rules, and test expectations. + +For agent connection changes, keep the Commonly instance URL configurable. Use the frontend's `getApiBaseUrl()` and pass `--instance` to CLI login commands; never send a self-hosted instance's agent key to the public instance by default. + +Keep agent keys out of URLs, logs, and committed files. Run focused tests for changed behavior and follow [REVIEW.md](../../REVIEW.md) before a PR. diff --git a/.gitignore b/.gitignore index 3f2a43a2ff..a132d8eeb7 100644 --- a/.gitignore +++ b/.gitignore @@ -18,7 +18,10 @@ dist/ *.pem -.cursor/ +/.cursor/* +!/.cursor/rules/ +/.cursor/rules/* +!/.cursor/rules/commonly.mdc # Playwright /test-results/ diff --git a/frontend/src/i18n/locales/en.json b/frontend/src/i18n/locales/en.json index 5824c870cb..8e2d2d2c7c 100644 --- a/frontend/src/i18n/locales/en.json +++ b/frontend/src/i18n/locales/en.json @@ -1462,7 +1462,9 @@ "snippets": { "runtimeToken": "The key on its own", "claudeCode": "Optional: let Claude Code use the pod in your own sessions", - "cursor": "Use the pod from Cursor via MCP — add to ~/.cursor/mcp.json", + "cursor": "Use the pod from Cursor via MCP", + "cursorInstall": "Add to Cursor", + "cursorInstallHint": "Cursor opens with this instance. Replace the placeholder key in Cursor’s MCP settings with the key above.", "memory": "Bring its memory (optional)", "claudeCodeBody": "Gives your own Claude Code sessions Commonly’s tools. It does not make {{name}} answer @mentions; the command above does.", "claudeCodeBodyOwn": "Gives your own Claude Code sessions Commonly’s tools.", diff --git a/frontend/src/i18n/locales/zh-CN.json b/frontend/src/i18n/locales/zh-CN.json index a74df2e5d7..4b0900d99e 100644 --- a/frontend/src/i18n/locales/zh-CN.json +++ b/frontend/src/i18n/locales/zh-CN.json @@ -1522,7 +1522,9 @@ "snippets": { "runtimeToken": "仅密钥", "claudeCode": "可选:让 Claude Code 在你自己的会话里使用这个 Pod", - "cursor": "通过 MCP 在 Cursor 中使用这个 Pod——添加到 ~/.cursor/mcp.json", + "cursor": "通过 MCP 在 Cursor 中使用这个 Pod", + "cursorInstall": "添加到 Cursor", + "cursorInstallHint": "Cursor 会连接到此实例。请在 Cursor 的 MCP 设置中将占位密钥替换为上面的密钥。", "memory": "导入它的记忆(可选)", "claudeCodeBody": "为你自己的 Claude Code 会话加上 Commonly 的工具。它不会让 {{name}} 回复 @提及,上面那条命令才会。", "claudeCodeBodyOwn": "为你自己的 Claude Code 会话加上 Commonly 的工具。", diff --git a/frontend/src/v2/__tests__/V2AgentBYOListenSnippet.test.tsx b/frontend/src/v2/__tests__/V2AgentBYOListenSnippet.test.tsx index 8e82cb220c..36d552beaf 100644 --- a/frontend/src/v2/__tests__/V2AgentBYOListenSnippet.test.tsx +++ b/frontend/src/v2/__tests__/V2AgentBYOListenSnippet.test.tsx @@ -88,6 +88,25 @@ describe('BYO listener snippet', () => { } }); + test('the Cursor install link uses this instance without putting the issued key in its URL', async () => { + const previousApiUrl = process.env.REACT_APP_API_URL; + process.env.REACT_APP_API_URL = 'https://api.example.test/'; + try { + await issueToken(); + const href = screen.getByRole('link', { name: 'Add to Cursor', hidden: true }).getAttribute('href') || ''; + const config = JSON.parse(atob(decodeURIComponent(href.split('config=')[1]))); + expect(config.env).toEqual({ + COMMONLY_API_URL: 'https://api.example.test', + COMMONLY_AGENT_TOKEN: 'PASTE_AGENT_TOKEN_HERE', + }); + expect(href).not.toContain('cm_agent_test_token'); + expect(href).not.toContain('api.commonly.me'); + } finally { + if (previousApiUrl === undefined) delete process.env.REACT_APP_API_URL; + else process.env.REACT_APP_API_URL = previousApiUrl; + } + }); + // QA BYO walk 1 (2026-10-16): four equal Copy boxes, and the one titled // "Claude Code" was the MCP line, which does not make the agent answer. The // command that does is THE box: first, and the only one not marked optional diff --git a/frontend/src/v2/__tests__/V2ConnectPage.test.tsx b/frontend/src/v2/__tests__/V2ConnectPage.test.tsx index 88df75318a..32ed6c3441 100644 --- a/frontend/src/v2/__tests__/V2ConnectPage.test.tsx +++ b/frontend/src/v2/__tests__/V2ConnectPage.test.tsx @@ -53,6 +53,14 @@ describe('V2ConnectPage', () => { expect(mcpSnippet).toContain('COMMONLY_API_URL=https://api.example.test'); expect(cliSnippet).not.toContain('api.commonly.me'); expect(mcpSnippet).not.toContain('api.commonly.me'); + const cursorHref = screen.getByRole('link', { name: 'Add Commonly to Cursor' }).getAttribute('href') || ''; + expect(cursorHref).toMatch(/^cursor:\/\/anysphere\.cursor-deeplink\/mcp\/install\?name=commonly&config=/); + const cursorConfig = JSON.parse(atob(decodeURIComponent(cursorHref.split('config=')[1]))); + expect(cursorConfig.env).toEqual({ + COMMONLY_API_URL: 'https://api.example.test', + COMMONLY_AGENT_TOKEN: 'PASTE_AGENT_TOKEN_HERE', + }); + expect(cursorHref).not.toContain('api.commonly.me'); fireEvent.click(screen.getAllByRole('button', { name: 'Copy' })[0]); await waitFor(() => expect(clipboard.writeText).toHaveBeenCalledWith(cliSnippet)); } finally { diff --git a/frontend/src/v2/components/V2AgentBYO.tsx b/frontend/src/v2/components/V2AgentBYO.tsx index ba5d6c043b..c1577ee263 100644 --- a/frontend/src/v2/components/V2AgentBYO.tsx +++ b/frontend/src/v2/components/V2AgentBYO.tsx @@ -30,6 +30,7 @@ import { PERSONA_CARDS } from '../agents/personaCatalogData'; import { DEFAULT_INSTALL_SCOPES } from '../utils/agentInstallScopes'; import { readPodVisits } from '../lib/podRecency'; import { AgentConnection, connectionLabel } from '../utils/agentConnection'; +import cursorMcpInstallLink from '../utils/cursorMcpInstallLink'; const DEFAULT_AGENT_NAME = 'my-mcp-agent'; // The token routes refuse a name that belongs to an agent Commonly runs (the @@ -896,6 +897,7 @@ const V2AgentBYO: React.FC = () => { }, }, null, 2) : ''; + const cursorInstallHref = cursorMcpInstallLink(apiUrl); return ( {
{t('agentByo.snippets.cursor')}
+

{t('agentByo.snippets.cursorInstallHint')}

+ {t('agentByo.snippets.cursorInstall')}
{cursorSnippet}
+
+ Add Commonly to Cursor + Add your agent key in Cursor’s MCP settings. +
Manage connected CLI devices diff --git a/frontend/src/v2/utils/cursorMcpInstallLink.ts b/frontend/src/v2/utils/cursorMcpInstallLink.ts new file mode 100644 index 0000000000..ce0ca6b56c --- /dev/null +++ b/frontend/src/v2/utils/cursorMcpInstallLink.ts @@ -0,0 +1,18 @@ +// Cursor's install deeplink contains its MCP configuration in the URL. Keep +// agent keys out of it; the user adds the key in Cursor after installation. +export const CURSOR_TOKEN_PLACEHOLDER = 'PASTE_AGENT_TOKEN_HERE'; + +const cursorMcpInstallLink = (apiUrl: string): string => { + const config = { + command: 'npx', + args: ['-y', '@commonlyai/mcp'], + env: { + COMMONLY_API_URL: apiUrl.replace(/\/+$/, ''), + COMMONLY_AGENT_TOKEN: CURSOR_TOKEN_PLACEHOLDER, + }, + }; + const encodedConfig = btoa(JSON.stringify(config)); + return `cursor://anysphere.cursor-deeplink/mcp/install?name=commonly&config=${encodeURIComponent(encodedConfig)}`; +}; + +export default cursorMcpInstallLink; diff --git a/frontend/src/v2/v2.css b/frontend/src/v2/v2.css index 1c72c468fb..a656e93d76 100644 --- a/frontend/src/v2/v2.css +++ b/frontend/src/v2/v2.css @@ -6481,6 +6481,13 @@ body.modern-ui.v2-canvas { color: var(--v2-accent-text); font: 500 13px/20px var(--v2-font); } +.v2-root a.v2-byo__cursor-link { + align-self: flex-start; + color: var(--v2-accent-text); + font: 500 13px/20px var(--v2-font); + text-decoration: none; +} +.v2-root a.v2-byo__cursor-link:hover { text-decoration: underline; } .v2-root button.v2-byo__secondary { align-self: flex-start; padding: 10px 18px; @@ -6762,6 +6769,17 @@ body.modern-ui.v2-canvas { text-decoration: underline; } +.v2-connect__cursor { + display: flex; + flex-wrap: wrap; + align-items: baseline; + gap: 4px 12px; + margin-top: 12px; + color: var(--v2-text-tertiary); + font: 400 13px/20px var(--v2-font); +} +.v2-root .v2-connect__cursor .v2-connect__link { margin-top: 0; } + .v2-connect__actions { display: flex; flex-wrap: wrap; From cdc1bb27d39a878efe349e4a1d8c0e1f668255c3 Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Fri, 23 Oct 2026 21:27:34 -0700 Subject: [PATCH 5/7] Make Cursor rule describe pod coordination and session limits Co-authored-by: Polish Agent-Model: codex/gpt-6-sol/medium --- .cursor/rules/commonly.mdc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.cursor/rules/commonly.mdc b/.cursor/rules/commonly.mdc index 5d7f8c1b2c..1baf47963f 100644 --- a/.cursor/rules/commonly.mdc +++ b/.cursor/rules/commonly.mdc @@ -1,10 +1,10 @@ --- -description: Commonly repository guidance for Cursor +description: Use Commonly as the shared pod for Cursor work alwaysApply: true --- -Read [AGENTS.md](../../AGENTS.md) before changing this repository. It defines the product model, required architecture documents, review rules, and test expectations. +When a task names a Commonly pod, call `commonly_get_context(podId)` before starting so you have its current priorities and recent messages. Use `commonly_get_messages` when you need more history. Post a concise result or handoff to that same pod with `commonly_post_message`; avoid step-by-step progress chatter. -For agent connection changes, keep the Commonly instance URL configurable. Use the frontend's `getApiBaseUrl()` and pass `--instance` to CLI login commands; never send a self-hosted instance's agent key to the public instance by default. +Cursor's MCP connection lets this session use Commonly tools. It does not watch for mentions or wake Cursor while no session is open. Do not claim that a Cursor agent is listening for @mentions unless a separate listener has been set up and verified. -Keep agent keys out of URLs, logs, and committed files. Run focused tests for changed behavior and follow [REVIEW.md](../../REVIEW.md) before a PR. +Keep agent keys out of pod messages, URLs, logs, and committed files. For work in this repository, follow [AGENTS.md](../../AGENTS.md) and [REVIEW.md](../../REVIEW.md). From fa64de6938358d37184676591a66b6fa595ee1c8 Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Fri, 23 Oct 2026 21:44:33 -0700 Subject: [PATCH 6/7] Clarify Cursor setup on BYO page Co-authored-by: Polish Agent-Model: codex/gpt-6-sol/medium --- frontend/src/i18n/locales/en.json | 4 ++-- frontend/src/i18n/locales/zh-CN.json | 4 ++-- .../src/v2/__tests__/V2AgentBYOListenSnippet.test.tsx | 9 +++++++++ frontend/src/v2/components/V2AgentBYO.tsx | 2 +- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/frontend/src/i18n/locales/en.json b/frontend/src/i18n/locales/en.json index 8e2d2d2c7c..d914e5a5be 100644 --- a/frontend/src/i18n/locales/en.json +++ b/frontend/src/i18n/locales/en.json @@ -1462,9 +1462,9 @@ "snippets": { "runtimeToken": "The key on its own", "claudeCode": "Optional: let Claude Code use the pod in your own sessions", - "cursor": "Use the pod from Cursor via MCP", + "cursor": "Use the pod from Cursor via MCP — add to ~/.cursor/mcp.json", "cursorInstall": "Add to Cursor", - "cursorInstallHint": "Cursor opens with this instance. Replace the placeholder key in Cursor’s MCP settings with the key above.", + "cursorInstallHint": "The link adds Commonly with a placeholder key. Replace it in Cursor’s MCP settings with the key above.", "memory": "Bring its memory (optional)", "claudeCodeBody": "Gives your own Claude Code sessions Commonly’s tools. It does not make {{name}} answer @mentions; the command above does.", "claudeCodeBodyOwn": "Gives your own Claude Code sessions Commonly’s tools.", diff --git a/frontend/src/i18n/locales/zh-CN.json b/frontend/src/i18n/locales/zh-CN.json index 4b0900d99e..eeeed86922 100644 --- a/frontend/src/i18n/locales/zh-CN.json +++ b/frontend/src/i18n/locales/zh-CN.json @@ -1522,9 +1522,9 @@ "snippets": { "runtimeToken": "仅密钥", "claudeCode": "可选:让 Claude Code 在你自己的会话里使用这个 Pod", - "cursor": "通过 MCP 在 Cursor 中使用这个 Pod", + "cursor": "通过 MCP 在 Cursor 中使用这个 Pod——添加到 ~/.cursor/mcp.json", "cursorInstall": "添加到 Cursor", - "cursorInstallHint": "Cursor 会连接到此实例。请在 Cursor 的 MCP 设置中将占位密钥替换为上面的密钥。", + "cursorInstallHint": "该链接会以占位密钥添加 Commonly。请在 Cursor 的 MCP 设置中将其替换为上面的密钥。", "memory": "导入它的记忆(可选)", "claudeCodeBody": "为你自己的 Claude Code 会话加上 Commonly 的工具。它不会让 {{name}} 回复 @提及,上面那条命令才会。", "claudeCodeBodyOwn": "为你自己的 Claude Code 会话加上 Commonly 的工具。", diff --git a/frontend/src/v2/__tests__/V2AgentBYOListenSnippet.test.tsx b/frontend/src/v2/__tests__/V2AgentBYOListenSnippet.test.tsx index 36d552beaf..c86e6b97aa 100644 --- a/frontend/src/v2/__tests__/V2AgentBYOListenSnippet.test.tsx +++ b/frontend/src/v2/__tests__/V2AgentBYOListenSnippet.test.tsx @@ -107,6 +107,15 @@ describe('BYO listener snippet', () => { } }); + test('the Cursor link leads its guidance, while the JSON still names its destination', async () => { + await issueToken(); + const link = screen.getByRole('link', { name: 'Add to Cursor', hidden: true }); + const hint = link.nextElementSibling; + expect(hint).toHaveClass('v2-byo__hint'); + expect(hint).toHaveTextContent('The link adds Commonly with a placeholder key.'); + expect(link.closest('.v2-byo__snippet')).toHaveTextContent('~/.cursor/mcp.json'); + }); + // QA BYO walk 1 (2026-10-16): four equal Copy boxes, and the one titled // "Claude Code" was the MCP line, which does not make the agent answer. The // command that does is THE box: first, and the only one not marked optional diff --git a/frontend/src/v2/components/V2AgentBYO.tsx b/frontend/src/v2/components/V2AgentBYO.tsx index c1577ee263..0493894e13 100644 --- a/frontend/src/v2/components/V2AgentBYO.tsx +++ b/frontend/src/v2/components/V2AgentBYO.tsx @@ -1487,8 +1487,8 @@ const V2AgentBYO: React.FC = () => {
{t('agentByo.snippets.cursor')}
-

{t('agentByo.snippets.cursorInstallHint')}

{t('agentByo.snippets.cursorInstall')} +

{t('agentByo.snippets.cursorInstallHint')}

{cursorSnippet}