Skip to content

Repository files navigation

Gantry (Vibecoded AI slop - but hey, it works!)

A terminal UI and CLI tool for Codemagic CI/CD, built with ratatui.

Gantry is an unofficial client for Codemagic. It is not affiliated with, endorsed by, or sponsored by Codemagic / Nevercode Ltd. "Codemagic" is used only to describe what this tool talks to.


Workspace layout

This repository is a Cargo workspace with three crates:

CrateWhat it is
core/gantry-core — the shared API client, data models, and config. No UI dependencies, so it compiles for desktop and mobile.
cli/gantry-cli — the terminal UI + CLI (this document).
app/gantry — a cross-platform Dioxus GUI (desktop + iOS/Android). See app/README.md.

Build everything with cargo build; build just the terminal client with cargo build -p gantry-cli.


Features

Interactive TUIBrowse all builds, filter by workflow and status, live-refresh running builds
Build actionsDownload artifacts, convert AAB → APK, stream logs
Remote accessSSH / VNC credentials for a running build machine
New-build wizardPick app → workflow → branch and trigger a build
CLI modedownload apk and remote-access subcommands for scripting and CI pipelines
ClipboardCopy app / workflow IDs with one keypress

Gantry — Builds list


Installation

macOS & Linux — one-liner

Paste this in your terminal. The script auto-detects your OS and CPU architecture (x86-64 or arm64), downloads the matching binary from the latest GitHub release, verifies the SHA-256 checksum, and installs to /usr/local/bin.

curl -fsSL https://raw.githubusercontent.com/cascalheira/codemagic-cli/main/install.sh | sh

Options — set environment variables before the pipe:

# Install a specific version
VERSION=v1.3.0 curl -fsSL https://raw.githubusercontent.com/cascalheira/codemagic-cli/main/install.sh | sh
# Install to a custom directory (no sudo needed if you own it)
INSTALL_DIR=~/.local/bin curl -fsSL https://raw.githubusercontent.com/cascalheira/codemagic-cli/main/install.sh | sh

Windows — PowerShell

Open PowerShell and run:

irm https://raw.githubusercontent.com/cascalheira/codemagic-cli/main/install.ps1 | iex

The script detects your CPU architecture (x86-64 or arm64), downloads the matching .zip from the latest GitHub release, verifies the SHA-256 checksum, extracts the binary to %LOCALAPPDATA%\gantry, and adds that directory to your user PATH automatically.

Options — set environment variables before the pipe:

# Install a specific version$env:VERSION="v1.3.0"; irm https://raw.githubusercontent.com/cascalheira/codemagic-cli/main/install.ps1 | iex
# Install to a custom directory$env:INSTALL_DIR="C:\Tools"; irm https://raw.githubusercontent.com/cascalheira/codemagic-cli/main/install.ps1 | iex

Execution-policy note: if you see a security error, run Set-ExecutionPolicy -Scope CurrentUser RemoteSigned once, then retry.


Manual download

Pre-built binaries for every platform are attached to every GitHub release:

FilePlatform
gantry-cli-macos-aarch64.tar.gzmacOS Apple Silicon
gantry-cli-macos-x86_64.tar.gzmacOS Intel
gantry-cli-linux-x86_64.tar.gzLinux x86-64
gantry-cli-linux-aarch64.tar.gzLinux arm64
gantry-cli-windows-x86_64.zipWindows x86-64
gantry-cli-windows-aarch64.zipWindows arm64

Each asset is accompanied by a .sha256 checksum file.


Build from source

Prerequisites:Rust 1.85+ (rustup update stable)

git clone https://github.com/cascalheira/codemagic-cli.git
cd codemagic-cli
cargo build --release
# binary → target/release/gantry-cli

Copy the binary somewhere on your $PATH:

cp target/release/gantry-cli /usr/local/bin/

Quick start

1. Get your API token

In the Codemagic web UI: Settings → Integrations → Codemagic API → Show

2. First launch

gantry-cli

On first run the onboarding screen appears and asks for your API token.
The token is validated against the API and saved to ~/.config/gantry/config.toml.

Subsequent launches jump straight to the builds list.


TUI — key bindings

Builds list

