make # this show available commandsRequires mise for zig, swiftlint, swift-format, xcbeautify, and xcsift tooling. Run mise install once to fetch the pinned versions.
Supacode is a macOS terminal emulator that for running multiple coding agents in parallel in Git worktrees, using GhosttyKit as the underlying terminal.
- TCA (swift-composable-architecture): App state, reducers, side effects
- GhosttyKit: Terminal emulator (built from Zig source in ThirdParty/ghostty)
- Sparkle: Auto-update framework
- swift-dependencies: Dependency injection for TCA clients
- PostHog: Analytics
- Sentry: Error tracking
- Target macOS 26.0+, Swift 6.0
- Before doing a big feature or when planning, consult with pfw (pointfree) skills on TCA, Observable best practices first.
- Use
@ObservableStatefor TCA feature state; use@Observablefor non-TCA shared stores; neverObservableObject - Always mark
@Observableclasses with@MainActor - Modern SwiftUI only:
foregroundStyle(),NavigationStack,ButtonoveronTapGesture() - When a new logic changes in the Reducer, always add tests
- In unit tests, never use
Task.sleep; useTestClock(or an injected clock) and drive time withadvance. - Prefer Swift-native APIs over Foundation where they exist (e.g.,
replacing()notreplacingOccurrences()) - Avoid
GeometryReaderwhencontainerRelativeFrame()orvisualEffect()would work - Do not use NSNotification to communicate between reducers.
- Prefer
@Shareddirectly in reducers for app storage and shared settings; do not introduce new dependency clients solely to wrap@Shared. - Use
SupaLoggerfor all logging. Never useprint()oros.Loggerdirectly.SupaLoggerprints in DEBUG and usesos.Loggerin release. - Avoid top-level free functions. Default to
staticmethods, computed properties, or instance methods on a relevant type (enum/struct/extension). Free functions pollute the module namespace, are harder to discover, and easily drift from the inline implementation a consumer ends up writing instead. If the operation is pure and stateless, make it astaticon a caselessenumor the most relevant type, not a top-levelfunc. - Closure-typed focused values invalidate the AppKit menu on every body run (closures have no Equatable conformance, so SwiftUI re-publishes every time). Always wrap menu-bar action closures with
FocusedAction<Input>and publish via.focusedSceneAction(_:enabled:token:perform:)/.focusedAction(_:enabled:token:perform:). The wrapper dedupes on(isEnabled, token), so AppKit only rebuilds the menu when something the menu actually displays changes. Token rules inApp/Models/FocusedAction.swift: settokento a hashable projection of any captured state that affects behavior; leave itnilwhen the closure captures only the store /@Statebindings. Consumers should read the action with@FocusedValue(\.x)and gate withaction?.isEnabled != true, notaction == nil. - Sidebar rows must not fan out invalidation. Per-row state lives in
RepositoriesFeature.State.sidebarItemsso a per-leaf mutation (notification tick, agent activity, running-script update) invalidates only that leaf, not every sibling. The view renders the cachedstate.sidebarStructure(computed in the reducer's post-reduce hook), never readingsidebarItems[id:]from a view body; derive per-leaf data incomputeSidebarStructure(...), not in the view.
- Buttons must have tooltips explaining the action and associated hotkey
- Use Dynamic Type, avoid hardcoded font sizes
- Components should be layout-agnostic (parents control layout, children control appearance)
- Never use custom colors, always use system provided ones.
- We use
.monospaced()modifier on fonts when appropriate
- After a task, ensure the app builds:
make build-app - Automatically commit your changes and your changes only. Do not use
git add . - Before you go on your task, check the current git branch name, if it's something generic like an animal name, name it accordingly. Do not do this for main branch
- Do not open a pull request unless the user explicitly asks for one. Commit to the working branch and let the user decide when to push and open a PR.
- When the user does ask you to open an issue or pull request, follow the templates in
.github: fill the bug or feature issue form, and use the pull request template (link the issue withCloses #<number>, complete the checklist, and disclose any AI tools you used). A human is the author of record: never set an AI agent as a commit author or co-author.