Something went wrong. Try again.
An unofficial terminal client for Tangled, optimized for humans and agents. tgcli.wisp.place
cli atproto go tangled
Something went wrong. Try again.
tg AGENTS.md
3.4 kB · 37 lines
Markdown
AGENTS.md #
tg is a Go 1.26+ CLI for Tangled (git forge on atproto), built with Cobra + Viper. Entry point: cmd/tg/main.go.
Verify changes (in order) #
nix fmt— treefmt wrapper (gofmt, prettier, alejandra, shfmt/shellcheck, statix, deadnix). Without Nix, run those formatters directly.nix build— the real gate: compiles, runsgo test ./..., and generates man pages + shell completions.go buildpassing is not enough.- Quick iteration only:
go build ./cmd/tg,go test ./....
Nix gotchas #
- Changing
go.mod/go.suminvalidatesvendorHashinnix/tg.nix.nix buildfails with a hash mismatch; copy thegot:hash intovendorHashand rebuild. Don't commit dependency changes until the build passes with the updated hash. - Man pages are generated at build time by the hidden
tg mancommand (invoked fromnix/tg.nix). - Docs are the Astro site in
website/: hand-written pages inwebsite/src/content/docs/(thereference/commands/pages are generated and gitignored, produced from help text bywebsite/scripts/gen-commands.mjs, which needstgbuilt first). Build withcd website && bun install && bun run build.
CI #
Tangled pipelines in .tangled/workflows/ (nixery engine), not GitHub Actions: nix build .#tg, go test ./..., and the website build (.tangled/workflows/website.yml). Default branch is master.
Architecture #
internal/app/— frontend-independent application layer.app.Servicebundles the resolver, appview, and auth dependencies and exposes every operation (target resolution, issue/PR/repo/string/SSH-key CRUD, auth flows) as methods returning typed domain structs. All application logic lives here.internal/cli/— thin Cobra frontend overinternal/app: one file per command, all built inNewRoot. EachRunEparses flags/args into a service call and renders the returned struct.tangled/— read-only client for the Bobbin appview XRPC API (defaulthttps://bobbin.klbr.net; override via--appview/TG_APPVIEW).- Writes go two ways: PDS record mutations with the user's session (
atproto/), and knot server RPCs (knot/) authed with a PDS-minted service-auth JWT. Both are orchestrated byinternal/app. atproto/— handle↔DID resolution, PDS discovery, OAuth + app-password sessions stored in the OS keyring.internal/gitutil/— git subprocesses (clone, fetch, patch apply); its tests needgitin PATH.
Conventions #
- New command: add the service method to
internal/app/, then a thin file ininternal/cli/that parses flags and calls it, registered withAddCommandinNewRoot. - Commands returning data must support
--jsonviaoutput(cmd, data, human)ininternal/cli/output.go. The JSON structs are the canonical domain types ininternal/app/types.go. - Repo-targeting commands accept
handle/repoor auto-detect from theoriginremote (seeinternal/app/target.goand theresolveTarget/resolveTargetFlagshims ininternal/cli/target.go). - Config is Viper: flag >
TG_env var >$XDG_CONFIG_HOME/tg/config.toml> default. - Tests are plain unit tests with table-driven style; keyring tests use an in-memory fake, no real keyring needed. Tests for application logic live in
internal/app/. - Commit messages: lowercase
<area>: <change>, area = package/command path (e.g.app:,cli:,atproto/auth:,nix/tg:,gitutil:).