entangle
entangle is a small CLI that wires up your git remotes so a single git push sends your code to both GitHub and Tangled simultaneously.
entangle setup # configure your usernames once
entangle init # wire up remotes in this repository
entangle shove # first-time push to both forges
Scope note: entangle currently supports GitHub ↔ Tangled mirroring only. Issues and PRs expanding it to other forges or mirroring workflows are very welcome.
Installation
The package is named entangle-mirror on crates.io (the name entangle was already taken); the installed binary is called entangle.
Or install directly from source:
Or build manually:
# binary is at target/release/entangle
Requirements: Rust 1.85+ (edition 2024), an SSH key configured for both GitHub and Tangled.
Quick start
1. Configure your usernames
Interactive prompts for your GitHub username, your Tangled handle (e.g. yourname.bsky.social), and which forge you want as the primary fetch remote. These are stored once in your platform config directory and reused for every repository.
You can also set individual values non-interactively:
2. Wire up a repository
Run from inside an existing local repository (or an empty directory — entangle init will run git init for you):
entangle will prompt for a repository name and configure origin with push URLs for both forges. If your repo has a different name on each forge, pass both:
Run entangle init --help for the full argument reference.
3. Push to both forges at once
After your first commit:
This runs git push origin --all && git push origin --tags. Because origin has two push URLs configured, both forges receive every branch and tag in one command.
For day-to-day work, git push continues to work exactly as before — entangle does not change your workflow after init.
Commands
| Command | Description |
|---|---|
entangle setup |
Interactive configuration of usernames and origin preference |
entangle set <key> <value> |
Set a single config field non-interactively |
entangle init [repo] [alias] |
Wire up push remotes in the current repository |
entangle shove |
Push all branches and tags to both forges |
Run entangle <command> --help for full per-command usage.
entangle set keys
| Key | Aliases | Values |
|---|---|---|
gh-user |
github-user |
Your GitHub username |
tngl-user |
tangled-user |
Your Tangled ATProto handle |
origin |
— | github / gh or tangled / tngl |
Repository name rules
entangle enforces the most restrictive common ground of GitHub and Tangled naming rules. A handful of repository names that are technically valid on GitHub will be rejected because they cannot be created on Tangled.
Specifically, repository names must:
- Be 1–100 characters long
- Contain only lowercase alphanumeric characters and hyphens
- Not start or end with a hyphen
- Not contain consecutive hyphens (
--)
Notable differences from GitHub's rules:
- Periods are not allowed. GitHub permits
my.project; entangle does not. Usemy-projectinstead. - Underscores are not allowed. GitHub permits
my_project; entangle does not. Usemy-projectinstead. - Uppercase is normalized to lowercase before validation, so
MyRepois accepted and stored asmyrepo.
If your existing repository uses a name that doesn't pass these rules, use the alias argument to entangle init to give it a different name on the mirror forge:
Configuration
Config is stored in your platform config directory:
| Platform | Path |
|---|---|
| Linux / BSD | ~/.config/entangle/config.json |
| macOS | ~/Library/Application Support/entangle/config.json |
| Windows | %APPDATA%\entangle\config.json |
You can override the path for scripting or testing with the ENTANGLE_CONFIG_PATH environment variable.
Known limitations
SSH URL format only. entangle constructs git@host:user/repo SSH URLs and assumes the default SSH port (22) and the standard git user. Users with non-standard SSH configurations (custom ports, Host aliases in ~/.ssh/config) will need to edit the generated remote URLs manually after running entangle init.
SSH error messages are matched in English. When entangle init checks whether a remote is reachable, it classifies failures by inspecting the text output of the ssh subprocess. If your system's SSH binary has been localized, an authentication failure may be reported as a generic connectivity problem ("couldn't reach remote") rather than the more specific "SSH key not set up" message. The behaviour in that case is still safe — entangle will prompt you to accept the override — but the error description may be less helpful.
License
MIT — see LICENSE.