KeyAction
/ kMove selection up
/ jMove selection down
EnterOpen the Build Actions sheet for the selected build
nOpen the New Build wizard
fOpen the Workflow filter popup
lLoad more builds (next page)
rRefresh (reload from the top)
iOpen the App & Workflow IDs browser
sOpen Settings (change API token)
q / EscQuit
Ctrl-C / Ctrl-DForce quit

Running builds show an animated braille spinner and a ● N live badge in the status bar. Their status is automatically refreshed every 5 seconds.


Build Actions sheet (Enter on any build row)

The sheet shows build details (status, app, workflow, branch, duration, commit) inline at the top, followed by the action list:

KeyAction
/ / j / kNavigate actions
EnterConfirm selected action
EscClose

Available actions:

Download Artifacts

Shows a table of all artefacts (name, type, size) for the selected build.
Selecting one and pressing Enter downloads it directly to:

~/Gantry/{App Name}/{Workflow Name}/{Build Number}/{filename}

An .aab file is always accompanied by a Convert → APK row at the bottom of the list (only shown when an AAB is present). Selecting it runs the bundletool conversion and saves the result at the same path as the other artefacts.

KeyAction
/ Navigate
EnterDownload / convert
EscBack to Build Actions

View Build Logs

Shows the list of build steps with their status icons (✓ ✗ ● ○).
Pressing Enter on a step fetches and displays the full plain-text log for that step.

KeyAction
/ Navigate steps
EnterOpen log for selected step
EscBack to Build Actions

Inside the Log Viewer:

KeyAction
/ / j / kScroll one line
PgUp / PgDnScroll 20 lines
EscBack to step list

Remote Access

Only offered while a build is running. Fetches the SSH script URL and the VNC host / port / username / password for the machine the build is executing on.

KeyAction
/ Navigate fields
EnterCopy the selected field to the clipboard
vOpen the VNC session in the system's default handler
rRetry the request
EscBack to Build Actions

Remote access has to be enabled for the workflow before the build starts, and the credentials only exist while the build is running. Otherwise Codemagic answers "Remote access is not enabled for this build", which is shown as-is.


Filter popup (f)

Two columns: Workflow and Status.

KeyAction
/ Navigate the focused column
Tab / / Switch column
EnterApply both filters and reload builds
EscCancel

Both active filters are shown in the filter bar. All Workflows and Any status clear their respective filter.

Filtering happens server-side, so a status filter searches your whole build history rather than only the builds already loaded. The status column needs the v3 API (see Architecture) and is hidden when it is unavailable.


New Build wizard (n)

Three-step process:

Step 1 — Select App

KeyAction
/ Navigate
EnterNext step
EscCancel

Step 2 — Select Workflow

KeyAction
/ Navigate workflows
EnterNext step
EscBack to app selection

An Enter workflow ID manually… option is always present at the bottom for codemagic.yaml-configured apps (which have no Workflow Editor entries). When selected, a text input appears for the workflow ID.

Step 3 — Select Branch

KeyAction
/ Navigate the filtered branch list
typeFilter branches (case-insensitive substring)
BackspaceDelete last filter character
EnterStart build with the highlighted branch (or type a new branch name)
EscBack to workflow selection

On success the TUI shows ✓ Build queued (id: …) and reloads the list so the new build appears immediately.


App & Workflow IDs browser (i)

Useful when you need IDs for the CLI, CI scripts, or the new-build wizard.

My Flutter App
App ID 5c9c064185dd2310123b8e96
Workflows
• Android Workflow 5d85f242e941e00019e81bd2
• iOS Release 6e96g353f052f11120f92ce3
──────────────────────────────────────────────────────────────
Another App
App ID 6a1b234567890abcdef12345
Workflows (none — uses codemagic.yaml)
KeyAction
/ / j / kMove between selectable IDs
Enter or yCopy the highlighted ID to the system clipboard
PgUp / PgDnScroll content
Esc / qClose

Clipboard access uses arboard. On headless Linux you may need xclip or xsel.


Settings (s)

Change or rotate the stored API token.

KeyAction
type / BackspaceEdit token
EnterValidate and save
EscCancel without saving

The new token is validated with a live API call before being saved. The builds list reloads automatically on success.


CLI mode

Non-interactive operations for scripts and CI pipelines.

download apk

Finds the latest finished build for a workflow that contains an AAB artefact, converts it to a universal APK with bundletool, and saves it locally.

