|
| 1 | +# Rebrand cmux → Programa — progress & remaining map |
| 2 | + |
| 3 | +Branch: `feat/rebrand-cmux-to-programa`. Every commit below is **build-green** (compile-only |
| 4 | +gate via `-scheme programa ... build`, or `build-for-testing` for the test phase). Runtime |
| 5 | +contracts compile but need CI/manual verification before merge. |
| 6 | + |
| 7 | +## Done (11 commits, off origin/main) |
| 8 | + |
| 9 | +0. **docs** — cmux→Programa in docs, manaflow-ai→darkroomengineering, README promo cleanup. |
| 10 | +1. **symbols** — `Cmux*`→`Programa*` (excl. AppleScript + DockTile files). |
| 11 | +2. **source files** — 6 files `git mv` + pbxproj. |
| 12 | +3. **test targets** — `cmuxTests`/`cmuxUITests`→`programaTests`/`programaUITests` + schemes' test labels. |
| 13 | +4. **schemes/CLI target/scripts/CI** — schemes renamed, `programa-cli` target, bridging header, |
| 14 | + scripts `-scheme`/DerivedData prefix, CI scheme+test-target refs. (`PRODUCT_NAME` was already `programa`.) |
| 15 | +5. **config paths** — `~/.config/programa/` + `programa.json` with dual-read legacy fallback. |
| 16 | +6a. **DockTile** — `CmuxDockTilePlugin`→`ProgramaDockTilePlugin` (class+target+product+Info.plist NSDockTilePlugIn). |
| 17 | +6b. **AppleScript** — `@objc(CmuxScript*)`→`ProgramaScript*` + `.sdef` cocoa-class + user-facing text; AE `code=` preserved. |
| 18 | +6c. **browser JS bridge** — `__cmux*`→`__programa*` + handlers (`cmuxIMEState`/`cmuxAddressBarFocusState`/`cmuxReactGrab`) across 7 files. |
| 19 | +6e. **CMUXCommit** — Info.plist commit key → `ProgramaCommit` (build writer + readers; no shim, regenerated per build). |
| 20 | +6-UserDefaults. **migration shim** — version-gated startup copy of every `cmux`-prefixed default → |
| 21 | + `programa`-prefixed (never deletes legacy). Renamed standalone keys (welcomeShown, surfacePoolEnabled, |
| 22 | + devMutate…, debugBG, focusDebug, keyLatencyProbe, shortcutMonitorTrace, typingTimingLogs, settingsFile.backups). |
| 23 | + |
| 24 | +## Remaining (each = its own build-gated commit; runtime = CI/manual) |
| 25 | + |
| 26 | +### 6d — shell-integration lockstep (LARGE) |
| 27 | +- Files: `Resources/shell-integration/cmux-{bash,zsh}-integration.{bash,zsh}` (~100+ `cmux_*` shell |
| 28 | + functions/vars, mostly internal to the scripts) + Swift/CLI refs in `GhosttyTerminalView.swift`, |
| 29 | + `KeyboardShortcutSettingsFileStore.swift`, `ProgramaApp.swift`, `Workspace.swift`, `CLI/programa.swift`. |
| 30 | +- Cross-boundary protocol tokens (rename BOTH sides in lockstep): `$cmux_port`, `$cmux_tty`, `$cmux_pid`, |
| 31 | + `cmux_shell_dir`, `cmuxPortBase`/`cmuxPortRange` (injected window globals + `@AppStorage`), the |
| 32 | + `cmux-{bash,zsh}-integration` **filenames** (+ pbxproj Copy-Resources phase `CMUX_SHELL_*` vars, line 440), |
| 33 | + and any `cmux-integration.zsh` dest name. |
| 34 | +- Approach: rename script filenames + `s/cmux_/programa_/g` inside the scripts, then rename every matching |
| 35 | + token on the Swift/CLI side. `cmuxPortBase/Range` covered by the UserDefaults migration already shipped. |
| 36 | +- Verify: `tests_v2` shell/port tests on CI + manual (open terminal, PR sidebar, port detection). |
| 37 | + |
| 38 | +### 6f — CLI command name + SSH (LARGE, 386 `cmux` refs in `CLI/programa.swift`) |
| 39 | +- Binary is ALREADY `programa` (PRODUCT_NAME). Categorize the 386: |
| 40 | + - user-facing help/usage strings `cmux <sub>` → `programa` (command is already programa). |
| 41 | + - remote SSH bootstrap: `~/.cmux/`→`~/.programa/` (issue #15 partially done — verify), `cmux_remote_bootstrap` |
| 42 | + fn + remote `cmux` invocation → programa; socket paths (check already-programa). |
| 43 | + - internal fn/var names → cosmetic. |
| 44 | + - DO NOT blanket-sed (hits socket paths, env vars, remote tokens). Categorize per-occurrence. |
| 45 | +- Verify: `tests_v2/test_ssh_remote_*.py` on CI. |
| 46 | + |
| 47 | +### 6g — user-facing brand strings (`Resources/Localizable.xcstrings` + a few Swift defaults) |
| 48 | +- Brand noun `cmux`→`Programa` ("Quit cmux", "About cmux", "cmux CLI", notifications, error text). |
| 49 | +- CLI usage strings inside xcstrings ("Usage: cmux claude-teams", "Install 'cmux' in PATH") → `programa` (lowercase command). |
| 50 | +- EN + JA. Distinguish brand (Programa) vs command (programa) per string — NOT a blanket sed. |
| 51 | + |
| 52 | +### 6h — release artifacts |
| 53 | +- `cmux.entitlements` → `programa.entitlements` (git mv + pbxproj `CODE_SIGN_ENTITLEMENTS` + `build-sign-upload.sh` + release/nightly yml). |
| 54 | +- DMG names `cmux-nightly-macos*.dmg`/`cmux-release-*` → `programa-*` (release.yml, nightly.yml) so README's `programa-macos.dmg` link resolves. |
| 55 | +- homebrew cask refs in `build-sign-upload.sh` (or delete per the board-sweep plan #7). |
| 56 | + |
| 57 | +### Analytics (keep + note) |
| 58 | +- PostHog `"platform": "cmuxterm"` (`PostHogAnalytics.swift:219`) and `com.cmuxterm.*` queue labels — KEEP the |
| 59 | + `cmuxterm` analytics value for historical continuity; add a comment. Queue labels are cosmetic (optional rename). |
| 60 | + |
| 61 | +### Bulk internal identifiers (SAFE but voluminous — do last) |
| 62 | +- Remaining lowercase `cmux*` camelCase Swift symbols (`cmuxAccentColor`, `cmuxOwning*`, `cmuxConfigStore`, …) |
| 63 | + and `cmux.*` os_log subsystems / dispatch-queue labels / in-process notification names. Pure internal, no |
| 64 | + contract → compile-verified. Big mechanical pass; exclude URLs, the analytics value, and anything already |
| 65 | + handled above. Consider delegating with a build gate. |
| 66 | + |
| 67 | +## Build recipe |
| 68 | +``` |
| 69 | +PROGRAMA_SKIP_ZIG_BUILD=1 xcodebuild -project GhosttyTabs.xcodeproj -scheme programa \ |
| 70 | + -configuration Debug -destination 'platform=macOS' -derivedDataPath /tmp/programa-rebrand \ |
| 71 | + PROGRAMA_SKIP_ZIG_BUILD=1 build 2>&1 | grep -iE "error:|BUILD (FAILED|SUCCEEDED)" |
| 72 | +``` |
| 73 | +Never blanket-sed lowercase `cmux` (hits URLs, shell vars, command name, socket paths, analytics). Keep |
| 74 | +`com.darkroom.programa` bundle IDs. Don't touch `ghostty/`. |
0 commit comments