A macOS Chromium browser shell using SwiftUI, AppKit, Objective-C++ and native Chromium. The native shell owns Spaces, tab tiers, split pages, Spotlight, address editing, History, Downloads and Settings. Chromium owns page rendering and navigation. Browser surfaces and their native editors remain mounted across selection and UI updates.
See code provenance, reuse scope and third-party notices. Chromium is the active native engine. Two Mori BrowserWindow files are adapted under MIT with attribution and a bundled license.
Requires macOS 26+, Apple Silicon, Xcode with Swift 6, and XcodeGen. Chromium 152.0.7977.83 is pinned by the engine scripts and is not committed. Xcode 27 and the Apple Metal Toolchain are required for this engine build.
python3 Scripts/try_chromium_build.py # once; official source and resumable build
CONFIGURATION=Debug Scripts/build.shThe build incrementally compiles the native Chromium bridge, regenerates Cio.xcodeproj, installs the shared scheme and packages/signs Chromium, its component libraries and four standard Helpers. The product is build/DerivedData/Build/Products/Debug/Cio.app. Use CONFIGURATION=Release with the same script for Release. Source, toolchains, binaries and generated projects stay under ignored build directories.
For a stable local signing identity, add the following to ~/.zshrc, using a certificate name from security find-identity -v -p codesigning:
export CIO_CODE_SIGN_IDENTITY="Apple Development: your certificate name"
# Optional: the development team's ID from your Apple Developer account.
# export CIO_DEVELOPMENT_TEAM="YOUR_TEAM_ID"Open a new terminal or run source ~/.zshrc, then build with the same command above. The script reads these exported variables and uses the selected Keychain identity for the app, frameworks and Helpers. A certificate's SHA-1 fingerprint is also accepted. With no variables configured, signing uses the project's ad-hoc defaults. Explicit build settings passed to Scripts/build.sh override the environment. Keep personal certificate names and team IDs in shell configuration rather than project.yml.
Scripts/package_native_chromium.py closes the runtime dependency graph using bundle-relative paths. Scripts/verify_bundle.sh checks native exports, libraries, signatures and licenses without launching the app. See the native engine guide for profiles, updates, codecs and current UI limitations.
CONFIGURATION=Debug Scripts/verify_current.shIndividual entry points:
| Script | Coverage |
|---|---|
| verify_unit_tests.sh | Standalone XCTest and local package tests |
| verify_bundle.sh | Individual App/framework/Helper signatures, identities and linkage |
| verify_runtime.sh | Native Chromium bundle and isolated runtime acceptance |
| verify_rendering.sh | Real application page load, callbacks and typed shutdown |
| verify_navigation.sh | Parser/probe, navigation, reload/stop, redaction and quit ordering |
| verify_tabs.sh | Multi-browser quit, real main menu and URL privacy |
| verify_workspace.sh | Current Space/tab/runtime invariants from the compatibility driver |
| verify_session_restore.sh | Separate seed/relaunch processes, exact persistence and lazy sessions |
| verify_history_downloads.sh | History/download callback driver, SQLite and downloaded bytes |
| verify_stability.sh | Tab/Space stress, lazy restore, beforeunload, bounded soak and Release |
| verify_release_candidate.sh | Hardened local Release bundle, rendering, restore, history/downloads |
| check_no_secrets.sh | Tracked files and git history; matched secret values are never printed |
The numbered verify_milestone scripts forward to these responsibility-based scripts for existing callers. No historical feature-stage specification is used as the current implementation contract.
The pre-refactor baseline had passing build, 244 passing unit tests, runtime/bundle checks and secret scan, but failing historical checks. Those failures are recorded separately in refactor progress. They have not been repaired or relabeled as successful validation. The old browser-close harness is excluded from the rendering gate; three obsolete shared-editor focus expectations in the compatibility workspace driver are explicitly labeled retired coverage. Unexpected runtime failures still fail validation.
Manual verification covers native keyboard/focus/IME and actual visual behavior. Script results do not claim these checks were performed. Open the freshly built Debug bundle only for explicitly requested computer-use validation.
The application imports the stable Objective-C CioChromium interface and uses the chromium-native backend. Native Browser/WebContents views are attached to Cio's existing AppKit shell. Chrome Settings is opened as a Cio tab using the same profile. The native engine is built separately with a version-pinned overlay; engine upgrades require rebuilding that overlay and replacing the complete runtime bundle. See architecture and upgrade boundaries.
Cio/
App/ entry point, scene, native menus and runtime
Diagnostics/ existing self-tests and navigation/sidebar probes
Browser/ workspace policy, sessions and Chromium containers
Resources/ Info.plist and signing entitlements
Tests/ standalone logic/native-model tests
Engine/
CioChromium/ public interface, native loader, shared containers and GN bridge
Chromium/ migration status and pinned source reference
Packages/
CioModel/
Sources/CioModel/ workspace/tab/split/snapshot values, parsing, URL redaction
Tests/CioModelTests/ workspace, parsing, exact-URL and log-redaction tests
CioEngine/
Sources/CioEngine/
Interfaces/ original-object protocols and navigation/download values
Browser/ site information, navigation and Spotlight completion
Persistence/ session JSON and SQLite history
History/ history values
Downloads/ original destination policy and download state
App/ shared logging categories
CioUI/
Sources/CioUI/
UI/
Main/ native shell, stable pages/toolbars and viewports
CommandBar/ NSTextField editor/model and menu notifications
Sidebar/ retained rows, dragging and Metal scroll-edge resource
Spotlight/ input/completion presentation
Internal/ History and Downloads views
Settings/ native settings
Visual/ native glass, controls and favicon views
Animation/ shared motion, tuning and preferences
SchemeTemplates/Cio.xcscheme
Scripts/ reproducible build and verification tools
ThirdParty/ upstream license notices
project.yml sole Xcode project definition
AGENTS.md shell, native-control, animation and validation constraints
ARCHITECTURE.md current ownership, lifetime and interaction design
- Chromium initialization, pumping and shutdown belong to the application, not views. Termination cancels the native request, waits for typed OnBeforeClose from every live session, shuts Chromium down once and retries termination.
- WorkspaceCollection owns domain identity/order/policy. BrowserSessionManager owns only live sessions and stable containers. Restored inactive tabs are lazy; selection cannot rebuild a live browser.
- Each page retains a tab-bound toolbar/editor and outer viewport. Section, tab and split changes preserve native component identity. Shared layout dimensions come from BrowserShellLayout.swift.
- Address editing uses native NSTextField and its field editor. The committed URL and edit buffer are separate; background callbacks cannot overwrite active input. Selecting another page ends the outgoing address edit.
- Cmd-L/R/[/] and tab commands are native menu equivalents. Cmd-T opens Spotlight. Current selection is resolved at action time.
- Popups route to managed tabs using the source runtime identity. Chromium C++ objects and download callbacks stay behind the bridge.
- Navigation and persistence retain complete URLs. Every URL log/probe uses the single URLLogSanitizer policy.
- Native materials, system controls and animation APIs retain their normal interactions. Animation tuning and speed scaling live in Packages/CioUI/Sources/CioUI/Animation/; AGENTS.md records the required geometry and motion contract.
See ARCHITECTURE.md for the current design and lifetime details.
Self-tests and probes live in Cio/Diagnostics. Historical numbered script entry points and trace labels remain tooling compatibility names; current implementation contracts are responsibility-based. CLI switches remain unchanged, including --navigation-self-test, --tabs-self-test, --spaces-self-test, --parse-navigation-input=, --session-restore-self-test=, --m7-self-test= and --m8-self-test=.
The retired CEF backend, custom CEF Helper, setup/build/package scripts and local CEF binaries have been removed. Legacy cef: trace labels, --cef-self-test and download callback field names remain compatible with existing diagnostic callers; they do not load or depend on CEF. The loader retains one-time copying of an inactive legacy profile and preserves its original directory. Scripts/verify_runtime.sh --mock-keychain now checks the native bundle and runs the native Chromium acceptance driver with disposable profiles.
build/DerivedData/Build/Products/Debug/Cio.app/Contents/MacOS/Cio --parse-navigation-input="https://example.com/"The main bundle ID is com.cerbur.Cio. Browser profile, session-v1.json and history.sqlite3 use ~/Library/Application Support/Cio/ by default. CIO_DATA_DIR overrides storage for verification; CIO_DOWNLOADS_DIR overrides the download destination. Changing the bundle ID changes the UserDefaults preference domain; existing preferences are not migrated implicitly. The browser data directory remains Cio.
Native Cio uses its own Cio Safe Storage keychain item rather than Chrome/Chromium's item. Development signing is ad-hoc: a changed binary identity can still cause a macOS authorization dialog after a rebuild. A stable signing identity is required for distribution and reliable authorization across updates. Verification cannot answer a user's keychain prompt or change its access policy. Scripts/verify_native_runtime.py --mock-keychain uses Chromium's explicit test keychain only with disposable profiles in the system temporary directory; logs remain under build/verification/native-runtime. It does not validate production encrypted-cookie migration.
Cookies (including session cookies) use Chromium's persistent profile and are flushed before normal application termination. Chromium continues to enforce expiry and the user's cookie/site-data policies. On the first launch with language initialization enabled, Cio seeds the profile's selected and accept languages from macOS's ordered preferred languages, normalizing Chinese script tags for Chrome. Later changes in chrome://settings/languages persist without a recurring language override. Native Settings provides entry points to Chrome Settings, Languages, Cookies, Site Data and Privacy in the current Cio profile.
The app currently supports one workspace window. Chromium navigation history and form/scroll state are not restored from Cio workspace snapshots; live popups retain their original WebContents and opener. Developer ID signing/notarization and final distribution assets remain outside the current local build.