# 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

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.
