docs(onboarding): fix Claude Code channel setup snippet served by canvas #1661

Merged
hongming merged 2 commits from docs-fix-claude-code-channel-template into main 2026-05-22 00:44:01 +00:00
Member

Summary

Fixes three real onboarding potholes in the canvas-served Claude Code channel snippet at workspace-server/internal/handlers/external_connection.go:externalChannelTemplate:

  1. Broken launch flag formclaude --dangerously-load-development-channels --channels plugin:molecule@molecule-channel errors with entries must be tagged: --channels (the --channels flag does not exist). Fixed to the working single-flag form claude --dangerously-load-development-channels plugin:molecule@molecule-channel.
  2. Legacy .env shape — Was MOLECULE_PLATFORM_URL + comma-separated IDs/TOKENS (single-tenant). Fixed to the canonical MOLECULE_WORKSPACES_JSON=[{id,token,platform_url}] shape (multi-tenant, post-PR#15 SSOT in molecule-mcp-claude-channel).
  3. "claude.ai admin settings" misleading — Was pointing at a non-existent web setting. Fixed to point at the on-disk managed-settings.json file (per OS) matching the plugin’s README.

Also surfaces the _as_workspace requirement for multi-workspace tool calls (the -32603 trap operators hit when calling send_message_to_user without it).

Empirical repro

2026-05-21 onboarding session walked through this exact snippet, hit the broken two-flag form, got entries must be tagged: --channels, lost ~10 minutes diagnosing before noticing the canvas snippet disagreed with the channel plugin’s README. This PR removes the disagreement at the source.

Test plan

  • go test ./internal/handlers/ -run TestExternal — 5 pass (3 existing template tests + 2 new regression tests)
  • TestExternalChannelTemplate_LaunchFlagShape pins the single-flag launch form + bans the broken two-flag form
  • TestExternalChannelTemplate_CanonicalEnvShape pins MOLECULE_WORKSPACES_JSON + {{WORKSPACE_ID}} + {{PLATFORM_URL}} placeholders
  • Reviewer manual: render this template via canvas (or hit /admin/workspaces/:id/external/claude-code-channel) on a deployed build, confirm the rendered snippet has the new launch line and JSON env shape
  • Reviewer manual: copy-paste the rendered snippet to a fresh Claude Code session, confirm claude --dangerously-load-development-channels plugin:molecule@molecule-channel runs cleanly and channel connects

SOP

  • Authored by plugin-dev persona (this is canvas-served docs touching workspace-server, but plugin-dev has push on molecule-core and the diff is doc-only — no Go code semantics change). Open to a reviewer rerouting if a tighter persona match is preferred.
  • 2 substantive approves expected. NO admin merge, NO CI skip.
  • molecule-core BP requires QA-team approval per feedback_molecule_core_qa_review_team_required.

Follow-ups (not in this PR)

  • Hermes channel template (line 432) has the same legacy-shape pattern in its export commands — separate PR if we want hermes parity.
  • doc.moleculesai.app/docs/guides/claude-code-channel-plugin (the linked docs page) may need parallel updates — not in this repo.

🤖 Generated with Claude Code

## Summary Fixes three real onboarding potholes in the canvas-served Claude Code channel snippet at `workspace-server/internal/handlers/external_connection.go:externalChannelTemplate`: 1. **Broken launch flag form** — `claude --dangerously-load-development-channels --channels plugin:molecule@molecule-channel` errors with `entries must be tagged: --channels` (the `--channels` flag does not exist). Fixed to the working single-flag form `claude --dangerously-load-development-channels plugin:molecule@molecule-channel`. 2. **Legacy .env shape** — Was `MOLECULE_PLATFORM_URL + comma-separated IDs/TOKENS` (single-tenant). Fixed to the canonical `MOLECULE_WORKSPACES_JSON=[{id,token,platform_url}]` shape (multi-tenant, post-PR#15 SSOT in molecule-mcp-claude-channel). 3. **"claude.ai admin settings" misleading** — Was pointing at a non-existent web setting. Fixed to point at the on-disk managed-settings.json file (per OS) matching the plugin’s README. Also surfaces the `_as_workspace` requirement for multi-workspace tool calls (the -32603 trap operators hit when calling send_message_to_user without it). ## Empirical repro 2026-05-21 onboarding session walked through this exact snippet, hit the broken two-flag form, got `entries must be tagged: --channels`, lost ~10 minutes diagnosing before noticing the canvas snippet disagreed with the channel plugin’s README. This PR removes the disagreement at the source. ## Test plan - [x] `go test ./internal/handlers/ -run TestExternal` — 5 pass (3 existing template tests + 2 new regression tests) - [x] `TestExternalChannelTemplate_LaunchFlagShape` pins the single-flag launch form + bans the broken two-flag form - [x] `TestExternalChannelTemplate_CanonicalEnvShape` pins `MOLECULE_WORKSPACES_JSON` + `{{WORKSPACE_ID}}` + `{{PLATFORM_URL}}` placeholders - [ ] Reviewer manual: render this template via canvas (or hit `/admin/workspaces/:id/external/claude-code-channel`) on a deployed build, confirm the rendered snippet has the new launch line and JSON env shape - [ ] Reviewer manual: copy-paste the rendered snippet to a fresh Claude Code session, confirm `claude --dangerously-load-development-channels plugin:molecule@molecule-channel` runs cleanly and channel connects ## SOP - Authored by `plugin-dev` persona (this is canvas-served docs touching workspace-server, but plugin-dev has push on molecule-core and the diff is doc-only — no Go code semantics change). Open to a reviewer rerouting if a tighter persona match is preferred. - 2 substantive approves expected. NO admin merge, NO CI skip. - molecule-core BP requires QA-team approval per `feedback_molecule_core_qa_review_team_required`. ## Follow-ups (not in this PR) - Hermes channel template (line 432) has the same legacy-shape pattern in its export commands — separate PR if we want hermes parity. - doc.moleculesai.app/docs/guides/claude-code-channel-plugin (the linked docs page) may need parallel updates — not in this repo. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
plugin-dev added 1 commit 2026-05-22 00:17:15 +00:00
docs(onboarding): fix Claude Code channel setup snippet served by canvas
Lint shellcheck (arm64 pilot) / shellcheck-arm64 (pilot) (pull_request) Waiting to run
Block internal-flavored paths / Block forbidden paths (pull_request) Successful in 4s
CI / Detect changes (pull_request) Successful in 8s
CI / Python Lint & Test (pull_request) Successful in 5s
E2E API Smoke Test / detect-changes (pull_request) Successful in 7s
sop-checklist / na-declarations (pull_request) N/A: (none)
E2E Chat / detect-changes (pull_request) Successful in 6s
E2E Staging Canvas (Playwright) / detect-changes (pull_request) Successful in 8s
Handlers Postgres Integration / detect-changes (pull_request) Successful in 4s
Harness Replays / detect-changes (pull_request) Successful in 4s
Lint forbidden tenant-env keys / Scan workspace_secrets writers for forbidden env keys (pull_request) Successful in 4s
Lint no tenant GITEA or GITHUB token write / Scan for repo-host token write into tenant workspace surface (pull_request) Successful in 5s
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 9s
gate-check-v3 / gate-check (pull_request) Successful in 9s
qa-review / approved (pull_request) Failing after 4s
security-review / approved (pull_request) Failing after 5s
sop-checklist / all-items-acked (pull_request) Successful in 3s
sop-checklist / review-refire (pull_request) Has been skipped
sop-tier-check / tier-check (pull_request) Successful in 4s
lint-required-no-paths / lint-required-no-paths (pull_request) Successful in 1m0s
E2E Chat / E2E Chat (pull_request) Successful in 4s
E2E Staging Canvas (Playwright) / Canvas tabs E2E (pull_request) Successful in 6s
Harness Replays / Harness Replays (pull_request) Successful in 4s
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Successful in 2m5s
CI / Canvas (Next.js) (pull_request) Successful in 3s
CI / Shellcheck (E2E scripts) (pull_request) Successful in 3s
E2E API Smoke Test / E2E API Smoke Test (pull_request) Successful in 1m48s
CI / all-required (pull_request) Failing after 7m58s
CI / Canvas Deploy Reminder (pull_request) Has been skipped
CI / Platform (Go) (pull_request) Failing after 2m52s
494a1d8f9a
The canvas-served Claude Code setup snippet had three real flaws that
new operators hit on first install:

1. **Wrong launch flag form.** The snippet told users to run
       claude --dangerously-load-development-channels \
         --channels plugin:molecule@molecule-channel
   but `--channels` is not a real Claude Code flag. On 2.1.143+ this
   errors with `entries must be tagged: --channels`; on older builds
   it silently no-ops. The correct form is the channel spec as the
   VALUE of --dangerously-load-development-channels:
       claude --dangerously-load-development-channels plugin:molecule@molecule-channel

2. **Legacy .env shape as the primary example.** The snippet used
   MOLECULE_PLATFORM_URL + comma-separated MOLECULE_WORKSPACE_IDS +
   MOLECULE_WORKSPACE_TOKENS — the pre-PR#15 single-tenant shape.
   The canonical SSOT (post-PR#15 in molecule-mcp-claude-channel) is
   MOLECULE_WORKSPACES_JSON, a JSON array of {id, token, platform_url}
   objects. Multi-platform onboarding (watch hongming + agents-team
   from one plugin instance) requires the JSON shape; the legacy form
   silently fails for that case.

3. **"claude.ai admin settings" misleading.** The allowlist is the
   on-disk managed-settings.json file (per OS), not a web setting.
   New operators searched the claude.ai web UI for a toggle that
   doesn't exist. Replaced with explicit per-OS paths and the
   `sudo tee` recipe (matches the channel plugin's README §65-118).

Promotes multi-workspace from a buried side-note to the canonical
example. Adds a "_as_workspace required when watching >1 workspace"
callout that operators were hitting as -32603 errors on tool calls.
Updates the expected stderr line to the post-PR#15 format
("watching N workspace(s) across M platform(s)") so operators can
verify their setup matched the new wire shape.

Empirical: hit by a session walking through this snippet 2026-05-21.
The two-flag form errored, the user copy-pasted from this exact
template, and the only way through was for me to identify the README
disagreement after the fact.

Adds two regression tests:
- TestExternalChannelTemplate_LaunchFlagShape pins the single-flag
  form + bans the broken two-flag form
- TestExternalChannelTemplate_CanonicalEnvShape pins the
  MOLECULE_WORKSPACES_JSON canonical shape with {{WORKSPACE_ID}} +
  {{PLATFORM_URL}} placeholders

Tests: 5 pass (3 existing + 2 new).

The hermes channel template (line 432+) has the same legacy-shape
pattern in its export commands but uses a different runtime config
mechanism (~/.hermes/config.yaml) — separate PR if we want hermes
parity. Not touched here.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
plugin-dev requested review from core-be 2026-05-22 00:17:24 +00:00
plugin-dev requested review from core-qa 2026-05-22 00:17:24 +00:00
plugin-dev added 1 commit 2026-05-22 00:24:47 +00:00
docs(onboarding): kimi bridge — opt into Layer 1 ?include=peer_info
CI / Canvas Deploy Reminder (pull_request) Blocked by required conditions
Lint shellcheck (arm64 pilot) / shellcheck-arm64 (pilot) (pull_request) Waiting to run
Block internal-flavored paths / Block forbidden paths (pull_request) Successful in 5s
CI / Python Lint & Test (pull_request) Successful in 3s
CI / Detect changes (pull_request) Successful in 7s
E2E API Smoke Test / detect-changes (pull_request) Successful in 6s
E2E Chat / detect-changes (pull_request) Successful in 6s
E2E Staging Canvas (Playwright) / detect-changes (pull_request) Successful in 6s
Handlers Postgres Integration / detect-changes (pull_request) Successful in 6s
Harness Replays / detect-changes (pull_request) Successful in 5s
Lint forbidden tenant-env keys / Scan workspace_secrets writers for forbidden env keys (pull_request) Successful in 6s
Lint no tenant GITEA or GITHUB token write / Scan for repo-host token write into tenant workspace surface (pull_request) Successful in 3s
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 4s
gate-check-v3 / gate-check (pull_request) Successful in 5s
qa-review / approved (pull_request) Failing after 3s
security-review / approved (pull_request) Failing after 5s
sop-checklist / na-declarations (pull_request) N/A: (none)
sop-checklist / all-items-acked (pull_request) Successful in 3s
sop-checklist / review-refire (pull_request) Has been skipped
sop-tier-check / tier-check (pull_request) Successful in 4s
lint-required-no-paths / lint-required-no-paths (pull_request) Successful in 1m3s
CI / Canvas (Next.js) (pull_request) Successful in 4s
CI / Shellcheck (E2E scripts) (pull_request) Successful in 2s
E2E Chat / E2E Chat (pull_request) Successful in 10s
E2E Staging Canvas (Playwright) / Canvas tabs E2E (pull_request) Successful in 3s
E2E API Smoke Test / E2E API Smoke Test (pull_request) Successful in 1m36s
Harness Replays / Harness Replays (pull_request) Successful in 4s
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Successful in 2m0s
CI / Platform (Go) (pull_request) Successful in 4m59s
CI / all-required (pull_request) Successful in 11m26s
audit-force-merge / audit (pull_request) Successful in 6s
5599800bae
Audited all 9 templates in external_connection.go against current platform
state. Channel (Claude Code) is fixed in the parent commit on this branch.
The remaining templates are mostly fine — UniversalMCP / Python / Hermes /
Codex / OpenClaw all use per-invocation env or workspace-specific server
names that handle multi-workspace correctly through their respective
runtime config (claude.json / config.yaml / config.toml / openclaw mcp).

The one outlier is the Kimi bridge script, which polls /activity in a Python
loop. That poll was bare — no ?include=peer_info — so Kimi operators saw
the legacy row shape and never received the Layer 1 enrichment fields
(peer_name / peer_role / agent_card_url / attachments[]) that the platform
projects when asked.

Changes:
- kimi_bridge.py poll_inbound: add `"include": "peer_info"` to the
  params dict. Pre-Layer-1 platforms ignore the unknown filter and
  return the bare row shape (HTTP spec: unknown query params are
  dropped silently) — back-compat across deploys.
- "What the script does" comment block notes the enrichment + points
  operators at how to use the new fields in their custom logic.

Adds TestPollingTemplates_OptIntoPeerInfo as a regression gate — any
template that polls /activity must opt into the enrichment, or operators
who customize the script silently lose sender / attachment metadata.

The Channel (Claude Code) plugin's poll URL is in molecule-mcp-claude-
channel/server.ts pollWorkspace (not in this Go file) and is handled in
PR#21 on that repo with the same opt-in semantics.

Tests: 6 pass (3 existing + 3 added across the two commits on this branch).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
hongming merged commit e92468db13 into main 2026-05-22 00:44:01 +00:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: molecule-ai/molecule-core#1661