A cross-platform desktop app for managing Git profiles. Switch your Git identity, SSH config, and connected accounts in one click.
Built with Tauri v2 (Rust) + React + TypeScript + Tailwind CSS.
- Profiles — Create, edit, and delete named accounts. Each profile can link GitHub, GitLab, or both.
- One-click activation — Activating a profile updates global
git config user.nameanduser.email, and rewrites~/.ssh/configso SSH to github.com / gitlab.com uses that profile's key. - Default platform — If both GitHub and GitLab are connected, choose which account supplies the active git identity (name/email).
- OAuth sign-in — GitHub via device code flow; GitLab.com via browser authorization and PKCE (local callback). OAuth app Client / Application IDs are configurable in Settings (with built-in defaults).
- SSH keys — Generate Ed25519 keys with
ssh-keygen, attach an existing key from~/.ssh, upload keys to GitHub/GitLab, and optionally remove keys from the host when deleting a profile. - System tray — Closing the window hides the app; restore or quit from the tray menu.
- Settings — OAuth credentials, launch at login (autostart), and light / dark / system theme.
Download the latest release for your OS from the Releases page.
- Windows
- Download the .msi installer
- Run the installer and follow the on-screen instructions
- macOS
- Download the .dmg file
- Open the .dmg file
- Drag the app to your Applications folder
- Linux
- Download the .AppImage file
- Make it executable: chmod +x GitAccountManager.AppImage
- Run it: ./GitAccountManager.AppImage
- Tokens are stored in plain text in the JSON file
- This is a simple tool for personal use
- For enhanced security, consider:
- Using SSH keys instead of HTTPS/PAT
- Encrypting the storage file
- Using a credential manager
Download from nodejs.org or install via winget:
winget install OpenJS.NodeJS.LTSnpm install -g pnpmWindows:
winget install Rustlang.Rustup --source wingetOr download the installer from rustup.rs.
After install, make sure cargo is in your PATH. You may need to restart your terminal. Verify:
rustc --version
cargo --versionIf cargo is not found after install, add it to PATH manually:
$env:Path = "$env:USERPROFILE\.cargo\bin;" + $env:PathmacOS:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | shLinux (Debian/Ubuntu):
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
sudo apt install libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelfGit must be installed and available in PATH (needed for git config and ssh-keygen).
git --version
ssh-keygen -Vpnpm installDevelopment
| Target | Command | Notes |
|---|---|---|
| Web (browser only, faster UI work; Tauri APIs unavailable) | pnpm dev:web |
Vite on http://localhost:1420 |
| Desktop (full Tauri shell) | pnpm dev:desktop |
Same as pnpm tauri dev; starts the Vite dev server automatically |
| Target | Command | Output |
|---|---|---|
| Web | pnpm build:web |
Static files in dist/ |
| Desktop | pnpm build:desktop |
Same as pnpm tauri build; runs build:web first, then Rust bundle |
Installers are generated under src-tauri/target/release/bundle/.
Pushing a version tag triggers the Build & Release workflow: it builds installers for Windows, Linux, and macOS, then attaches them to a GitHub Release.
- Bump the version consistently in
package.json,src-tauri/tauri.conf.json, andsrc-tauri/Cargo.toml. - Commit and push those changes to
main(or your default branch). - Create a tag whose name starts with
v(the workflow only publishes onrefs/tags/v*):
git tag v0.1.0 # same version as in tauri/package
git push origin v0.1.0Pushes to main or pull requests still run the build jobs, but the release job runs only on a tag push like the above. If you run the workflow manually from the Actions tab, the release step is skipped for the same reason (the ref is a branch, not a tag).
Preview production web build
pnpm preview:webThis is returned when GitHub responds with an error to the device authorization request (POST https://github.com/login/device/code). The app shows the response body from GitHub; Not Found usually means GitHub does not accept the Client ID or the app is not set up for this flow.
Typical causes and what to try
| Situation | What to check / fix |
|---|---|
| Wrong or unknown Client ID | The ID in Settings → GitHub OAuth must match an existing OAuth App under your account (or org). Typos, extra spaces, or an app that was deleted produce this kind of error. Create a new OAuth App or restore the correct Client ID. |
| OAuth App not created yet | Complete New OAuth App in GitHub Developer Settings before pasting the Client ID. |
| Device flow disabled | In the OAuth App settings on GitHub, enable Device flow (required for "Connect with GitHub"). Without it, authorization for this desktop flow may fail. |
| Wrong app type | Use a GitHub OAuth App, not a GitHub App—their credentials and flows differ. |
After changing settings on GitHub, save the app, copy the Client ID again into this application, and retry Connect with GitHub.
GitLab (browser): Client authentication failed due to unknown client, no client authentication included, or unsupported authentication method.
This appears on GitLab’s website (URL like gitlab.com/oauth/authorize?...) immediately after you click Connect with GitLab, when the browser opens the authorization page. GitLab rejects the OAuth application before you can approve access.
Typical causes and what to try
| Situation | What to check / fix |
|---|---|
| Wrong or unknown Application ID | The value in Settings → GitLab OAuth must be the Application ID from your GitLab application on GitLab.com. Typos, extra spaces, a deleted application, or an ID from another GitLab instance will trigger unknown client. Create a new application or copy the ID again from the correct app. |
| Application not created yet | Finish Add new application on GitLab before pasting the Application ID (see in-app steps for redirect URI and scopes). |
| Confidential / auth method | This app uses a public client with PKCE (no client secret). On GitLab, leave Confidential unchecked when creating the application. A confidential app can lead to unsupported authentication method (or related failures) during token exchange because the flow does not send a client secret. |
| Redirect URI or scopes | Set Redirect URI to http://localhost:19847/callback and enable the api scope, as shown in Settings. A mismatch can cause other OAuth errors; fix the application on GitLab to match. |
After fixing the application on GitLab, click Save Settings in this app, then try Connect with GitLab again.
After you click Connect with GitLab, the browser completes authorization and the app exchanges the authorization code for an access token by POSTing to https://gitlab.com/oauth/token. That message is returned when the HTTP client cannot complete the request (no response was received). It is a transport failure, not a wrong Client ID or redirect URI (those usually produce a different error after GitLab responds).
Typical causes and what to try
| Situation | What to check / fix |
|---|---|
| No route to the internet | Confirm the machine can open https://gitlab.com in a browser and that nothing is forcing offline mode. |
| DNS | Ensure gitlab.com resolves (nslookup gitlab.com or ping). Corporate DNS or a broken hosts file can block the name. |
| Firewall / proxy | Allow outbound HTTPS to gitlab.com (port 443). If you must use an HTTP(S) proxy, the app’s Rust reqwest stack must see proxy settings (system env vars such as HTTPS_PROXY are often required for CLI/desktop tools on Windows). |
| TLS / certificates | HTTPS inspection (corporate proxy, antivirus) can break TLS if a custom root is not trusted by the TLS stack the app uses (rustls + Mozilla root store in this project). Try without inspection, or install/trust the corporate root as required by your IT policy. |
| VPN or split tunneling | Some VPNs block or misroute gitlab.com; disconnect or adjust split tunneling and retry. |
| GitLab availability | Rare, but check GitLab status if everything else works in the browser. |
Quick checks
- In a terminal on the same PC:
curl -I https://gitlab.com/oauth/token(or open the URL in a browser; you may get a method-not-allowed response—that still proves reachability). - Temporarily disable VPN / third-party firewall / HTTPS-scanning antivirus to see if the error disappears (then re-enable and narrow the exception).
Note: OAuth in this app targets GitLab.com (gitlab.com). Self-managed GitLab instances use different hostnames and are not covered by the built-in URLs.
- Authentication options: support SSH keys and personal access tokens.
- Clipboard: copy SSH public keys to the clipboard from the app.
- Per-account keys: view and manage SSH keys for each saved account.
- Bitbucket: connect Bitbucket.org from a profile, alongside GitHub and GitLab.
Contributions are welcome! Here's how you can contribute:
- Fork the repository.
- Create a new branch:
git checkout -b feature-branch-name. - Make your changes and commit them:
git commit -m 'Add some feature'. - Push to the branch:
git push origin feature-branch-name. - Submit a pull request.
This project is licensed under the MIT License. See the LICENSE file for details.


