# 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.
