v1.0.1

tng -- Tangled CLI

Work with Tangled, the decentralized Git collaboration platform, from your terminal.

Quick start
tng auth login --handle example.bsky.social
tng repo clone example.bsky.social/my-project
cd my-project
tng pr list
tng issue create --title "Bug report"

Installation

From source (Go)

Requires Go 1.26.5 or newer.

go install tangled.org/eric.wien/tng-cli/cmd/tng@latest

Build manually

git clone git@knot.eric.wien:eric.wien/tng-cli
cd tng-cli
make build
./bin/tng version

Makefile targets

TargetDescription
make buildBuild the binary to ./bin/tng
make testRun all tests
make lintRun golangci-lint
make installInstall to /usr/local/bin
make cleanRemove build artifacts

Authentication

tng authenticates using AT Protocol OAuth 2.0 with PKCE and DPoP. This is the same protocol used by Bluesky. Your handle can be from any AT Protocol provider.

# Opens browser for authorization
tng auth login --handle example.bsky.social

# Paste the localhost callback URL in a headless environment
tng auth login --manual --handle example.bsky.social

# Check current session
tng auth status

# Sign out (revokes tokens)
tng auth logout

The login flow:

  1. Resolves your handle to a DID and PDS endpoint
  2. Sends a Pushed Authorization Request (PAR) with PKCE challenge
  3. Opens your browser, or displays an authorization URL in a remote session
  4. Handles the OAuth callback on a local HTTP server or from a pasted callback URL
  5. Exchanges the code for DPoP-bound access tokens
  6. Stores the session locally at ~/.config/tng/

Over SSH, manual browser authentication is selected automatically. Open the displayed URL on your local machine, authorize the CLI, then copy the full localhost callback URL from the browser's address bar back into the terminal. Use --manual to select this flow in other headless environments.

Tokens are automatically refreshed. The public client flow gives sessions a lifetime of approximately two weeks.

tng auth

Manage authentication with your Tangled / AT Protocol account.

tng auth login

Authenticate via browser-based OAuth flow.

tng auth login
tng auth login --handle example.bsky.social
tng auth login --manual --handle example.bsky.social
tng auth login --handle did:plc:abc123
FlagDescription
--handleAT Protocol handle or DID. If omitted, prompted interactively.
--manualComplete login by pasting the localhost callback URL. Automatically enabled over SSH.

tng auth status

Show all authenticated accounts. The active account is marked with *.

tng auth logout

Revoke tokens and remove the session.

FlagDescription
--didDID of account to log out. Defaults to the active account.

tng repo

Create, clone, view, and list Tangled repositories. Alias: tng r

tng repo create <name>

Create a repository on a Tangled knot. New repositories publish their knot-issued repository DID, so they are indexed by the Tangled appview. Pass --knot or configure default_knot.

