# gtg A [Gleam](https://gleam.run) CLI client for [Tangled](https://tangled.org), the git forge built on AT Protocol. `gtg` is a Gleam reimplementation of [`aly.codes/tg`](https://tangled.org/aly.codes/tg) (the Go `tg` tool — an analogue of GitHub’s `gh`). ## Features - **Auth** — OAuth (browser + localhost callback + DPoP) or app-password login; multi-account store - **Repos** — list, view, clone, create, delete, edit, set-default-branch - **Issues** — list, view, create, comment, close, reopen - **Pull requests** — list, view, create (patch upload), comment, diff, checkout, close, reopen, merge - **Strings** — list, view, create, delete - **SSH keys** — list, add, delete - **API** — call authenticated XRPC endpoints - **Browse** — open a repo on tangled.org Reads go through the Bobbin appview (default `https://bobbin.klbr.net`). Writes use your PDS session and knot service-auth JWTs. ## Build / develop ### With Nix (recommended) ```bash nix develop # or: direnv allow (uses .envrc → use flake) gleam run -- --help gleam test ``` One-shot without entering the shell: ```bash nix run . -- --help nix run . -- repo list aly.codes ``` ### Without Nix Requires Erlang/OTP and Gleam on `PATH`: ```bash gleam build gleam run -- --help gleam run -- auth status ``` ## Quick start ```bash # Log in with OAuth (opens browser; callback on 127.0.0.1:8095) gtg auth login alice.example.com # Or headless with an atproto app password gtg auth login alice.example.com xxxx-xxxx-xxxx-xxxx # Clone a repository (SSH) gtg repo clone aly.codes/tg # List issues / PRs (detects origin remote in a Tangled clone) gtg issue list gtg pr list # Create an issue gtg issue create --body "Details" "Bug report" -R handle/repo ``` ## Configuration Precedence (highest first): flags → `TG_*` env → config file → defaults. | Source | Keys | |--------|------| | Flags | `--appview`, `--account`, `--config`, `--json` | | Env | `TG_APPVIEW`, `TG_ACCOUNT` | | File | `$XDG_CONFIG_HOME/gtg/config.toml` (also reads `tg/config.toml`) | ```toml # ~/.config/gtg/config.toml appview = "https://bobbin.klbr.net" ``` Sessions are stored under `$XDG_DATA_HOME/gtg/` (not the OS keyring — unlike Go `tg`). ## Architecture ``` src/gtg.gleam entrypoint src/gtg/cli.gleam command tree src/gtg/config.gleam flags / env / toml src/gtg/app/ domain service (repos, issues, PRs, …) src/gtg/atproto/ resolve, XRPC, OAuth+DPoP, password auth, PDS, sessions src/gtg/tangled/ Bobbin appview client src/gtg/knot/ knot RPCs src/gtg/gitutil.gleam git clone / remotes / patches ``` ## Differences from Go `tg` | | `tg` (Go) | `gtg` (Gleam) | |--|-----------|---------------| | Auth | OAuth + app password, OS keyring | OAuth (DPoP) + app password, file store | | Binary name | `tg` | `gtg` | | Config dir | `~/.config/tg` | `~/.config/gtg` (falls back to reading `tg`) | | Completions / man | generated | not yet | ## License MIT (this port). Upstream `tg` has its own license — see [aly.codes/tg](https://tangled.org/aly.codes/tg).