# Gotcha Gotcha is a lightweight Gitea and Forgejo client with a reusable Rust core, a CLI, a Ratatui terminal interface, and a native iOS application. The iOS interface is UIKit/Swift; UniFFI exposes the Rust application logic to Swift. On the icon: git in a tea cup. it is obvious, isn't it? On the name: well, tea, we established that. there is something tea like called matcha. and this is git. so gotcha, because gitcha sounds dumb. Stop rolling your eyes. In general, this app is mainly meant for self-hosters who run their own small installation of gitea and want to pay attention to what their AI agents push to their projects. decentralisation is the game, so this is for that use case. this is not necessarily the app to use when you manage or frequent a large instance. ## Workspace - `gotcha_gitea`: reusable asynchronous Gitea/Forgejo API client with the complete typed Gitea 1.25-compatible API and model surface - `gotcha`: CLI for typed common operations and arbitrary API requests - `gotcha-tui`: paned, keyboard-and-mouse terminal application - `gotcha-app`: Rust application core and UniFFI API used by iOS - `ios`: native UIKit application for activity, repositories, favorites, issues, milestones, pull requests, commit history, changed files, and diffs; bundle identifier `de.rfc1437.gotcha` The generated API modules and models cover every Gitea 1.25 operation. The low-level request API remains available for newer instance-specific endpoints; purpose-built CLI and app views are added feature-by-feature. See [API_COVERAGE.md](API_COVERAGE.md) for the live contract inventory and the separate API-crate and CLI coverage status. ## CLI Build the workspace with `cargo build`; the CLI executable is written to `target/debug/gotcha`. To build only the CLI, use `cargo build -p gotcha-cli`. Create an optimized release build of the CLI with: ```sh cargo build --release -p gotcha-cli ``` The executable is written to `target/release/gotcha`. Store each server profile in `~/.config/gotcha/config`: ```sh cargo run -p gotcha-cli -- auth login gitea.example.com cargo run -p gotcha-cli -- auth login forgejo.example.com --provider forgejo cargo run -p gotcha-cli -- server version cargo run -p gotcha-cli -- user show cargo run -p gotcha-cli -- repo list cargo run -p gotcha-cli -- repo show cargo run -p gotcha-cli -- issue list cargo run -p gotcha-cli -- issue list --milestones "Version 1.0" --state open cargo run -p gotcha-cli -- issue show 7 cargo run -p gotcha-cli -- issue close 7 cargo run -p gotcha-cli -- milestone list cargo run -p gotcha-cli -- pull list cargo run -p gotcha-cli -- api request GET repos/owner/project/issues cargo run -p gotcha-cli -- api request POST user/repos '{"name":"demo"}' ``` `auth login` derives `https://gitea.example.com` from the server name, discovers Gitea or Forgejo, and reads the token from standard input with echo disabled. The optional provider requires the selected API when automatic discovery is not sufficient. The resulting plain YAML file at `~/.config/gotcha/config` has mode `0600` and one entry per server: ```yaml servers: gitea.example.com: url: https://gitea.example.com token: your-token provider: gitea forgejo.example.com: url: https://forgejo.example.com token: your-token provider: forgejo ``` Inside a Git repository, Gotcha matches its remotes to these server URLs and derives the `owner/repository` scope. Use `--server gitea.example.com` when selection is ambiguous, or `--url`/`GITEA_URL` for an unconfigured server. Tokens are never accepted as command-line arguments or environment variables. ## Terminal UI Build and run the standalone TUI with an existing CLI server profile: ```sh cargo run -p gotcha-tui cargo run -p gotcha-tui -- --server gitea.example.com ``` The five numbered panes mirror the iPhone app: Home, Issues, Repositories, pull requests, and Milestones. Use `j`/`k` or the arrow keys to select rows, Enter to open, Backspace to return, `/` for list filters, and `a`, `e`, `c`, `x`, and `d` for mutations. Use `n`/`p` for API result pages; scrolling the mouse wheel past a page boundary does the same. Repository lists support `*` favorites, commit lists support `b` branch switching, and Home supports `v` activity filters. Editors use Tab between fields and Ctrl-S to save. Mouse selection, double-click, and wheel scrolling work in ordinary terminals and Herdr. Overview panes refresh every five seconds by default. Press `,` to change the interval or set it to zero. Refresh waits while an editor or confirmation is open and after keyboard or mouse activity so it does not move the current selection during interaction. ## Architecture `gotcha_gitea` owns Gitea/Forgejo access, authentication, validation, mutations, relationships between server objects, and shared CLI/TUI server configuration. The CLI and TUI are terminal presentation layers that invoke shared client operations. `gotcha-app` owns application state, preferences, favorites, Keychain-backed credentials, and view-ready UniFFI records. UIKit owns native navigation, controls, layout, and other platform presentation behavior. New server workflows belong in `gotcha_gitea::Client` first, then receive CLI or app presentation as needed. Future work includes iOS integrations such as sharing, notifications, and background refresh. ## iOS app Prebuilt iPhone releases will be distributed through the [rfc1437 Apps AltStore PAL source](https://rfc1437.de/apps/). The source page explains how to add it to AltStore PAL and install available apps. Server tokens are kept in the Apple Keychain; JSON preferences contain only server metadata, settings, and favorites. The app requires Xcode, XcodeGen, an installed iOS Simulator runtime, and Rust's `aarch64-apple-ios` and `aarch64-apple-ios-sim` targets. Generate the project after installing those prerequisites: ```sh cd ios xcodegen generate open Gotcha.xcodeproj ``` For a fast host-side check, run `cargo test -p gotcha-app`. See [TESTING.md](TESTING.md) for the complete build, simulator, gesture, and release regression checklist.