Skip to content

Latest commit

 

History

History
161 lines (127 loc) · 8.09 KB

CONTRIBUTING.md

File metadata and controls

161 lines (127 loc) · 8.09 KB

Contributing to cmux

New here? Read docs/start-here.md first: how to pick an issue, what you can fix without a Mac, and what happens to your pull request. This file is the mechanics: setup, checks, CI and the pull request checklist.

Be nice, assume the best: CODE_OF_CONDUCT.md. Write issues and pull requests the way the short writing guide says.

Prerequisites

Only needed for the native app. Docs, translations, Python tooling, cmux-tui and web/ work on Linux; see what you can fix without a Mac build.

  • macOS 14+

  • Xcode 26 (the pinned toolchain). Xcode 16.2 on Intel Macs with macOS 14.5+ also builds the app, best effort (Swift 6.0 limits).

  • The Xcode 26 Metal compiler, which is a separate download. Select the Xcode you build with first (DEVELOPER_DIR overrides xcode-select), then:

    xcodebuild -downloadComponent MetalToolchain
  • Zig: brew install zig

  • Rust. Every app build compiles the bundled cmux-cua engine with cargo, and scripts/setup.sh looks for rustup in ~/.cargo/bin, where the official installer puts it:

    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

    Homebrew's rustup works too, but it is keg-only: add $(brew --prefix rustup)/bin to PATH and run rustup default stable yourself.

Getting Started

git clone --recursive https://github.com/manaflow-ai/cmux.git
cd cmux
./scripts/setup.sh
CMUX_DEV_BACKEND_MODE=local ./scripts/reload.sh --tag my-feature
  • setup.sh initializes the submodules, installs the pinned Rust toolchain, and fetches a checksum-pinned prebuilt GhosttyKit.xcframework (it builds from source with Zig if that fails; force that with CMUX_GHOSTTYKIT_NO_PREBUILT=1).
  • reload.sh --tag <tag> builds a tagged Debug app and prints its path. Add --launch to open it, or --build-only to only compile. CMUX_DEV_BACKEND_MODE=local points it at the local dev origin; without it a tagged build expects the maintainers' shared backend and stops. See tagged builds for cache reuse and Release variants.
  • reload.sh skips emitting the app's Swift module to make rebuilds a little faster, except on Xcode 26.2 and 26.3, where that build stops at the module merge with error: type mismatch of function ... but used in a swift module as .... If you see that error on another Xcode, rerun with CMUX_RELOAD_APP_EMIT_MODULE=1.
  • After pulling changes to setup or the merge drivers, rerun ./scripts/install-git-hooks.sh. With a custom core.hooksPath it prints the pre-commit and post-merge lines to add yourself; wire both.

Team members with a Stack account can also sign DEBUG builds in and attach an iOS build: see team dev setup.

Fast checks before committing or building

python3 scripts/verify-local.py

It picks the static checks your diff touches (localization, project and test wiring, package grouping, generated policy, feature flags) and parses changed Swift. It compares against your local upstream/HEAD, then origin/HEAD, and fetches nothing. When a check fails it prints the rerun command, for example:

python3 scripts/verify-local.py --only project --only test-wiring

--list previews, --all runs the full static recipe CI uses, and --receipt - prints JSON (details). Parsing is not typechecking or testing. The script runs repository code, so use a trusted checkout. Git push does not run it for you.

For web/ and other JS/TS sources, run bun run biome:check from the repository root. The root biome.json deliberately scopes that to maintained web and JS/TS sources, excluding generated bundles, build outputs, vendored trees and review-tool metadata. Formatting and import sorting are off for now, so do not wire this into required CI until the remaining source lint diagnostics are paid down.

Tests and CI

Go up the verification ladder as far as your change needs: source checks, the owning package's tests, compiling the app and tests, then runtime and physical checks. In the pull request, say which of those you ran. A parse or a build is not a test run.

You do not need to run the app-host or UI tests on your own Mac. They launch the app and need a disposable GUI session. If you can't run them, open the pull request anyway and say so under Testing. Opening the pull request is the request for CI:

  • Static checks run on every pull request. The Linux guards run when your diff touches what they cover.
  • Swift, package, app-host and tooling tests are routed from your diff: an edited suite runs, and an app-source change runs the suites whose tests mention what you changed. No label needed.
  • The broad macOS suite is label-gated. A maintainer adds full-ci when a change needs it (PR CI coverage). It is not a merge requirement.
  • No pull request job runs cmuxUITests/ in full. If you touch that directory, the suite-coverage check stays red until a maintainer runs the affected classes and records it with no-full-ci.
  • On your first pull request, checks wait for a maintainer to approve the workflow run. That's a GitHub default for new contributors, not a judgement on the patch.

Read which tests actually ran on your commit, not the color of the checks list: a skipped job is green and is not coverage.

Ghostty Submodule

ghostty points to manaflow-ai/ghostty, our fork of Ghostty. To change it, rebuild GhosttyKit.xcframework or pull in upstream, follow the cmux-ghostty skill: push the submodule commit to the fork before committing the pointer here. Fork changes and conflict notes are in docs/ghostty-fork.md.

Pull Requests

  • One change per pull request. A fix plus a reformat is two pull requests.
  • Fill in the template: a summary of the problem and what someone can do after the change, and Testing with the commands you ran.
  • For a bug fix, commit the failing regression test before the fix (regression commits).
  • Under ## Changelog, write one Added/Changed/Fixed/Removed line for a user-visible change, or none. Don't edit CHANGELOG.md; releases build it from these lines.
  • Localize user-facing strings (localization skill).
  • No unrelated formatting, generated files, vendored trees or version bumps.
  • Sign the CLA once by commenting I have read the CLA Document v2.2 and I hereby sign the CLA on your pull request. The check matches commit author emails to your GitHub account, so commit with an email linked to it.

Merges are squash merges, so the title and description become the commit that ships. How review works and what makes a patch wait is in start here.

Agents working in this repository also follow CLAUDE.md (also AGENTS.md).

License

By contributing to this repository, you agree that:

  1. Your contributions are licensed under the license of the directory you contribute to: the Business Source License 1.1 (BUSL-1.1) for the server directories listed in LICENSE (web/, workers/ci-artifacts/, workers/iroh-v2/, workers/presence/, services/iroh-relay-minter/, cmux-tui/relays/cloudflare-do/), and the project's GNU General Public License v3.0 or later (GPL-3.0-or-later) everywhere else unless a file states otherwise.
  2. You grant Manaflow, Inc. a perpetual, worldwide, non-exclusive, royalty-free, irrevocable license to use, reproduce, modify, sublicense, and distribute your contributions under any license, including a commercial license offered to third parties.