Conversation
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.
Bugbot is paused — on-demand spend limit reachedBugbot 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. |
|
Someone is attempting to deploy a commit to the Manaflow Team on Vercel. A member of the Team first needs to authorize it. |
📝 WalkthroughWalkthroughCode 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. ChangesCode Puppy integration
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
Possibly related PRs
Suggested reviewers: Important Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional. ❌ Failed checks (1 error, 2 warnings, 1 inconclusive)
✅ Passed checks (21 passed)
✨ Finishing Touches 💡 2⚔️ Resolve merge conflicts 💡
🛠️ Fix failing CI checks 💡
🧪 Generate unit tests (beta)
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. Comment |
Greptile SummaryThis 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.
Confidence Score: 5/5This 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
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]
%%{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]
Reviews (4): Last reviewed commit: "test: assert Code Puppy hook groups carr..." | Re-trigger Greptile |
| AgentHookDef( | ||
| name: "kimi", | ||
| configDir: ".kimi-code", configFile: "config.toml", configDirEnvOverride: "KIMI_CODE_HOME", |
There was a problem hiding this comment.
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.
| 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", |
| .init(id: "code-puppy", displayName: "Code Puppy", assetName: "AgentIcons/CodePuppy", | ||
| launchKinds: ["code-puppy"], | ||
| directBasenames: ["code-puppy", "code_puppy", "pup"], | ||
| argumentNeedles: ["code_puppy"]), |
There was a problem hiding this comment.
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.
| .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)
There was a problem hiding this comment.
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
⛔ Files ignored due to path filters (3)
Assets.xcassets/AgentIcons/CodePuppy.imageset/CodePuppy.pngis excluded by!**/*.pngAssets.xcassets/AgentIcons/CodePuppy.imageset/CodePuppy@2x.pngis excluded by!**/*.pngAssets.xcassets/AgentIcons/CodePuppy.imageset/CodePuppy@3x.pngis excluded by!**/*.png
📒 Files selected for processing (11)
Assets.xcassets/AgentIcons/CodePuppy.imageset/Contents.jsonCLI/CMUXCLI+AgentHookCatalog.swiftCLI/cmux.swiftSources/CmuxConfig.swiftSources/CmuxTaskManagerCodingAgentDefinition+BuiltIns.swiftSources/VaultAgentRegistry+CodePuppy.swiftSources/VaultAgentRegistry.swiftcmuxTests/CodePuppyDetectionTests.swiftcmuxTests/TaskManagerResourcesTests.swiftdocs/agent-hooks.mddocs/code-puppy-integration-plan.md
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.
|
Thanks for the reviews! Addressed in P0 (build breaker) — greptile P1 (false positive) — greptile
Both are explicit user intent. cmux-launched Minor — coderabbit
Skipped (with reason) — coderabbit
Tests updated accordingly: bare |
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).
There was a problem hiding this comment.
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
📒 Files selected for processing (6)
CLI/CMUXCLI+AgentHookCatalog.swiftCLI/CMUXCLI+AgentHookDefinitions.swiftCLI/cmux.swiftcmux.xcodeproj/project.pbxprojcmuxTests/CodePuppyHookConfigTests.swiftdocs/code-puppy-integration-plan.md
There was a problem hiding this comment.
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
📒 Files selected for processing (9)
CLI/CMUXCLI+AgentHookCatalog.swiftCLI/cmux.swiftPackages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/CodePuppyAgentRegistration.swiftPackages/macOS/CMUXAgentLaunch/Tests/CMUXAgentLaunchTests/CodePuppyAgentRegistrationTests.swiftResources/Localizable.xcstringsSources/CmuxConfig.swiftSources/CmuxTaskManagerCodingAgentDefinition+BuiltIns.swiftSources/VaultAgentRegistry.swiftdocs/code-puppy-integration-plan.md
| "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)" | ||
| } | ||
| } | ||
| } | ||
| }, |
There was a problem hiding this comment.
🎯 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}")
PYRepository: 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)}")
PYRepository: 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.xcstringsRepository: 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"), |
There was a problem hiding this comment.
🎯 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.
| 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
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)
code-puppyandpupconsole scripts, andpython -m code_puppymodule invocationCMUX_AGENT_LAUNCH_KIND=code-puppysupport for wrapper launchers (e.g.uv run)Launch config kind (Tier 1)
.codePuppycase inCmuxConfigAgentKindso action buttons incmux.jsoncan specify"agent": "code-puppy"with a proper default iconSession tracking, restore & Feed (Tier 2)
.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 neededSessionStart,UserPromptSubmit,Stop,Notification,SessionEndPreToolUse,PostToolUsesessionIdSource: .argvOption("--resume")— cmux mints the session name at launch, reads it from argv, and replayscode-puppy --resume <name>on restoreCMUX_CODE_PUPPY_PIDwired into both PID-inference switchesIcon (Tier 3)
AgentIcons/CodePuppyimageset — 14/28/42 px PNGs from the Code Puppy brand markDocs
docs/agent-hooks.md: integrations table, supported-agent list, auto-naming skip list, environment overrides tableKey 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.jsonin the same JSON shape cmux's existing.nestedwriter already produces for Codex/Gemini/Copilot. This means the integration needs:AgentHookDefcatalog row + one Vault registrationTesting
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.Files changed
cmuxTests/CodePuppyDetectionTests.swiftcmuxTests/TaskManagerResourcesTests.swiftSources/CmuxTaskManagerCodingAgentDefinition+BuiltIns.swiftSources/CmuxConfig.swift.codePuppylaunch kindSources/VaultAgentRegistry+CodePuppy.swiftSources/VaultAgentRegistry.swiftbuiltInCodePuppyintoload()CLI/CMUXCLI+AgentHookCatalog.swiftAgentHookDefrowCLI/cmux.swiftAssets.xcassets/AgentIcons/CodePuppy.imageset/docs/agent-hooks.mddocs/code-puppy-integration-plan.mdSummary by CodeRabbit
code-puppyandpupcommand aliases.CMUX_CODE_PUPPY_HOOKS_DISABLED=1.