tng repo create my-project --knot knot1.tangled.sh
tng repo create my-project -d "Project description" --knot knot1.tangled.sh
tng repo create my-project --knot https://knot.eric.wien
tng repo create my-project --default-branch main --clone --knot knot1.tangled.sh
FlagDescription
-d, --descriptionRepository description
--default-branchDefault branch name (default: main)
-k, --knotKnot URL to create the repo on (e.g., https://knot.eric.wien). Falls back to default_knot in config.
-c, --cloneClone the repository after creation

tng repo clone <owner/repo> [directory]

Clone a Tangled repository via SSH.

tng repo clone example.bsky.social/my-project
tng repo clone example.bsky.social/my-project ./my-dir

tng repo view [owner/repo]

Display repository details: file tree, last commit, and README. Uses the current repo if no argument is given.

FlagDescription
-w, --webOpen in browser instead of printing

tng repo list [owner]

List repositories for a user. Defaults to the authenticated user. Alias: tng repo ls

FlagDescription
-L, --limitMaximum number of results (default: 30)

tng pr

Create, view, merge, and manage pull requests.

Tangled uses a round-based review model. Each push to a PR creates a new immutable round. Reviewers can view interdiffs between rounds.

tng pr create

tng pr create --title "Add feature" --body "Description"
tng pr create -t "Fix bug" --base main --head fix-branch
FlagDescription
-t, --titlePR title (required)
-B, --bodyPR description
-b, --baseTarget branch (default: main)
-H, --headSource branch (default: current branch)

tng pr list

tng pr list
tng pr list --repo example.bsky.social/my-project
tng pr list --web
FlagDescription
-R, --repoFilter by repository (owner/name)
-w, --webPrint the tangled.sh pull requests URL

tng pr view <rkey>

Display PR details including title, branches, and body.

FlagDescription
--authorDID of the PR author (defaults to you)
-w, --webOpen in browser

tng pr diff <rkey>

Print the raw diff of a pull request to stdout.

tng pr merge <rkey>

Merge a pull request. The PR must be in open status.

tng pr close <rkey>

Close a pull request without merging.

tng pr comment <rkey>

Add a comment to a pull request.

FlagDescription
-b, --bodyComment text (required)

tng issue

Create, view, and manage issues. Alias: tng i

tng issue create

tng issue create --title "Bug: login fails" --body "Steps to reproduce..."
tng issue create -t "Feature request"
FlagDescription
-t, --titleIssue title (required)
-b, --bodyIssue body
-R, --repoRepository override

tng issue list

tng issue list
tng issue list --repo example.bsky.social/my-project
tng issue list --web
FlagDescription
-R, --repoFilter by repository (owner/name)
-w, --webPrint the tangled.sh issues URL

tng issue view <rkey>

FlagDescription
--authorDID of the issue author (defaults to you)
-w, --webOpen in browser

tng issue close <rkey>

Close an issue.

tng issue comment <rkey>

FlagDescription
-b, --bodyComment text (required)

tng browse

Open the current repository (or a specific file) in your web browser.

tng browse                            # Open repo root
tng browse src/main.go                # Open specific file
tng browse -n                         # Print URL, don't open
tng browse -R example.bsky.social/proj  # Specify repo
FlagDescription
-R, --repoRepository override
-n, --no-browserPrint the URL instead of opening it

Utilities

tng upgrade

Upgrade to the latest released version via the Go module proxy and go install (requires a Go toolchain). Alias: tng update

FlagDescription
--checkOnly check for a newer version, don't install

tng version

Print the version, build date, and commit hash.

tng completion <shell>

Generate shell completion scripts. Supported: bash, zsh, fish, powershell.

Configuration

Config is stored at ~/.config/tng/config.yml (respects XDG_CONFIG_HOME and TNG_CONFIG_DIR).

default_knot: ""     # Default knot for repo creation
api_host: ""         # Override API host (default: https://tangled.sh)

Environment Variables

VariableDescription
TNG_HOSTOverride API host (default: https://tangled.sh)
TNG_CONFIG_DIROverride config directory
TNG_REPOOverride repo context (owner/name)
TNG_FORCE_TTYForce color output in non-TTY contexts
NO_COLORDisable all color output

Repository Context

Inside a cloned Tangled repository, tng automatically detects the repo from git remotes. Resolution priority:

  1. TNG_REPO environment variable
  2. git config tng.default-repo
  3. Git remotes matching tangled.sh (priority: upstream > tangled > origin)

Supported remote formats:

git@tangled.sh:owner/repo
https://tangled.sh/owner/repo

Shell Completions

# Bash
tng completion bash > /etc/bash_completion.d/tng

# Zsh (add to fpath)
tng completion zsh > "${fpath[1]}/_tng"

# Fish
tng completion fish > ~/.config/fish/completions/tng.fish

Architecture

tng follows the same patterns as the GitHub CLI:

Key differences from GitHub CLI

Aspectgh (GitHub)tng (Tangled)
AuthGitHub OAuth device flowAT Protocol OAuth 2.0 with PKCE + DPoP
IdentityGitHub usernameAT Protocol DID + handle
APIREST + GraphQLXRPC (AT Protocol RPC)
PRsMutable, linearRound-based, immutable per round, interdiffs
DataCentralized on GitHubAT Protocol records on user's PDS
HostingMonolithic serviceKnots (federated git servers)

Project Structure

cmd/tng/              Entry point
internal/
  tngcmd/             Root command assembly, exit codes
  authflow/           AT Protocol OAuth flow
  config/             Config files and session storage
  build/              Version info (set via ldflags)
pkg/
  cmd/                Command implementations
    auth/             login, logout, status
    repo/             create, clone, view, list
    pr/               create, list, view, diff, merge, close, comment
    issue/            create, list, view, close, comment
    browse/           Open in browser
    version/          Print version
    completion/       Shell completions
  cmdutil/            Factory, errors, arg helpers
  iostreams/          TTY detection, color, terminal width
api/                  XRPC API client and domain methods
context/              Git remote resolution
git/                  Git CLI wrapper, remote parsing

tng-cli is open source. Source code at tangled.org/eric.wien/tng-cli.