Skip to content

Add Claude Code plugin for end-user skill installation#2640

Open
Jac0bDeal wants to merge 4 commits intomanaflow-ai:mainfrom
Jac0bDeal:feat/claude-code-plugin
Open

Add Claude Code plugin for end-user skill installation#2640
Jac0bDeal wants to merge 4 commits intomanaflow-ai:mainfrom
Jac0bDeal:feat/claude-code-plugin

Conversation

@Jac0bDeal
Copy link
Copy Markdown

@Jac0bDeal Jac0bDeal commented Apr 6, 2026

Summary

  • Adds .claude-plugin/plugin.json manifest with metadata and explicit skill selection
  • Adds .claude-plugin/marketplace.json for marketplace distribution
  • Exposes only end-user skills (cmux, cmux-browser, cmux-markdown), excluding dev-only skills (cmux-debug-windows, release)

Once merged, users can install with:

/plugin marketplace add manaflow-ai/cmux
/plugin install cmux

Closes #2542

Testing

  • Verify /plugin marketplace add manaflow-ai/cmux discovers the marketplace
  • Verify /plugin install cmux installs the plugin with only the 3 end-user skills
  • Verify dev-only skills (cmux-debug-windows, release) are not exposed
  • Verify skills are invocable as /cmux:cmux, /cmux:cmux-browser, /cmux:cmux-markdown

Demo Video

N/A — no UI or behavior changes, plugin manifest only.

Review Trigger (Copy/Paste as PR comment)

@codex review
@coderabbitai review
@greptile-apps review
@cubic-dev-ai review

Checklist

  • I tested the change locally
  • I added or updated tests for behavior changes
  • I updated docs/changelog if needed
  • I requested bot reviews after my latest commit (copy/paste block above or equivalent)
  • All code review bot comments are resolved
  • All human review comments are resolved

Summary by cubic

Publishes a Claude Code plugin for cmux so users can install only the three end‑user skills from the marketplace. Marketplace source points to upstream manaflow-ai/cmux. Addresses #2542.

  • New Features

    • Added .claude-plugin/plugin.json exposing ./skills/cmux, ./skills/cmux-browser, ./skills/cmux-markdown; excludes cmux-debug-windows and release.
    • Added .claude-plugin/marketplace.json with source https://github.com/manaflow-ai/cmux.git.
    • README: added install steps with bash code block.
  • Migration

    • Add the marketplace: /plugin marketplace add manaflow-ai/cmux
    • Install the plugin: /plugin install cmux@cmux

Written for commit 48e1b31. Summary will update on new commits.

Summary by CodeRabbit

  • New Features

    • Claude Code plugin "cmux" is now available in the marketplace, providing window management, browser automation, and markdown viewing capabilities.
  • Documentation

    • Added instructions for adding and installing the cmux plugin via the Claude Code plugin marketplace.

@vercel
Copy link
Copy Markdown

vercel bot commented Apr 6, 2026

@Jac0bDeal is attempting to deploy a commit to the Manaflow Team on Vercel.

A member of the Team first needs to authorize it.

@chatgpt-codex-connector
Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 6, 2026

📝 Walkthrough

Walkthrough

Adds a Claude Code plugin manifest and marketplace metadata for "cmux" by introducing .claude-plugin/plugin.json and .claude-plugin/marketplace.json, plus README instructions to install the plugin via Claude Code's marketplace.

Changes

Cohort / File(s) Summary
Plugin manifests
.claude-plugin/marketplace.json, .claude-plugin/plugin.json
Added marketplace metadata and plugin manifest for cmux (version 0.1.0). Declares owner, repository URL, top-level metadata, and registers three skill entry points: ./skills/cmux, ./skills/cmux-browser, ./skills/cmux-markdown.
Documentation
README.md
Added Claude Code Plugin installation instructions showing plugin marketplace add manaflow-ai/cmux and plugin install cmux@cmux commands.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

Poem

🐰✨ A little manifest hopped in to play,
Three skillful trails to brighten the day,
A marketplace map and a README cheer,
Install with a command, the path is clear,
Hooray for cmux—let the windows sway!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding a Claude Code plugin manifest and marketplace metadata for end-user skill installation.
Linked Issues check ✅ Passed All code requirements from issue #2542 are met: plugin.json manifest added, marketplace.json added, end-user skills exposed (cmux, cmux-browser, cmux-markdown), dev-only skills excluded, and README updated with install instructions.
Out of Scope Changes check ✅ Passed All changes are directly related to the linked issue #2542 objectives: plugin manifest files, marketplace metadata, and documentation updates. No unrelated changes detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description check ✅ Passed The pull request description follows the repository template comprehensively, including all required sections: summary with what/why, testing steps with verification items, demo video explanation, review trigger block, and a detailed checklist.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Adds .claude-plugin/plugin.json and marketplace.json so users can
install cmux skills via the plugin system. Only exposes end-user
skills (cmux, cmux-browser, cmux-markdown), excluding dev-only
skills (cmux-debug-windows, release).

Install with:
  /plugin marketplace add manaflow-ai/cmux
  /plugin install cmux@cmux

Closes manaflow-ai#2542

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Jac0bDeal Jac0bDeal force-pushed the feat/claude-code-plugin branch from 4bc94ad to 999a2b4 Compare April 6, 2026 20:13
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Jac0bDeal Jac0bDeal marked this pull request as ready for review April 6, 2026 20:15
@cubic-dev-ai
Copy link
Copy Markdown

cubic-dev-ai bot commented Apr 6, 2026

This review could not be run because your cubic account has exceeded the monthly review limit. If you need help restoring access, please contact contact@cubic.dev.

@Jac0bDeal
Copy link
Copy Markdown
Author

@codex review
@coderabbitai review
@greptile-apps review
@cubic-dev-ai review

@cubic-dev-ai
Copy link
Copy Markdown

cubic-dev-ai bot commented Apr 6, 2026

@codex review
@coderabbitai review
@greptile-apps review
@cubic-dev-ai review

@Jac0bDeal I have started the AI code review. It will take a few minutes to complete.

@chatgpt-codex-connector
Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 6, 2026

@Jac0bDeal Sure, I'll review the changes now!


🧠 Learnings used
Learnt from: pstanton237
Repo: manaflow-ai/cmux PR: 0
File: :0-0
Timestamp: 2026-04-06T12:03:16.899Z
Learning: Repo: manaflow-ai/cmux — In CLI/cmux.swift, `claudeTeamsLaunchArguments` must use two independent branches: (1) prepend `--teammate-mode auto` only when the caller has NOT already supplied `--teammate-mode`; (2) append `--settings <claudeHooksJSON>` unconditionally (modulo `CMUX_CLAUDE_HOOKS_DISABLED=1` opt-out). These two branches must never be coupled in a single early-return or conditional block — coupling them was the original `#2229` regression (hook JSON silently bypassed when `--teammate-mode auto|manual` was explicit). Mirrors `Resources/bin/claude:208`: `exec "$REAL_CLAUDE" --settings "$HOOKS_JSON" "$@"` where `$@` content never gates hook injection.

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 2514
File: CLI/cmux.swift:9691-9711
Timestamp: 2026-04-01T22:58:26.254Z
Learning: Repo: manaflow-ai/cmux — In CLI/cmux.swift (runClaudeTeams), custom Claude path resolution now trims whitespace and rejects paths that point to the cmux wrapper using isCmuxClaudeWrapper(), before falling back to PATH/bundled. The Resources/bin/claude wrapper also resolves the real path and compares against itself, requiring -f/-x to avoid recursion/self-reference.

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 2514
File: CLI/cmux.swift:9698-9706
Timestamp: 2026-04-01T23:08:19.526Z
Learning: Repo: manaflow-ai/cmux — In CLI/cmux.swift (CMUXCLI.runClaudeTeams), custom Claude path candidates (CMUX_CUSTOM_CLAUDE_PATH and UserDefaults key "claudeCodeCustomClaudePath") now reject directory-valued paths by checking isDirectory == false before isExecutableFile, aligning with the Resources/bin/claude wrapper’s [[ -f && -x ]] validation and ensuring fallback to PATH/bundled.

Learnt from: Horacehxw
Repo: manaflow-ai/cmux PR: 2492
File: CLI/cmux.swift:319-321
Timestamp: 2026-04-06T09:45:30.721Z
Learning: Repo: manaflow-ai/cmux — Claude hook stop classification precedence: in CLI/cmux.swift, summarizeClaudeHookStop should detect failures by checking (1) hook_event_name == "StopFailure" or (2) presence of the "error" field; only then fall back to stop_reason != "end_turn" for back-compat. The notification subtitle/body should use String(localized:) with keys claude.hook.stop.verb.stopped/completed and claude.hook.stop.state.stopped/completed.
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@chatgpt-codex-connector
Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 6, 2026

Greptile Summary

This PR adds a Claude Code plugin manifest (.claude-plugin/plugin.json) and marketplace config (.claude-plugin/marketplace.json), plus README install instructions. The three referenced skill paths (./skills/cmux, ./skills/cmux-browser, ./skills/cmux-markdown) all exist in the repository, dev-only skills are correctly excluded, and the previously-flagged fork-source issue has been resolved — the source now correctly points to https://github.com/manaflow-ai/cmux.git.

Confidence Score: 5/5

Safe to merge — config-only change with no runtime behavior.

All three skill paths verified to exist, canonical repo URL in place, dev-only skills excluded, and the only prior P1 concern (fork source) is resolved. No remaining P0 or P1 findings.

No files require special attention.

Important Files Changed

Filename Overview
.claude-plugin/plugin.json New plugin manifest; all 3 skill paths verified, repo URL correct, dev skills excluded.
.claude-plugin/marketplace.json Marketplace config; source URL now correctly points to canonical manaflow-ai/cmux repo (prior fork-branch issue resolved).
README.md Added Claude Code plugin install instructions matching marketplace.json and plugin.json names.

Sequence Diagram

sequenceDiagram
    actor User
    participant CC as Claude Code
    participant Marketplace as Plugin Marketplace
    participant Repo as manaflow-ai/cmux

    User->>CC: /plugin marketplace add manaflow-ai/cmux
    CC->>Repo: fetch .claude-plugin/marketplace.json
    Repo-->>CC: marketplace metadata + plugin list
    CC-->>User: marketplace "cmux" registered

    User->>CC: /plugin install cmux@cmux
    CC->>Marketplace: resolve source URL
    Marketplace-->>CC: https://github.com/manaflow-ai/cmux.git
    CC->>Repo: fetch .claude-plugin/plugin.json
    Repo-->>CC: skills: [cmux, cmux-browser, cmux-markdown]
    CC->>Repo: clone skills/cmux, skills/cmux-browser, skills/cmux-markdown
    Repo-->>CC: skill files
    CC-->>User: plugin installed (cmux:cmux, cmux:cmux-browser, cmux:cmux-markdown)
Loading

Greploops — Automatically fix all review issues by running /greploops in Claude Code. It iterates: fix, push, re-review, repeat until 5/5 confidence.
Use the Greptile plugin for Claude Code to query reviews, search comments, and manage custom context directly from your terminal.

Reviews (2): Last reviewed commit: "Add language specifier to README code bl..." | Re-trigger Greptile

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.claude-plugin/marketplace.json:
- Around line 15-16: Update marketplace.json to use the production repository
URL and a valid branch/tag: replace the "url" value currently set to
"https://github.com/Jac0bDeal/cmux.git" with
"https://github.com/manaflow-ai/cmux" (to match plugin.json and README) and
change the "ref" from "feat/claude-code-plugin" to an existing branch or tag on
the manaflow-ai/cmux repo (e.g., main or a release tag). Ensure the "url" and
"ref" strings in marketplace.json exactly match the production repository and a
valid ref.

In `@README.md`:
- Around line 123-126: The fenced code block containing the plugin commands
lacks a language tag; update the triple-backtick fence that wraps "/plugin
marketplace add manaflow-ai/cmux" and "/plugin install cmux@cmux" to include a
shell language specifier (e.g., bash or shell) so the block becomes ```bash (or
```shell) for proper syntax highlighting.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0417a220-a5fb-4603-9332-25246955cc3f

📥 Commits

Reviewing files that changed from the base of the PR and between 179b16c and 88bf742.

📒 Files selected for processing (3)
  • .claude-plugin/marketplace.json
  • .claude-plugin/plugin.json
  • README.md

Jac0bDeal and others added 2 commits April 6, 2026 16:21
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Jac0bDeal
Copy link
Copy Markdown
Author

@codex review
@coderabbitai review
@greptile-apps review
@cubic-dev-ai review

@cubic-dev-ai
Copy link
Copy Markdown

cubic-dev-ai bot commented Apr 6, 2026

@codex review
@coderabbitai review
@greptile-apps review
@cubic-dev-ai review

@Jac0bDeal I have started the AI code review. It will take a few minutes to complete.

@chatgpt-codex-connector
Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

1 similar comment
@chatgpt-codex-connector
Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 6, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Read plugin manifest and marketplace files
cat .claude-plugin/plugin.json
echo "---"
cat .claude-plugin/marketplace.json
echo "---"
# Check that referenced skill paths exist
ls skills/
echo "---"
# Check README changes
grep -A 20 "Claude Code Plugin" README.md

Length of output: 3181


@Jac0bDeal, here is my review of PR #2640:


Review of .claude-plugin/plugin.json

This file looks well-formed overall. A few observations:

Skills array format — The skills field is declared as an array of individual subdirectory paths:

"skills": [
  "./skills/cmux",
  "./skills/cmux-browser",
  "./skills/cmux-markdown"
]

Per the plugin manifest reference, the skills field is typically a path to the skills directory (e.g. "./custom/skills/") rather than an array of individual skill subdirectory paths. If Claude Code's plugin loader expects a single directory string rather than an array of paths, this would silently fail to register any skills. Consider changing to:

"skills": "./skills"

…and relying on auto-discovery of subdirectories — but then you'd need a mechanism to exclude cmux-debug-windows and release. Alternatively, verify with claude plugin validate that the array form is accepted.


Review of .claude-plugin/marketplace.json

🚨 Non-standard source object structure — The plugin entry's source field uses a nested object:

"source": {
  "source": "url",
  "url": "https://github.com/manaflow-ai/cmux.git"
}

Anthropic's official marketplace entries use "source": "./plugins/plugin-name" — a simple relative path string, not a nested object. The { "source": "url", "url": "..." } tagged-union pattern is not documented in any official example I can find. If Claude Code's parser doesn't recognize this format, the plugin will fail to install from the marketplace.

For an external Git repo source, the correct format (if supported) would need to be verified against the actual runtime schema. As a safe fallback, consider restructuring the repository so the marketplace entry points to a relative path (e.g. "source": "./") if this repo is the plugin, or refer to the official docs for the external URL source format.

Missing $schema — Not a blocker; the Anthropic-referenced schema URL https://anthropic.com/claude-code/marketplace.schema.json doesn't actually resolve, so omitting $schema in marketplace.json is consistent with working examples.

metadata wrapper — The description is nested under "metadata": { "description": "..." }, but official Anthropic marketplace files use a top-level "description" field alongside "name" and "owner", not wrapped in a metadata object. This may or may not be accepted by the parser.

No ref pinned — The source has no ref field, so installs will always track the default branch HEAD. Plugin versions determine cache paths and update detection; you can specify the version in plugin.json or in the marketplace entry. Since plugin.json already has "version": "0.1.0", this is fine for now, but worth noting that version bumps in plugin.json will be needed to signal updates to users.


Review of README.md

Install instructions look correct. The /plugin install cmux@cmux syntax correctly references the marketplace entry name.


Summary

File Status Key Issue
plugin.json ⚠️ Needs verification skills array vs. directory string format
marketplace.json 🚨 Likely broken Non-standard source object structure
README.md Looks good

I'd strongly recommend running claude plugin validate (or testing the actual /plugin marketplace add + /plugin install flow) before merging, specifically to validate that the nested source object in marketplace.json is recognized by the runtime.


🧠 Learnings used
Learnt from: pstanton237
Repo: manaflow-ai/cmux PR: 0
File: :0-0
Timestamp: 2026-04-06T12:03:16.899Z
Learning: Repo: manaflow-ai/cmux — In CLI/cmux.swift, `claudeTeamsLaunchArguments` must use two independent branches: (1) prepend `--teammate-mode auto` only when the caller has NOT already supplied `--teammate-mode`; (2) append `--settings <claudeHooksJSON>` unconditionally (modulo `CMUX_CLAUDE_HOOKS_DISABLED=1` opt-out). These two branches must never be coupled in a single early-return or conditional block — coupling them was the original `#2229` regression (hook JSON silently bypassed when `--teammate-mode auto|manual` was explicit). Mirrors `Resources/bin/claude:208`: `exec "$REAL_CLAUDE" --settings "$HOOKS_JSON" "$@"` where `$@` content never gates hook injection.

Learnt from: Horacehxw
Repo: manaflow-ai/cmux PR: 2492
File: CLI/cmux.swift:319-321
Timestamp: 2026-04-06T09:45:30.721Z
Learning: Repo: manaflow-ai/cmux — Claude hook stop classification precedence: in CLI/cmux.swift, summarizeClaudeHookStop should detect failures by checking (1) hook_event_name == "StopFailure" or (2) presence of the "error" field; only then fall back to stop_reason != "end_turn" for back-compat. The notification subtitle/body should use String(localized:) with keys claude.hook.stop.verb.stopped/completed and claude.hook.stop.state.stopped/completed.

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 2514
File: CLI/cmux.swift:9698-9706
Timestamp: 2026-04-01T23:08:19.526Z
Learning: Repo: manaflow-ai/cmux — In CLI/cmux.swift (CMUXCLI.runClaudeTeams), custom Claude path candidates (CMUX_CUSTOM_CLAUDE_PATH and UserDefaults key "claudeCodeCustomClaudePath") now reject directory-valued paths by checking isDirectory == false before isExecutableFile, aligning with the Resources/bin/claude wrapper’s [[ -f && -x ]] validation and ensuring fallback to PATH/bundled.

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 2514
File: CLI/cmux.swift:9691-9711
Timestamp: 2026-04-01T22:58:26.254Z
Learning: Repo: manaflow-ai/cmux — In CLI/cmux.swift (runClaudeTeams), custom Claude path resolution now trims whitespace and rejects paths that point to the cmux wrapper using isCmuxClaudeWrapper(), before falling back to PATH/bundled. The Resources/bin/claude wrapper also resolves the real path and compares against itself, requiring -f/-x to avoid recursion/self-reference.

Learnt from: apollow
Repo: manaflow-ai/cmux PR: 1089
File: CLI/cmux.swift:462-499
Timestamp: 2026-03-09T02:08:54.956Z
Learning: Repo: manaflow-ai/cmux
PR: `#1089`
File: CLI/cmux.swift
Component: ClaudeHookTagExtractor.extractTags(subtitle:body:)
Learning: For Claude Code session tag extraction, pre-redact sensitive spans (UUIDs, emails, access tokens, filesystem paths, ENV_VAR=..., long numerics) across the combined body+subtitle using unanchored sensitiveSpanPatterns before tokenization. Then tokenize and still filter each token with anchored sensitivePatterns. Rationale: prevents PII/path fragments from slipping into searchable tags after delimiter splitting.

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 2525
File: Sources/GhosttyTerminalView.swift:481-513
Timestamp: 2026-04-02T10:13:39.235Z
Learning: Repo: manaflow-ai/cmux — In Sources/GhosttyTerminalView.swift, terminal file-link resolution trims trailing unmatched closing delimiters “) ] } >” only when they are dangling (more closers than openers), preserving wrapped tokens like “(file:///tmp/a.png)”. Implemented via terminalFileLinkTrailingClosingDelimiters and count comparison inside trimTrailingTerminalFileLinkPunctuation(_:) and exercised by a regression test (PR `#2525`, commit 3f5c5b6d).

Learnt from: pstanton237
Repo: manaflow-ai/cmux PR: 0
File: :0-0
Timestamp: 2026-04-06T12:03:16.899Z
Learning: Repo: manaflow-ai/cmux — In CLI/cmux.swift `runClaudeTeams`, `setenv("CMUX_CLAUDE_PID", ...)` is set unconditionally before the passthrough-subcommand check, mirroring `Resources/bin/claude:188` which exports `CMUX_CLAUDE_PID=$$` before the subcommand `case` statement. This is intentional design: the env var is dead for `mcp`/`config`/`api-key`/`rc`/`remote-control` paths but harmless, and matching the bash wrapper unconditional export exactly is a deliberate design principle for the claude-teams hook injection feature.

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 2528
File: Sources/AppDelegate.swift:2196-2200
Timestamp: 2026-04-03T03:36:45.112Z
Learning: Repo: manaflow-ai/cmux — In Sources/AppDelegate.swift, when KeyboardShortcutSettings.didChangeNotification fires, AppDelegate must clear configured-chord caches (pendingConfiguredShortcutChord and activeConfiguredShortcutChordPrefixForCurrentEvent) via clearConfiguredShortcutChordState() before refreshing tooltips/UI. Also clear chord state on applicationWillResignActive to avoid cross-activity leakage. Verified by cmuxTests/AppDelegateShortcutRoutingTests.swift::testShortcutChangeClearsPendingConfiguredChord.

Learnt from: outoftime
Repo: manaflow-ai/cmux PR: 1528
File: Resources/shell-integration/fish/vendor_conf.d/cmux-fish-integration.fish:541-546
Timestamp: 2026-03-17T13:59:10.665Z
Learning: Repo: manaflow-ai/cmux — The socket command `report_git_branch` (parsed in Sources/TerminalController.swift) expects the branch name as an **unquoted, bare token**. Wrapping the branch name in double quotes causes it to be silently discarded by the parser. This matches the bash/zsh shell integration convention. Do not suggest quoting the branch argument for this command; the fix was attempted in commit 829437c7 and immediately reverted because it broke branch reporting.

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 2514
File: Sources/GhosttyTerminalView.swift:3759-3761
Timestamp: 2026-04-01T22:57:41.165Z
Learning: Repo: manaflow-ai/cmux — In Sources/cmuxApp.swift, ClaudeCodeIntegrationSettings.customClaudePath(defaults:) trims surrounding whitespace and returns nil for empty/whitespace-only values; callers (e.g., TerminalSurface.createSurface(for:)) can safely set CMUX_CUSTOM_CLAUDE_PATH without additional trimming.

@Jac0bDeal
Copy link
Copy Markdown
Author

@coderabbitai Thanks for the thorough review. Here's context on the points raised:

1. Skills array format — The array form is supported and tested. The worktrunk plugin uses the same pattern in both its plugin.json and marketplace.json. We verified end-to-end that all 3 skills load correctly via /plugin install.

2. Source object structure — The {"source": "url", "url": "..."} tagged-union format is the standard for external repos. The official Anthropic marketplace (claude-plugins-official) uses this exact format for every external plugin (e.g. adspirer, aikido, endorlabs). We confirmed this by inspecting ~/.claude/plugins/marketplaces/claude-plugins-official/.claude-plugin/marketplace.json.

3. metadata wrapper — Also matches the worktrunk marketplace format, which is a working published plugin.

4. No ref pinned — Agreed this is fine for now. plugin.json has version: "0.1.0" for cache/update detection.

All formats were validated through actual installation testing (/plugin marketplace add + /plugin install) before opening this PR.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 6, 2026

Tip

For best results, initiate chat on the files or code changes.

@Jac0bDeal, thank you for the detailed context — all four points are well-addressed:

  1. Skills array format — Good to know the array-of-paths form is both accepted and verified. The worktrunk reference makes this clear.
  2. Source object structure — The {"source": "url", "url": "..."} tagged-union being the official format for external repos (confirmed against claude-plugins-official) was exactly the validation needed. My concern was unfounded.
  3. metadata wrapper — Consistent with a working published plugin; noted.
  4. No ref pinned — Agreed, the version field in plugin.json handles that use-case sufficiently.

Apologies for the noise — the review raised issues that were already validated against the real runtime. The PR looks good to merge.


✏️ Learnings added
Learnt from: Jac0bDeal
URL: https://github.com/manaflow-ai/cmux/pull/2640

Timestamp: 2026-04-06T20:32:16.642Z
Learning: Repo: manaflow-ai/cmux — In `.claude-plugin/plugin.json` for Claude Code plugins, the `skills` field accepts an **array of individual skill subdirectory paths** (e.g. `["./skills/cmux", "./skills/cmux-browser", "./skills/cmux-markdown"]`), not only a single directory string. This array form is the correct way to expose a selective subset of skills while excluding dev-only skill directories. Verified end-to-end via `/plugin install` and matches the worktrunk plugin (https://github.com/maxroos/worktrunk) pattern.

Learnt from: Jac0bDeal
URL: https://github.com/manaflow-ai/cmux/pull/2640

Timestamp: 2026-04-06T20:32:16.642Z
Learning: Repo: manaflow-ai/cmux — In `.claude-plugin/marketplace.json` for Claude Code plugins, the standard `source` format for an external Git repository is a **tagged-union object**: `{"source": "url", "url": "https://github.com/org/repo.git"}`. This is the format used by every external plugin in the official Anthropic marketplace (`claude-plugins-official`), confirmed by inspecting `~/.claude/plugins/marketplaces/claude-plugins-official/.claude-plugin/marketplace.json`. Do not flag this as non-standard.

Learnt from: Jac0bDeal
URL: https://github.com/manaflow-ai/cmux/pull/2640

Timestamp: 2026-04-06T20:32:16.642Z
Learning: Repo: manaflow-ai/cmux — In `.claude-plugin/marketplace.json` for Claude Code plugins, the top-level description is correctly nested under a `"metadata": { "description": "..." }` wrapper — this matches the worktrunk working published plugin format and is accepted by the Claude Code plugin runtime. Do not flag the `metadata` wrapper as non-standard.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: pstanton237
Repo: manaflow-ai/cmux PR: 0
File: :0-0
Timestamp: 2026-04-06T12:03:16.899Z
Learning: Repo: manaflow-ai/cmux — In CLI/cmux.swift, `claudeTeamsLaunchArguments` must use two independent branches: (1) prepend `--teammate-mode auto` only when the caller has NOT already supplied `--teammate-mode`; (2) append `--settings <claudeHooksJSON>` unconditionally (modulo `CMUX_CLAUDE_HOOKS_DISABLED=1` opt-out). These two branches must never be coupled in a single early-return or conditional block — coupling them was the original `#2229` regression (hook JSON silently bypassed when `--teammate-mode auto|manual` was explicit). Mirrors `Resources/bin/claude:208`: `exec "$REAL_CLAUDE" --settings "$HOOKS_JSON" "$@"` where `$@` content never gates hook injection.

Learnt from: Horacehxw
Repo: manaflow-ai/cmux PR: 2043
File: Resources/bin/claude:0-0
Timestamp: 2026-04-03T07:49:14.139Z
Learning: Repo: manaflow-ai/cmux — In Resources/bin/claude, SELF_DIR is validated with a broad regex `[\"\\' $\`!;|&<>()*?\[\]]` before interpolating it into HOOKS_JSON command strings. Paths that match (unsafe chars including spaces and shell metacharacters) cause the wrapper to fall back to BASE_HOOKS_JSON and emit a warning. This guard-and-fallback is the intentional design; do not suggest adding shell quoting inside the JSON command strings — the guard approach is preferred.

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 2514
File: CLI/cmux.swift:9691-9711
Timestamp: 2026-04-01T22:58:26.254Z
Learning: Repo: manaflow-ai/cmux — In CLI/cmux.swift (runClaudeTeams), custom Claude path resolution now trims whitespace and rejects paths that point to the cmux wrapper using isCmuxClaudeWrapper(), before falling back to PATH/bundled. The Resources/bin/claude wrapper also resolves the real path and compares against itself, requiring -f/-x to avoid recursion/self-reference.

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 2514
File: CLI/cmux.swift:9698-9706
Timestamp: 2026-04-01T23:08:19.526Z
Learning: Repo: manaflow-ai/cmux — In CLI/cmux.swift (CMUXCLI.runClaudeTeams), custom Claude path candidates (CMUX_CUSTOM_CLAUDE_PATH and UserDefaults key "claudeCodeCustomClaudePath") now reject directory-valued paths by checking isDirectory == false before isExecutableFile, aligning with the Resources/bin/claude wrapper’s [[ -f && -x ]] validation and ensuring fallback to PATH/bundled.

Learnt from: apollow
Repo: manaflow-ai/cmux PR: 1089
File: CLI/cmux.swift:462-499
Timestamp: 2026-03-09T02:08:54.956Z
Learning: Repo: manaflow-ai/cmux
PR: `#1089`
File: CLI/cmux.swift
Component: ClaudeHookTagExtractor.extractTags(subtitle:body:)
Learning: For Claude Code session tag extraction, pre-redact sensitive spans (UUIDs, emails, access tokens, filesystem paths, ENV_VAR=..., long numerics) across the combined body+subtitle using unanchored sensitiveSpanPatterns before tokenization. Then tokenize and still filter each token with anchored sensitivePatterns. Rationale: prevents PII/path fragments from slipping into searchable tags after delimiter splitting.

Learnt from: pstanton237
Repo: manaflow-ai/cmux PR: 0
File: :0-0
Timestamp: 2026-04-06T12:03:16.899Z
Learning: Repo: manaflow-ai/cmux — In CLI/cmux.swift `runClaudeTeams`, `setenv("CMUX_CLAUDE_PID", ...)` is set unconditionally before the passthrough-subcommand check, mirroring `Resources/bin/claude:188` which exports `CMUX_CLAUDE_PID=$$` before the subcommand `case` statement. This is intentional design: the env var is dead for `mcp`/`config`/`api-key`/`rc`/`remote-control` paths but harmless, and matching the bash wrapper unconditional export exactly is a deliberate design principle for the claude-teams hook injection feature.

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 2525
File: Sources/GhosttyTerminalView.swift:481-513
Timestamp: 2026-04-02T10:13:39.235Z
Learning: Repo: manaflow-ai/cmux — In Sources/GhosttyTerminalView.swift, terminal file-link resolution trims trailing unmatched closing delimiters “) ] } >” only when they are dangling (more closers than openers), preserving wrapped tokens like “(file:///tmp/a.png)”. Implemented via terminalFileLinkTrailingClosingDelimiters and count comparison inside trimTrailingTerminalFileLinkPunctuation(_:) and exercised by a regression test (PR `#2525`, commit 3f5c5b6d).

Learnt from: Horacehxw
Repo: manaflow-ai/cmux PR: 2492
File: CLI/cmux.swift:319-321
Timestamp: 2026-04-06T09:45:30.721Z
Learning: Repo: manaflow-ai/cmux — Claude hook stop classification precedence: in CLI/cmux.swift, summarizeClaudeHookStop should detect failures by checking (1) hook_event_name == "StopFailure" or (2) presence of the "error" field; only then fall back to stop_reason != "end_turn" for back-compat. The notification subtitle/body should use String(localized:) with keys claude.hook.stop.verb.stopped/completed and claude.hook.stop.state.stopped/completed.

Learnt from: outoftime
Repo: manaflow-ai/cmux PR: 1528
File: Resources/shell-integration/fish/vendor_conf.d/cmux-fish-integration.fish:541-546
Timestamp: 2026-03-17T13:59:10.665Z
Learning: Repo: manaflow-ai/cmux — The socket command `report_git_branch` (parsed in Sources/TerminalController.swift) expects the branch name as an **unquoted, bare token**. Wrapping the branch name in double quotes causes it to be silently discarded by the parser. This matches the bash/zsh shell integration convention. Do not suggest quoting the branch argument for this command; the fix was attempted in commit 829437c7 and immediately reverted because it broke branch reporting.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature Request: Package cmux skills as a Claude Code plugin for easy installation

1 participant