gantry-cli download apk \
--app-id 5c9c064185dd2310123b8e96 \
--workflow-id release

Example output:

Fetching app info…
App: My Flutter App · Workflow: Release Workflow
Searching for the latest build with an AAB artefact…
Searched 20 builds so far, looking further back…
Found AAB in build #37: app-release.aab
Generating download link…
Downloading AAB (32.1 MB)…
Converting AAB → APK (bundletool)…
Extracting universal APK…
✓ APK saved to /Users/you/Gantry/My Flutter App/Release Workflow/last/build.apk

Output path:

~/Gantry/{App Name}/{Workflow Name}/last/build.apk

last/ is always overwritten, giving you a stable path to the freshest APK.

Recursive search:
If the most recent build has no AAB (e.g. it failed, was cancelled, or only produced an IPA), the command walks backwards through older builds automatically until it finds one.

Getting IDs:
Press i in the TUI to open the App & Workflow IDs browser and copy the values you need.

bundletool auto-install

The command works without bundletool pre-installed:

  1. Checks for bundletool binary on PATH — uses it if found
  2. Checks for java on PATH — required for the JAR fallback
  3. Checks for a cached JAR at ~/.config/gantry/bundletool.jar
  4. Downloads the latest JAR from GitHub Releases and caches it (one-time download, ~80 MB)

The cached JAR is shared between the TUI and the CLI, so it is only downloaded once regardless of which mode first triggers it.

# Quick manual install if preferred:
brew install bundletool

remote-access

Prints the SSH script URL and VNC credentials for the machine a build is running on.

gantry-cli remote-access --build-id 6a61dd804f424ae5d8417923
SSH script : https://api.codemagic.io/remote-access/…/connect.sh
VNC URL : vnc://builder:s3cret@1.2.3.4:5900
VNC host : 1.2.3.4
VNC port : 5900
VNC user : builder
VNC pass : s3cret

Add --json for a machine-readable object to pipe into a VNC client or an ssh wrapper:

gantry-cli remote-access --build-id <id> --json | jq -r .vnc.url

Remote access has to be enabled for the workflow before the build starts, and the credentials only exist while the build is running. Otherwise the command exits non-zero with Codemagic's own explanation.


Artifact download path convention

All downloaded files follow the same directory structure:

~/Gantry/
{App Name}/
{Workflow Name}/
{Build Number}/ ← numbered builds from TUI
app-release.apk
app-release.aab
app-release.ipa
last/ ← always the latest, from CLI
build.apk

Characters illegal in directory names (/ \ : * ? " < > |) are replaced with _.


Configuration

FilePurpose
~/.config/gantry/config.tomlStored API token
~/.config/gantry/bundletool.jarCached bundletool JAR

config.toml format:

api_token = "your-token-here"

You can edit this file directly or use the Settings dialog (s) in the TUI.


Architecture

src/
main.rs Entry point: clap dispatch → TUI or CLI
cli.rs Non-interactive download commands
app.rs TUI application state machine (screens, popups, async messages)
ui.rs ratatui rendering (all screens and popups)
api.rs Codemagic v1 REST API client (reqwest)
api_v3.rs Codemagic v3 REST API client — filtered/cursor-paged build
listing and remote access; converts to the v1 build model
models.rs API response types (serde)
config.rs Config file read / write (toml)

Async design:

  • The terminal event loop runs on the tokio runtime
  • A dedicated std::thread reads crossterm events (blocking I/O) and forwards them via an mpsc channel — this prevents the tokio runtime from being blocked
  • API calls are spawned as tokio tasks; results arrive via a second mpsc channel
  • A 5-second interval ticker polls running builds to keep their status live

Two APIs:

Codemagic runs a v1 API (api.codemagic.io) and a newer v3 one (codemagic.io/api/v3), both authenticated with the same token. Gantry uses v3 for the build listing — it is the only one that filters by status server-side, pages by cursor, and exposes remote access — and v1 for everything else: build details, logs, artifact URLs, and starting builds.

v3 lists builds per team, so Gantry resolves the token's teams on startup and merges a page from each. If that call fails or the token sees no teams, the list falls back to the v1 endpoint and the status filter is hidden.


License

MIT

About

Vibecoded Codemagic CLI client.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages