Skip to content

feat: add Code Puppy coding agent integration - #8282

Open
mattnico wants to merge 10 commits into
manaflow-ai:mainfrom
mattnico:feature/code-puppy-integration
Open

mattnico wants to merge 10 commits into
manaflow-ai:mainfrom
mattnico:feature/code-puppy-integration

Conversation

@mattnico

@mattnico mattnico commented Jul 16, 2026 •

Copy link
Copy Markdown

Summary

Adds full cmux integration for Code Puppy, an open-source Python TUI coding agent, with parity to the existing Codex/Gemini/Copilot integrations.

What's new

Process detection (Tier 0)

  • Detects all three Code Puppy entry points: code-puppy and pup console scripts, and python -m code_puppy module invocation
  • CMUX_AGENT_LAUNCH_KIND=code-puppy support for wrapper launchers (e.g. uv run)

Launch config kind (Tier 1)

  • .codePuppy case in CmuxConfigAgentKind so action buttons in cmux.json can specify "agent": "code-puppy" with a proper default icon

Session tracking, restore & Feed (Tier 2)

  • Hook catalog row using .nested(timeoutMs: 5000) format pointed at ~/.code_puppy/hooks.json — the exact JSON shape Code Puppy's native hook engine already reads, so no custom plugin or PATH-shim is needed
  • Events: SessionStart, UserPromptSubmit, Stop, Notification, SessionEnd
  • Feed: PreToolUse, PostToolUse
  • Vault registration with sessionIdSource: .argvOption("--resume") — cmux mints the session name at launch, reads it from argv, and replays code-puppy --resume <name> on restore
  • CMUX_CODE_PUPPY_PID wired into both PID-inference switches

Icon (Tier 3)

  • AgentIcons/CodePuppy imageset — 14/28/42 px PNGs from the Code Puppy brand mark

Docs

  • docs/agent-hooks.md: integrations table, supported-agent list, auto-naming skip list, environment overrides table

Key design finding

Code Puppy ships a native Claude-Code-compatible hook engine (code_puppy/hook_engine/) already wired to its run lifecycle via a built-in plugin. It reads hooks from ~/.code_puppy/hooks.json in the same JSON shape cmux's existing .nested writer already produces for Codex/Gemini/Copilot. This means the integration needs:

  • No PATH-shim wrapper (unlike Codex)
  • No cmux-authored Python plugin
  • No changes to the Code Puppy repo
  • One AgentHookDef catalog row + one Vault registration

Testing

Added CodePuppyDetectionTests.swift (Swift Testing) with 9 focused tests covering every entry point and two no-false-positive guards. The test file was committed before the definition (two-commit structure) so CI can show the red-to-green transition.

cmux hooks setup code-puppy
code-puppy --resume my-session

Files changed

File Change
cmuxTests/CodePuppyDetectionTests.swift New — 9 Swift Testing detection tests
cmuxTests/TaskManagerResourcesTests.swift +3 entries in existing table test
Sources/CmuxTaskManagerCodingAgentDefinition+BuiltIns.swift Detection def
Sources/CmuxConfig.swift .codePuppy launch kind
Sources/VaultAgentRegistry+CodePuppy.swift New — Vault registration
Sources/VaultAgentRegistry.swift Wire builtInCodePuppy into load()
CLI/CMUXCLI+AgentHookCatalog.swift AgentHookDef row
CLI/cmux.swift PID switches + help text
Assets.xcassets/AgentIcons/CodePuppy.imageset/ New — icon PNGs + Contents.json
docs/agent-hooks.md Agent tables + supported-agent list
docs/code-puppy-integration-plan.md New — integration plan (repo-verified)

Summary by CodeRabbit

  • New Features
    • Added end-to-end Code Puppy support, including detection, launching, session restoration, hooks, feed integration, and a dedicated icon.
    • Added code-puppy and pup command aliases.
    • Added localized Code Puppy labels in English and Japanese.
    • Added an option to disable hook installation with CMUX_CODE_PUPPY_HOOKS_DISABLED=1.
  • Documentation
    • Updated agent hook documentation and added a Code Puppy integration plan.
  • Tests
    • Added coverage for process detection, hook configuration, wrappers, module invocations, and false positives.

Matt Nicolaysen added 4 commits July 16, 2026 12:39
Adds CodePuppyDetectionTests.swift (Swift Testing) covering all Code Puppy
entry points: code-puppy basename, code_puppy underscore variant, pup alias,
python -m code_puppy module invocation, python3 variant, uv run via
CMUX_AGENT_LAUNCH_KIND, asset name, and no-false-positive guards.

Also extends the existing testCodingAgentMatcherCoversSupportedAgentExecutableNames
table in TaskManagerResourcesTests.swift with code-puppy, code_puppy, and pup.

All new tests fail until the builtin definition is added in commit 2.

Also adds docs/code-puppy-integration-plan.md: repo-verified integration plan
(verified against ~/dev/Projects/Community/code_puppy v0.0.643). Key finding:
Code Puppy ships a native Claude-Code-compatible hook engine and native --resume,
so integration needs no PATH-shim, no custom plugin, and no Code Puppy changes.
Plan: 9 files, one AgentHookDef catalog row, one Vault registration.
Registers code-puppy in CmuxTaskManagerCodingAgentDefinition.builtIns so the
task manager detects and tracks Code Puppy processes.

Detection covers all three supported entry points (verified against
~/dev/Projects/Community/code_puppy v0.0.643 pyproject.toml):
  - code-puppy  (primary console script, directBasenames)
  - code_puppy  (underscore variant, directBasenames)
  - pup         (secondary console script alias, directBasenames)
  - python -m code_puppy  (module invocation, argumentNeedles)
  - python3 -m code_puppy (same, argumentNeedles)
  - uv run code-puppy via CMUX_AGENT_LAUNCH_KIND=code-puppy (launchKinds)

assetName: AgentIcons/CodePuppy (icon asset to be added in a follow-up).

This commit makes all tests added in commit 1 pass (CI: red -> green).
Next: Tier 1 (CmuxConfigAgentKind), Tier 2 (hook catalog + Vault registration).
Tier 1 — Launch config kind
- CmuxConfig.swift: add .codePuppy case to CmuxConfigAgentKind with
  commandName 'code-puppy', defaultIcon .symbol('dog'), and decoder
  aliases code-puppy / codePuppy / code_puppy / pup.

Tier 2 — Session tracking, restore & Feed
- CMUXCLI+AgentHookCatalog.swift: AgentHookDef for code-puppy using
  .nested(timeoutMs: 5000) format pointed at ~/.code_puppy/hooks.json
  (the exact JSON shape Code Puppy's native hook engine already reads).
  Events: SessionStart, UserPromptSubmit, Stop, Notification, SessionEnd.
  Feed: PreToolUse, PostToolUse.
- VaultAgentRegistry+CodePuppy.swift: builtInCodePuppy registration.
  Detects code-puppy / code_puppy / pup basenames and code_puppy argv
  needle (python -m code_puppy). sessionIdSource: .argvOption('--resume')
  so cmux mints the session name at launch and reads it from argv.
  sessionDirectory: ~/.code_puppy/autosaves.
- VaultAgentRegistry.swift: include builtInCodePuppy in load().
- cmux.swift: add code-puppy to agentPIDFromHookEnvironment and
  agentPidForFeedSource switches (CMUX_CODE_PUPPY_PID env key); add
  code-puppy to hooks setup help text.

Tier 3 — Docs & notification gating
- docs/agent-hooks.md: add Code Puppy to integrations table, supported-
  agent list, auto-naming skip list, and environment overrides table.
- AgentNotificationGate.swift: no change needed — Stop maps to the
  existing turn-complete gate via the cmux hooks stop handler; the .other
  fallback covers legacy/uncategorized events correctly.

No new install format, no custom plugin, no Code Puppy repo changes.
Icon asset (AgentIcons/CodePuppy) to be added in a follow-up.
14x14 / 28x28 / 42x42 px PNGs derived from the Code Puppy brand mark
at puppy.walmart.com. Matches the scale convention used by Claude,
Codex, OpenCode, Antigravity, and RovoDev.
@cursor

cursor Bot commented Jul 16, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@vercel

vercel Bot commented Jul 16, 2026

Copy link
Copy Markdown

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

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Jul 16, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Code Puppy is added as a built-in cmux agent with aliases, process detection, launch configuration, hook integration, Vault-based session restoration, icon assets, tests, and documentation.

Changes

Code Puppy integration

Layer / File(s) Summary
Agent identity and detection
Assets.xcassets/AgentIcons/CodePuppy.imageset/Contents.json, Sources/CmuxConfig.swift, Sources/CmuxTaskManagerCodingAgentDefinition+BuiltIns.swift, cmuxTests/*, cmux.xcodeproj/project.pbxproj
Adds the Code Puppy config kind, aliases, command name, icon, detection metadata, asset registration, and regression tests for executable, module, wrapper, launch-kind, and negative matching cases.
Launch, hooks, and session restoration
Packages/macOS/CMUXAgentLaunch/..., CLI/*, Sources/VaultAgentRegistry.swift, cmuxTests/CodePuppyHookConfigTests.swift
Adds a shared registration contract, launch aliases, PID environment mappings, matcher-aware hook generation, lifecycle and feed events, hook configuration validation, and session resume registration.
Integration plan and documentation
docs/agent-hooks.md, docs/code-puppy-integration-plan.md, Resources/Localizable.xcstrings
Documents supported-agent behavior, hook and resume contracts, localization, rollout, notification and feed handling, kill-switch semantics, testing, and dogfood steps.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant CMUXCLI
  participant CodePuppy
  participant CmuxVaultAgentRegistry
  User->>CMUXCLI: launch code-puppy or pup
  CMUXCLI->>CodePuppy: configure hooks and start process
  CodePuppy->>CMUXCLI: emit session and tool hook events
  CMUXCLI->>CmuxVaultAgentRegistry: store session resume information
  CmuxVaultAgentRegistry->>CodePuppy: restore with --resume sessionId
Loading

Possibly related PRs

  • manaflow-ai/cmux#9017: Adds a similar first-class coding-agent integration across metadata, detection, hooks, session restoration, tests, and documentation.
  • manaflow-ai/cmux#9155: Shares the coding-agent detection and icon asset infrastructure.
  • manaflow-ai/cmux#9265: Shares CMUXAgentLaunch registration and session resume integration.

Suggested reviewers: austinywang


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error, 2 warnings, 1 inconclusive)

Check name Status Explanation Resolution
Cmux Full Internationalization ❌ Error The PR adds three Localizable.xcstrings keys with entries only for en and ja, while the touched catalog already contains 20 locale codes. Add translated entries for ar, bs, da, de, es, fr, it, km, ko, nb, pl, pt-BR, ru, th, tr, uk, zh-Hans, and zh-Hant to all three keys.
Description check ⚠️ Warning The description explains the integration and testing, but it omits the required Demo Video, Review Trigger, and Checklist sections. Add the missing Demo Video, Review Trigger, and Checklist sections, and complete them with the required links, confirmations, and review status.
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Cmux Architecture Rethink ❓ Inconclusive The repository has no working-tree diff, so the changed Swift code is not directly available for architecture assessment. Provide the pull-request revision or a populated diff so the added Swift paths can be checked against the architecture rule.
✅ Passed checks (21 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: adding Code Puppy integration.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Cmux Swift Actor Isolation ✅ Passed The production diff adds only immutable Sendable/value data and configuration; it adds no shared mutable reference, service protocol, actor boundary, or background access to a UI-bound store.
Cmux Swift Blocking Runtime ✅ Passed The PR adds no semaphores, waits, sleeps, delayed dispatch, polling, main-queue sync, or locks; the 5,000 ms value is hook configuration, not synchronization.
Cmux Browser Automation Off-Main ✅ Passed The PR changes no browser automation source, worker policy, router, or policy tests; the rule-scope files are unchanged versus main, so no off-main wait or new worker command is introduced.
Cmux Expensive Synchronous Load ✅ Passed The full topic diff adds Code Puppy metadata, hook configuration writing, and registry wiring, but no synchronous history loader; existing close paths use SharedLiveAgentIndex with a nil-cache fall...
Cmux Cache Substitution Correctness ✅ Passed The PR adds Code Puppy registration, detection, Vault metadata, and hook matcher handling; it does not replace any fresh persistence, history, undo, or snapshot read with a cache.
Cmux No Hacky Sleeps ✅ Passed The PR adds Swift code, tests, docs, assets, and Xcode metadata only; it adds no covered TypeScript, JavaScript, shell, or build/runtime sleep or timer logic.
Cmux Algorithmic Complexity ✅ Passed The PR adds only fixed-size agent metadata and hook-event scans; the Code Puppy hook loops are bounded, and the added JSON loops are test-only. No scalable batch or hot-path algorithm is introduced.
Cmux Swift Concurrency ✅ Passed The complete Code Puppy Swift diff adds no Dispatch, Combine, completion-handler, or fire-and-forget Task patterns; it only adds synchronous registration data and tests.
Cmux Swift @Concurrent ✅ Passed The PR’s Swift diff adds no async/nonisolated work, @concurrent annotations, actor isolation, or heavy async call sites; all new functions and registration logic are synchronous.
Cmux Swift Package Boundaries ✅ Passed The PR places reusable Code Puppy metadata in the independently testable CMUXAgentLaunch package; app-target changes only wire that contract into CLI, config, detection, and Vault registries.
Cmux Swiftpm Lockfiles ✅ Passed Packages/macOS/CMUXAgentLaunch/Package.swift has no dependency change, and cmux.xcodeproj only adds test file references; no SwiftPM package-reference or lockfile change is required.
Cmux Swift Logging ✅ Passed The full PR diff adds no print, debugPrint, dump, NSLog, Logger, or production file/stdout diagnostics; the only stderr reference is in a test assertion, which is allowed.
Cmux User-Facing Error Privacy ✅ Passed The production diff adds Code Puppy integration metadata, labels, and advanced hook help only; it adds no user-facing error, alert, raw upstream message, credential, token, session ID, or payload d...
Cmux Swiftui State Layout ✅ Passed The full PR diff adds only CLI/configuration, registry metadata, and tests; it introduces no SwiftUI views, state wrappers, layout readers, lazy rows, or render-time state writes.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed The complete PR diff adds no NSWindow, NSPanel, NSWindowController, Window, or WindowGroup code; scripts/lint_auxiliary_window_close_shortcuts.py also passes.
Cmux Source Artifacts ✅ Passed All 19 changed paths are source, tests, docs, localization, project config, or small PNG assets; forbidden artifact-path scan found none.
Cmux No Test Or Debug Seam In Production Source ✅ Passed Across the full PR range, changed production Sources contain no DEBUG/test guards or test-seam names; the public registration is used by production CLI and Sources callers.
Cmux No Ambient Global State ✅ Passed The new production API is a constructable immutable registration struct; static let standard is a constant contract, and builtInCodePuppy is a computed factory matching existing registrations.
✨ Finishing Touches 💡 2
⚔️ Resolve merge conflicts 💡
  • Resolve merge conflict in branch feature/code-puppy-integration
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 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.

@greptile-apps

greptile-apps Bot commented Jul 16, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds a full Code Puppy coding agent integration — process detection, launch config kind, hook catalog, vault session tracking, and icon — with parity to the existing Codex/Gemini/Copilot integrations.

  • Process detection (CmuxTaskManagerCodingAgentDefinition+BuiltIns.swift): code-puppy and code_puppy direct basenames + argument needles cover console scripts, module invocation (python -m code_puppy), and wrapper launchers (uvx/uv run). pup is correctly excluded from basenames (to avoid the ericchiang/pup HTML CLI false positive) and only recognized via CMUX_AGENT_LAUNCH_KIND.
  • Hook catalog (CMUXCLI+AgentHookCatalog.swift): A new AgentHookDef row reuses the existing .nested(timeoutMs:) format pointed at ~/.code_puppy/hooks.json; nestedGroupMatcher: "*" is added to satisfy Code Puppy's validator requirement that every hook group carry a matcher field. The new nestedGroupMatcher property on AgentHookDef is nil-defaulted so existing agents are unaffected.
  • Vault registration (VaultAgentRegistry.swift): builtInCodePuppy uses sessionIdSource: .argvOption("--resume") — cmux mints the session name at launch and reads it from argv, avoiding reliance on the hook stdin session_id which is a placeholder at SessionStart.

Confidence Score: 5/5

This PR is safe to merge — it adds a new agent integration through well-established extension points without touching existing agent paths.

All changes are additive: new enum case, new builtin definition, new catalog row, new vault registration, new test files. Every production-code touch point follows the exact same pattern as existing agents (grok, antigravity, gemini, copilot). The two previous review concerns — the kimi entry missing required params and pup as a direct basename causing false positives — are both correctly resolved: kimi retains its full displayName and statusKey, and pup is absent from directBasenames, argumentNeedles, and vault processNames across the board. The nestedGroupMatcher addition is nil-defaulted and has no effect on any existing agent. No blocking, actor isolation, global-state, expensive-load, or test-seam issues were found in the production Swift.

No files require special attention.

Important Files Changed

Filename Overview
CLI/CMUXCLI+AgentHookCatalog.swift Adds Code Puppy AgentHookDef row with nestedGroupMatcher: "*" to satisfy Code Puppy's validator requirement; kimi entry remains intact with all required params.
CLI/CMUXCLI+AgentHookDefinitions.swift Adds optional nestedGroupMatcher: String? to AgentHookDef; nil-defaulted so all existing agents are unaffected. Used by cmux.swift to conditionally write the matcher field per hook group.
Sources/CmuxTaskManagerCodingAgentDefinition+BuiltIns.swift Adds code-puppy detection definition with directBasenames [code-puppy, code_puppy] and matching argumentNeedles; pup is deliberately absent from all detection lists to avoid collision with ericchiang/pup.
Sources/VaultAgentRegistry.swift Adds builtInCodePuppy static computed property following the existing pattern; processNames correctly excludes pup; argvOption("--resume") is the right sessionIdSource since the hook stdin session_id is a placeholder at SessionStart.
Sources/CmuxConfig.swift Adds .codePuppy case with commandName, defaultIcon (.symbol("pawprint")), decoder aliases (code-puppy/codePuppy/code_puppy/pup), and localized default title.
CLI/cmux.swift Wires CMUX_CODE_PUPPY_PID into both PID-inference switch statements and updates help text; identical pattern to all other agents.
cmuxTests/CodePuppyDetectionTests.swift Nine focused Swift Testing tests covering all entry points (console script, underscore variant, module invocation, wrapper launchers, launch-kind env) plus two no-false-positive guards for bare python and bare pup.
cmuxTests/CodePuppyHookConfigTests.swift Integration test that runs cmux hooks code-puppy install --yes and asserts every generated hook group carries matcher: "*", covering the nestedGroupMatcher fix for Code Puppy's validator.
docs/code-puppy-integration-plan.md New integration plan document following the repo's established pattern; explains key design decisions including the pup false-positive tradeoff and argvOption session ID rationale.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[User launches code-puppy
or code_puppy or pup] --> B{Detection path}
    B -- "direct basename
code-puppy / code_puppy" --> C[CmuxTaskManagerCodingAgentDefinition
id: code-puppy]
    B -- "argv needle
code-puppy / code_puppy
e.g. uvx code-puppy
python -m code_puppy" --> C
    B -- "CMUX_AGENT_LAUNCH_KIND=code-puppy
e.g. pup via cmux launcher" --> C
    C --> D[Task Manager shows
Code Puppy with brand icon]

    E[cmux hooks code-puppy install] --> F[AgentHookDef
format: .nested timeoutMs:5000
nestedGroupMatcher: asterisk]
    F --> G[~/.code_puppy/hooks.json
SessionStart UserPromptSubmit Stop
Notification SessionEnd PreToolUse PostToolUse
each group carries matcher: asterisk]
    G --> H[Code Puppy hook_engine
reads hooks.json natively]

    I[cmux launches via Vault session action] --> J[code-puppy --resume cmux-name]
    J --> K[CmuxVaultAgentRegistration
sessionIdSource: .argvOption --resume]
    K --> L[Session tracked and restorable
in ~/.code_puppy/autosaves]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[User launches code-puppy
or code_puppy or pup] --> B{Detection path}
    B -- "direct basename
code-puppy / code_puppy" --> C[CmuxTaskManagerCodingAgentDefinition
id: code-puppy]
    B -- "argv needle
code-puppy / code_puppy
e.g. uvx code-puppy
python -m code_puppy" --> C
    B -- "CMUX_AGENT_LAUNCH_KIND=code-puppy
e.g. pup via cmux launcher" --> C
    C --> D[Task Manager shows
Code Puppy with brand icon]

    E[cmux hooks code-puppy install] --> F[AgentHookDef
format: .nested timeoutMs:5000
nestedGroupMatcher: asterisk]
    F --> G[~/.code_puppy/hooks.json
SessionStart UserPromptSubmit Stop
Notification SessionEnd PreToolUse PostToolUse
each group carries matcher: asterisk]
    G --> H[Code Puppy hook_engine
reads hooks.json natively]

    I[cmux launches via Vault session action] --> J[code-puppy --resume cmux-name]
    J --> K[CmuxVaultAgentRegistration
sessionIdSource: .argvOption --resume]
    K --> L[Session tracked and restorable
in ~/.code_puppy/autosaves]
Loading

Reviews (4): Last reviewed commit: "test: assert Code Puppy hook groups carr..." | Re-trigger Greptile

Comment on lines +246 to 248
AgentHookDef(
name: "kimi",
configDir: ".kimi-code", configFile: "config.toml", configDirEnvOverride: "KIMI_CODE_HOME",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P0 Missing required parameters break kimi entry — build failure

The Code Puppy entry was spliced in by replacing the original one-liner name: "kimi", displayName: "Kimi Code", statusKey: "kimi",, but the replacement only emits name: "kimi", for the kimi AgentHookDef. AgentHookDef.init declares both displayName: String and statusKey: String as required non-optional parameters (no defaults), so this call does not compile. Every consumer that invokes cmux hooks setup kimi — display name, set-status key, hook marker lookup — would be broken even if a compiler error is somehow bypassed.

Suggested change
AgentHookDef(
name: "kimi",
configDir: ".kimi-code", configFile: "config.toml", configDirEnvOverride: "KIMI_CODE_HOME",
AgentHookDef(
name: "kimi", displayName: "Kimi Code", statusKey: "kimi",
configDir: ".kimi-code", configFile: "config.toml", configDirEnvOverride: "KIMI_CODE_HOME",

Comment on lines +50 to +53
.init(id: "code-puppy", displayName: "Code Puppy", assetName: "AgentIcons/CodePuppy",
launchKinds: ["code-puppy"],
directBasenames: ["code-puppy", "code_puppy", "pup"],
argumentNeedles: ["code_puppy"]),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 pup basename causes false-positive agent detection

pup is a widely-used, Homebrew-installable HTML processing CLI tool (github.com/ericchiang/pup). Registering it as a directBasename means any running pup HTML-parser process will be detected as Code Puppy, showing Code Puppy controls, routing task-manager state, and triggering Vault session tracking for an unrelated program. The same collision exists in VaultAgentRegistry+CodePuppy.swift where processNames also includes "pup". Using only code-puppy and code_puppy as direct basenames — which uniquely identify the Code Puppy tool — and letting argumentNeedles: ["code_puppy"] handle the module invocation case would avoid the false positive.

Suggested change
.init(id: "code-puppy", displayName: "Code Puppy", assetName: "AgentIcons/CodePuppy",
launchKinds: ["code-puppy"],
directBasenames: ["code-puppy", "code_puppy", "pup"],
argumentNeedles: ["code_puppy"]),
.init(id: "code-puppy", displayName: "Code Puppy", assetName: "AgentIcons/CodePuppy",
launchKinds: ["code-puppy"],
directBasenames: ["code-puppy", "code_puppy"],
argumentNeedles: ["code_puppy"]),

Rule Used: Flag correctness-critical detection/identity deriv... (source)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CLI/CMUXCLI`+AgentHookCatalog.swift:
- Around line 231-245: Add the `pup` alias to the `AgentHookDef` for
`code-puppy` by setting its aliases collection to include `"pup"`, preserving
the existing hook configuration so commands using either agent name resolve
identically.

In `@Sources/CmuxConfig.swift`:
- Around line 372-373: Update the .codePuppy case in the icon mapping to return
the established “pawprint” SF Symbol instead of “dog”, preserving the existing
default-icon behavior and ensuring compatibility with supported older macOS
versions.

In `@Sources/CmuxTaskManagerCodingAgentDefinition`+BuiltIns.swift:
- Around line 50-53: Update the "code-puppy" built-in definition to include
"codepuppy" in launchKinds and both "code-puppy" and "-m code_puppy" in
argumentNeedles, while preserving the existing matchers.
🪄 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: c1d60f41-96e6-478c-af4d-ea0b37984336

📥 Commits

Reviewing files that changed from the base of the PR and between 25dc913 and a7ab821.

⛔ Files ignored due to path filters (3)
  • Assets.xcassets/AgentIcons/CodePuppy.imageset/CodePuppy.png is excluded by !**/*.png
  • Assets.xcassets/AgentIcons/CodePuppy.imageset/CodePuppy@2x.png is excluded by !**/*.png
  • Assets.xcassets/AgentIcons/CodePuppy.imageset/CodePuppy@3x.png is excluded by !**/*.png
📒 Files selected for processing (11)
  • Assets.xcassets/AgentIcons/CodePuppy.imageset/Contents.json
  • CLI/CMUXCLI+AgentHookCatalog.swift
  • CLI/cmux.swift
  • Sources/CmuxConfig.swift
  • Sources/CmuxTaskManagerCodingAgentDefinition+BuiltIns.swift
  • Sources/VaultAgentRegistry+CodePuppy.swift
  • Sources/VaultAgentRegistry.swift
  • cmuxTests/CodePuppyDetectionTests.swift
  • cmuxTests/TaskManagerResourcesTests.swift
  • docs/agent-hooks.md
  • docs/code-puppy-integration-plan.md

Comment thread CLI/CMUXCLI+AgentHookCatalog.swift Outdated
Comment thread Sources/CmuxConfig.swift Outdated
Comment thread Sources/CmuxTaskManagerCodingAgentDefinition+BuiltIns.swift Outdated
P0 (build breaker): restore displayName and statusKey on the kimi
AgentHookDef. An earlier edit accidentally dropped both required init
params when the code-puppy row was spliced in ahead of kimi.

P1 (false positive): remove 'pup' from bare-process detection. pup is
also github.com/ericchiang/pup, a popular HTML CLI — matching it by
basename would misidentify that tool as Code Puppy. pup remains a
config-kind alias and a hook CLI alias (aliases: ["pup"]) since those
are explicit user intent; cmux-launched pup is still detected via
CMUX_AGENT_LAUNCH_KIND. Removed pup from directBasenames (BuiltIns) and
Vault processNames.

Minor:
- Add aliases: ["pup"] to the code-puppy AgentHookDef so 'cmux hooks
  pup install' resolves to code-puppy.
- Use .symbol("pawprint") instead of .symbol("dog") for the default
  icon — dog is macOS 15+, pawprint is macOS 12+ (matches deploy target).
- Add 'code-puppy' argv needle so uvx/pipx run code-puppy is detected.

Skipped (with reason):
- '-m code_puppy' needle: the argv tokenizer splits on spaces, so a
  multi-token needle can never match a single argv token; the existing
  'code_puppy' needle already covers python -m code_puppy.
- 'codepuppy' launchKind: cmux only ever exports 'code-puppy' (the
  commandName) as the launch kind, so it would be dead weight.

Tests updated: bare 'pup' now asserts NO match (HTML-tool guard) plus a
launch-kind match; added a uvx code-puppy argv-needle test; dropped the
stale 'pup' basename row from the matcher table. Plan doc snippets
updated to match the final matchers.
@mattnico

Copy link
Copy Markdown
Author

Thanks for the reviews! Addressed in 13ab759:

P0 (build breaker) — greptile
Restored displayName: "Kimi Code", statusKey: "kimi" on the kimi AgentHookDef. An earlier edit accidentally dropped both required init params when the code-puppy row was spliced in ahead of kimi. Good catch — this would have failed the build.

P1 (false positive) — greptile
Removed pup from bare-process detection (both directBasenames in the task-manager def and processNames in the Vault registration). pup (github.com/ericchiang/pup) is a popular HTML CLI and matching it by basename would misidentify it as Code Puppy. pup is kept only as:

  • a config-kind alias ("agent": "pup" in cmux.json)
  • a hook CLI alias (aliases: ["pup"], so cmux hooks pup install resolves)

Both are explicit user intent. cmux-launched pup is still detected via CMUX_AGENT_LAUNCH_KIND=code-puppy.

Minor — coderabbit

  • Added aliases: ["pup"] to the code-puppy AgentHookDef.
  • Swapped .symbol("dog") → .symbol("pawprint") (dog is macOS 15+, pawprint is macOS 12+).
  • Added code-puppy argv needle so uvx / pipx run code-puppy is detected.

Skipped (with reason) — coderabbit

  • -m code_puppy needle: the argv tokenizer splits on whitespace, so a multi-token needle can never match a single argv token. The existing code_puppy needle already covers python -m code_puppy.
  • codepuppy launchKind: cmux only ever exports code-puppy (the commandName) as the launch kind, so this would be dead weight.

Tests updated accordingly: bare pup now asserts no match (HTML-tool guard) plus a launch-kind match, added a uvx code-puppy argv-needle test, and dropped the stale pup basename row from the matcher table.

Matt Nicolaysen added 4 commits July 16, 2026 20:39
Adding the .codePuppy case to CmuxConfigAgentKind made the defaultTitle(for:action:)
switch non-exhaustive, breaking the build. Add the missing case returning the
localized "Code Puppy" title, matching the commandName and defaultIcon switches.
cmux.xcodeproj uses explicit file references (no synchronized folder
groups), so files added to the worktree are silently excluded from the
build until registered in project.pbxproj.

- Inline builtInCodePuppy into VaultAgentRegistry.swift next to
  builtInPi/Omp/Antigravity/Grok (matches the majority pattern) and
  delete the standalone VaultAgentRegistry+CodePuppy.swift, which was
  never in the pbxproj and therefore never compiled — that caused
  'type CmuxVaultAgentRegistration has no member builtInCodePuppy'.
- Register cmuxTests/CodePuppyDetectionTests.swift as a PBXFileReference
  + PBXSourcesBuildPhase entry so the detection tests actually compile
  and run (lint-pbxproj-test-wiring.sh now passes: 517 files). Without
  this the whole test file was silently skipped by Xcode/CI.
- Ran scripts/normalize-pbxproj.py; scripts/check-pbxproj.sh passes.
Code Puppy's hook-config validator (hook_engine/validator.py) requires a
'matcher' field on every hook group and rejects the config outright if
it's missing — even though the loader (registry.py) would default an
absent matcher to '*'. cmux's shared .nested writer emitted groups as
{"hooks": [...]} with no matcher, so 'cmux hooks setup code-puppy'
produced a config Code Puppy refused to load:

  Configuration has 7 error(s):
   • SessionStart[0] missing required field matcher   (and 6 more)

Add an optional AgentHookDef.nestedGroupMatcher; when set, the .nested
event and feed writers include "matcher": <value> on each group. Set it
to "*" for code-puppy only. Codex/Gemini/Copilot keep nil (unchanged
output). Verified: code_puppy validate_hooks_config now returns (True, [])
for the generated ~/.code_puppy/hooks.json.
Runs the bundled CLI 'hooks code-puppy install --yes' against a temp HOME
and asserts every generated hook group (SessionStart, UserPromptSubmit,
Stop, Notification, SessionEnd, PreToolUse, PostToolUse) in
~/.code_puppy/hooks.json carries matcher "*". Without the
nestedGroupMatcher fix this fails exactly as Code Puppy's validator did
('missing required field matcher'). Wired into project.pbxproj
(lint-pbxproj-test-wiring passes: 518 files).

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/code-puppy-integration-plan.md`:
- Around line 194-202: Update the documented AgentHookDef catalog example to
include nestedGroupMatcher: "*" alongside the other required fields. Keep the
surrounding Code Puppy hook shape and explanatory text unchanged, ensuring
implementations copied from the example emit a matcher for every hook group.
🪄 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: ac25daf3-acff-4b76-8eef-6843d9ecf458

📥 Commits

Reviewing files that changed from the base of the PR and between a402d97 and 37cff73.

📒 Files selected for processing (6)
  • CLI/CMUXCLI+AgentHookCatalog.swift
  • CLI/CMUXCLI+AgentHookDefinitions.swift
  • CLI/cmux.swift
  • cmux.xcodeproj/project.pbxproj
  • cmuxTests/CodePuppyHookConfigTests.swift
  • docs/code-puppy-integration-plan.md

Comment thread docs/code-puppy-integration-plan.md

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Resources/Localizable.xcstrings`:
- Around line 50381-50431: Extend the three new localization
entries—agent.codePuppy.displayName, command.cmuxConfig.defaultCodePuppyTitle,
and command.cmuxCLI.hooks.agents—with translated values for every supported
locale currently missing, including ar, bs, da, de, es, fr, it, km, ko, nb, pl,
pt-BR, ru, th, tr, uk, zh-Hans, and zh-Hant. Preserve the fixed hook tokens and
the exact “code-puppy (alias: pup)” text in command.cmuxCLI.hooks.agents.

In `@Sources/VaultAgentRegistry.swift`:
- Line 195: Update the agent registration name in the relevant
VaultAgentRegistry entry to use the literal product name "Code Puppy" instead of
String(localized:...), keeping localization limited to surrounding UI labels.
🪄 Autofix

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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 1db17e43-8215-4db4-b331-846c51a986f2

📥 Commits

Reviewing files that changed from the base of the PR and between 37cff73 and a0b9993.

📒 Files selected for processing (9)
  • CLI/CMUXCLI+AgentHookCatalog.swift
  • CLI/cmux.swift
  • Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/CodePuppyAgentRegistration.swift
  • Packages/macOS/CMUXAgentLaunch/Tests/CMUXAgentLaunchTests/CodePuppyAgentRegistrationTests.swift
  • Resources/Localizable.xcstrings
  • Sources/CmuxConfig.swift
  • Sources/CmuxTaskManagerCodingAgentDefinition+BuiltIns.swift
  • Sources/VaultAgentRegistry.swift
  • docs/code-puppy-integration-plan.md

Comment on lines +50381 to +50431
"agent.codePuppy.displayName": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Code Puppy"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "Code Puppy"
}
}
}
},
"command.cmuxConfig.defaultCodePuppyTitle": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Code Puppy"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "Code Puppy"
}
}
}
},
"command.cmuxCLI.hooks.agents": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "codex, grok, opencode, pi, omp, campfire, amp, cursor, gemini, kiro, antigravity (alias: agy), rovodev (alias: rovo), hermes-agent, copilot, codebuddy, factory, qoder, code-puppy (alias: pup)"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "codex、grok、opencode、pi、omp、campfire、amp、cursor、gemini、kiro、antigravity(エイリアス: agy)、rovodev(エイリアス: rovo)、hermes-agent、copilot、codebuddy、factory、qoder、code-puppy(エイリアス: pup)"
}
}
}
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

