# Gotcha Gotcha is a lightweight Gitea client with a reusable Rust core, a CLI, and a native iOS application. The iOS interface is UIKit/Swift; UniFFI exposes the Rust application logic to Swift. ## Workspace - `gotcha_gitea`: reusable asynchronous Gitea API client with the complete typed Gitea 1.25 API and model surface - `gotcha`: CLI for typed common operations and arbitrary API requests - `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 Store each server profile in `~/.config/gotcha/config`: ```sh cargo run -p gotcha-cli -- auth login gitea.example.com 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 -- 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 and reads the token from standard input with echo disabled. 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 ``` 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. ## Architecture The Rust core owns Gitea access, validation, presentation records, preferences, favorites, and Keychain-backed credentials. UniFFI generates the Swift bridge in `ios/Generated`. UIKit owns navigation, lists, text input, menus, scrolling, pull-to-refresh, appearance, and other platform behavior. New API workflows should first be exercised and typed in the CLI, then exposed through the Rust core and presented with native UIKit controls. Future work includes write workflows and iOS integrations such as sharing, notifications, and background refresh. ## iOS app 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.