docs

Homebrew tap

Homebrew tap

outl ships pre-built binaries through the same avelino/outl repo — no separate homebrew-outl repo. Two surfaces live on main:

PathWhat it ships
/Formula/outl.rbGA CLI / TUI, semver tag vX.Y.Z.
/Formula/outl@beta.rbBeta CLI / TUI, rebuilt on every push to main.
/Casks/outl-desktop@beta.rbBeta desktop app (.dmg), rebuilt on every push to main.

Install the CLI / TUI

brew tap avelino/outl https://github.com/avelino/outl
brew install outl@beta     # beta channel — every push to main
# brew install outl        # GA channel — semver tags only

The custom-URL form (brew tap <name> <url>) tells Homebrew to use this repo as the tap directly, without the usual homebrew-<name> naming convention.

outl and outl@beta install the same outl binary and conflict by design. Switching channels:

brew unlink outl@beta && brew install outl       # to GA
brew unlink outl  && brew install outl@beta      # to beta

Install the desktop app

brew tap avelino/outl https://github.com/avelino/outl   # same tap as the CLI
brew install --cask outl-desktop@beta

That drops outl.app into /Applications via the universal dmg the release workflow builds on a single arm64 runner (--target universal-apple-darwinlipo merge of arm64 + x86_64 into one binary). Both Apple Silicon and Intel Macs install the same dmg. The cask sits in /Casks/outl-desktop@beta.rb and is bumped automatically alongside the CLI formula on every push to main.

The CLI formula (outl@beta) and the desktop cask coexist without conflicts — the formula installs /usr/local/bin/outl, the cask installs /Applications/outl.app. Both point at the same workspace on disk if you configure the same path; the op log (ops/ops-<actor>.jsonl) reconciles edits made from either surface.

First-launch Gatekeeper warning

The desktop dmg is unsigned today. On the first launch macOS Gatekeeper refuses the app with:

“outl.app” Not Opened Apple could not verify “outl.app” is free of malware that may harm your Mac or compromise your privacy.

macOS Sequoia (15) tightened Gatekeeper — the old “right-click → Open” shortcut no longer dismisses the warning by itself. Two ways through that actually work on current macOS:

Terminal (fastest):

xattr -dr com.apple.quarantine /Applications/outl.app

This drops the quarantine attribute that Gatekeeper checks against; subsequent launches work normally.

System Settings → Privacy & Security:

  1. Try to open outl.app once and dismiss the warning.
  2. Open System Settings → Privacy & Security.
  3. Scroll to the bottom — there’s an entry “outl.app was blocked from use because it is not from an identified developer”.
  4. Click Open Anyway, then confirm with Touch ID or your password.
  5. Try opening outl.app again — Gatekeeper now prompts for a final confirmation; click Open.

Signing + notarisation will land with the first GA release (the cask’s caveats block reminds the user of this on every install until then).

Updating

brew update
brew upgrade --cask outl-desktop@beta

The livecheck block in the cask points Homebrew at the GitHub releases feed, so brew outdated knows when a new beta dmg lands.

How updates happen

The release workflow (/.github/workflows/release.yml) has an update_tap job that runs after publish_release succeeds on a prerelease. It does four things:

  1. Checks out main.
  2. Downloads every .sha256 sidecar from the GitHub release (CLI tarballs and desktop dmgs).
  3. Uses sed to bump the version + sha lines in both files in place:
    • Formula/outl@beta.rbversion plus three sha256 lines tagged # anchor: macos-arm64, # anchor: macos-x64, # anchor: linux-x64.
    • Casks/outl-desktop@beta.rbversion plus one sha256 line tagged # anchor: macos (universal dmg, both architectures in the same file).
  4. Commits the bumped formula + cask back to main with [skip ci] in the message — that prevents the commit from re-triggering the release workflow itself.

The version comes from the prepare job, which reads workspace.package.version out of Cargo.toml and appends -beta.<run_number>. So the only source of truth for the base version is Cargo.toml; nothing is hardcoded in the formula.

Formula/outl@beta.rb and Casks/outl-desktop@beta.rb are both committed with bootstrap placeholders (version "0.0.0", zeroed SHAs). The first beta release after each lands bumps it to real values. Until then, brew install outl@beta and brew install --cask outl-desktop@beta both 404 on the download URL.

Formula/outl.rb and Casks/outl-desktop.rb (the GA channels) don’t exist yet. When the first non-prerelease tag (vX.Y.Z with no -beta) ships, bump them by hand the first time; after that we can add a GA-flavored update_tap job if it’s worth automating.

Authentication

The job uses the default GITHUB_TOKEN (with contents: write permission scoped to the job). No PAT, no extra secret to manage.

Troubleshooting

Tap update commits but brew install still pulls the old version — run brew update first; Homebrew caches tap state.

brew install outl@beta fails with SHA256 mismatch — the formula on main drifted from the release asset. Usually means someone re-uploaded an asset on the GitHub release. Re-trigger the failed release via workflow_dispatch and update_tap will re-render with the current SHAs.

A manual edit on Formula/*.rb got overwritten — by design. The job templates the whole file on every release. If you need to change the formula structure (add a platform, change the test, etc), edit the heredoc in release.yml. The next release picks it up.

Renaming the binary or adding a second binarybin.install "outl" in the heredoc only ships the outl executable. If/when outl grows additional binaries (e.g. outl-tui as a separate binary), update the heredoc accordingly.