python3 - <<'PY'
import json
from pathlib import Path

data = json.loads(Path("Resources/Localizable.xcstrings").read_text())
keys = [
    "agent.codePuppy.displayName",
    "command.cmuxConfig.defaultCodePuppyTitle",
    "command.cmuxCLI.hooks.agents",
]

for key in keys:
    locales = sorted(data["strings"][key].get("localizations", {}))
    print(f"{key}: {locales}")
PY

Repository: manaflow-ai/cmux

Length of output: 294


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
import json
from pathlib import Path

path = Path("Resources/Localizable.xcstrings")
data = json.loads(path.read_text())
strings = data.get("strings", {})

all_localizations = set()
for _, entry in strings.items():
    locs = entry.get("localizations", {})
    all_localizations.update(locs.keys())

keys = [
    "agent.codePuppy.displayName",
    "command.cmuxConfig.defaultCodePuppyTitle",
    "command.cmuxCLI.hooks.agents",
]
for key in keys:
    entry = strings.get(key, {})
    locales = sorted(entry.get("localizations", {}).keys())
    missing = []
    for locale in sorted(all_localizations):
        loc = entry.get("localizations", {}).get(locale, {})
        value = loc.get("stringUnit", {}).get("value")
        if value in (None, ""):
            missing.append(locale)
    print(f"{key}:")
    print(f"  present: {locales}")
    print(f"  missing_or_empty: {missing or '<none>'}")
    for locale in missing:
        loc = entry.get("localizations", {}).get(locale, {})
        print(f"    {locale}: {loc.get('stringUnit')}")
PY

printf '\nFirst 60 lines of xcstrings metadata:\n'
python3 - <<'PY'
import json
from pathlib import Path
data = json.loads(Path("Resources/Localizable.xcstrings").read_text())
for k in ["sourceLanguage", "version", "supportedLocales"]:
    if k in data:
        print(f"{k}: {json.dumps(data[k], indent=2)}")
PY

Repository: manaflow-ai/cmux

Length of output: 1569


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
import json
from pathlib import Path

path = Path("Resources/Localizable.xcstrings")
data = json.loads(path.read_text())
strings = data.get("strings", {})

all_localizations = set()
for _, entry in strings.items():
    locs = entry.get("localizations", {})
    all_localizations.update(locs.keys())

print("Global localization set:", sorted(all_localizations))
PY

printf '\nLines around agent.codePuppy related keys:\n'
sed -n '50350,50445p' Resources/Localizable.xcstrings

Repository: manaflow-ai/cmux

Length of output: 2891


Add localizations for the missing supported locales.

Resources/Localizable.xcstrings supports 21 locales, but the new entries only provide en and ja. Add matching translated values for agent.codePuppy.displayName, command.cmuxConfig.defaultCodePuppyTitle, and command.cmuxCLI.hooks.agents, including every missing locale such as ar, bs, da, de, es, fr, it, km, ko, nb, pl, pt-BR, ru, th, tr, uk, zh-Hans, and zh-Hant. Keep code-puppy (alias: pup) and the other hook tokens fixed in command.cmuxCLI.hooks.agents.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Resources/Localizable.xcstrings` around lines 50381 - 50431, Extend the three
new localization entries—agent.codePuppy.displayName,
command.cmuxConfig.defaultCodePuppyTitle, and command.cmuxCLI.hooks.agents—with
translated values for every supported locale currently missing, including ar,
bs, da, de, es, fr, it, km, ko, nb, pl, pt-BR, ru, th, tr, uk, zh-Hans, and
zh-Hant. Preserve the fixed hook tokens and the exact “code-puppy (alias: pup)”
text in command.cmuxCLI.hooks.agents.

Sources: Coding guidelines, Path instructions

let contract = CodePuppyAgentRegistration.standard
return CmuxVaultAgentRegistration(
id: contract.id,
name: String(localized: "agent.codePuppy.displayName", defaultValue: "Code Puppy"),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Keep the Code Puppy product name stable.

Code Puppy is a product name, not translatable UI text. Localizing this registration field makes its value depend on the active locale. Use the literal "Code Puppy" here and localize only surrounding UI labels.

Based on learnings, brand and product name literals should not use String(localized:...).

Proposed fix
-            name: String(localized: "agent.codePuppy.displayName", defaultValue: "Code Puppy"),
+            name: "Code Puppy",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
name: String(localized: "agent.codePuppy.displayName", defaultValue: "Code Puppy"),
name: "Code Puppy",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Sources/VaultAgentRegistry.swift` at line 195, Update the agent registration
name in the relevant VaultAgentRegistry entry to use the literal product name
"Code Puppy" instead of String(localized:...), keeping localization limited to
surrounding UI labels.

Source: Learnings

This branch has not been deployed

No deployments
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.

2 participants