DEV Community

Cover image for Managing Multiple GitHub Accounts with GitHub Codespaces Without Constant CLI Context Switching
Nirbhay Hiwse
Nirbhay Hiwse

Posted on

Managing Multiple GitHub Accounts with GitHub Codespaces Without Constant CLI Context Switching

Using one GitHub account is easy.

Using two is manageable.

Using three or four while working across different repositories, organizations, and Codespaces is where the workflow starts getting messy.

I know because I use GitHub for more than one context.

There is a personal side.

There are project-specific environments.

There can be organization or client access.

And once GitHub Codespaces enters the picture, authentication isn't the only thing you have to think about.

You also have to think about:

Account
Repository
Codespace
SSH host
CLI context
Remote workspace
Enter fullscreen mode Exit fullscreen mode

This post explains the problem, what GitHub supports today, and the architecture I used in Antigravity Codespaces Pro to make multiple-account Codespaces management less painful.


First: multiple GitHub accounts are supported

Let's get one misconception out of the way.

GitHub CLI does support multiple accounts.

GitHub's official documentation explains that you can authenticate multiple accounts on the same GitHub platform and switch between them using:

gh auth switch
Enter fullscreen mode Exit fullscreen mode

GitHub also explains that the CLI can sometimes determine the intended account from repository context, while some commands need explicit context.

So the problem is not:

GitHub doesn't support multiple accounts.

It does.

The problem is:

How do you manage several accounts without turning your development environment into a collection of context switches?

That's a different problem.


The normal workflow

Imagine you have:

Account A → personal projects
Account B → company work
Account C → client repositories
Enter fullscreen mode Exit fullscreen mode

And Codespaces under each.

The normal CLI-oriented workflow might look like:

gh auth switch --user account-b
gh codespace list
gh codespace ssh
Enter fullscreen mode Exit fullscreen mode

Then later:

gh auth switch --user account-a
gh codespace list
gh codespace ssh
Enter fullscreen mode Exit fullscreen mode

Again, this works.

But now think about an editor that is already open with an active remote workspace.

The real question becomes:

Which account is active?
Which Codespace belongs to it?
Which SSH configuration belongs to that environment?
Can I switch without disturbing something else?
Enter fullscreen mode Exit fullscreen mode

That is where small pieces of friction start accumulating.


Why this becomes more annoying with SSH

GitHub CLI can generate OpenSSH configuration for Codespaces using:

gh codespace ssh --config
Enter fullscreen mode Exit fullscreen mode

GitHub explicitly documents this as an integration point for standard OpenSSH-based tools.

That means each remote workspace can effectively become an SSH host.

Conceptually:

GitHub Account A
   ↓
Codespace A
   ↓
SSH host A

GitHub Account B
   ↓
Codespace B
   ↓
SSH host B
Enter fullscreen mode Exit fullscreen mode

Now multiply that by several environments.

Your ~/.ssh/config can become one more thing you have to keep synchronized.

That was one of the reasons I wanted to automate the configuration rather than asking developers to maintain it manually.


The approach inside Antigravity Codespaces Pro

The extension treats an account as a separate authentication context.

The project supports multiple GitHub accounts simultaneously, with account-specific credentials stored through the editor's secure storage facilities rather than plain-text configuration. The implementation then performs API operations in isolated contexts rather than repeatedly changing one global CLI state.

Conceptually:

                Codespaces Manager
                        │
          ┌─────────────┼─────────────┐
          ↓             ↓             ↓
      Account A     Account B     Account C
          │             │             │
       Token A       Token B       Token C
          │             │             │
       Spaces A      Spaces B      Spaces C
Enter fullscreen mode Exit fullscreen mode

Each account can be queried independently.

That means the dashboard can show:

Personal
Work
Client
Enter fullscreen mode Exit fullscreen mode

at the same time.

Instead of repeatedly asking:

Which account should my CLI be using right now?

the UI asks:

Which environment do you want to open?

That's a much better abstraction for a graphical development tool.


Why credential isolation matters

Multi-account development isn't just a convenience problem.

It is also a security problem.

You don't want the credentials for one environment accidentally becoming the credentials for another.

That's why I didn't want a design where the extension writes personal access tokens into ordinary configuration files.

The project uses the editor's SecretStorage API for credentials and keeps account contexts isolated.

The mental model is simple:

Never:
token → plain text config

Prefer:
token → OS / editor secure credential storage
Enter fullscreen mode Exit fullscreen mode

This doesn't magically solve every authentication problem, but it gives you a much safer foundation.


SSH configuration should also be predictable

One of the more frustrating things with remote development is a broken SSH configuration.

A good automation layer should avoid:

append random config
append same block again
break existing config
lose backup
Enter fullscreen mode Exit fullscreen mode

The extension instead uses generated SSH blocks and atomic file handling, with backup behavior described in the project documentation.

The goal is that running synchronization repeatedly should not slowly destroy the configuration file.


Why a dashboard makes more sense than a terminal here

The terminal is excellent for commands.

For example:

gh codespace list
gh codespace stop
gh codespace rebuild
gh codespace ssh
Enter fullscreen mode Exit fullscreen mode

GitHub officially supports these Codespaces operations through the CLI.

But once you have:

5 Codespaces
3 GitHub accounts
different repositories
different branches
multiple machine sizes
Enter fullscreen mode Exit fullscreen mode

a command-by-command workflow starts making less sense visually.

So the extension provides a Cloud Hub dashboard.

The current dashboard includes things like:

  • account filters
  • workspace cards
  • running/stopped states
  • repository and branch information
  • start/stop controls
  • rebuild actions
  • SSH actions
  • port access
  • search
  • quick connect

These are all directly reflected in the current project implementation and metadata.


The cost side of multiple Codespaces

There is another reason to make the workspace state visible.

Cloud compute has a cost model.

GitHub explains that only running Codespaces incur CPU charges, while stopped Codespaces still incur storage charges.

It also explains that compute usage is measured in core-hours, so larger machines consume those hours faster.

That means a dashboard showing:

8 workspaces
0 running
8 stopped
Enter fullscreen mode Exit fullscreen mode

isn't just pretty UI.

It provides immediate operational information.

You can see what is active and what is not.

That helps reduce the chance of leaving an expensive environment running simply because you forgot about it.


Multiple accounts + AI coding agents

This is the other scenario that pushed me toward the architecture.

Modern coding workflows don't always look like:

type
compile
type
compile
Enter fullscreen mode Exit fullscreen mode

AI coding agents may spend several minutes:

reading files
searching code
planning changes
running commands
building
testing
Enter fullscreen mode Exit fullscreen mode

During periods with little interactive terminal input, connection reliability becomes more important.

The extension exposes SSH keepalive configuration such as:

{
  "antigravity-codespaces.serverAliveInterval": 30,
  "antigravity-codespaces.serverAliveCountMax": 10
}
Enter fullscreen mode Exit fullscreen mode

The project uses these settings to send keepalive traffic over the SSH connection and reduce idle-connection failures during longer agent workflows.

I want to be precise here:

keepalive does not guarantee that every network failure disappears.

It is a connection-resilience measure.

That distinction matters.


A practical example

Imagine this setup:

Personal GitHub
└── portfolio
    └── Codespace

Work GitHub
└── company-api
    └── Codespace

Client GitHub
└── ecommerce-platform
    └── Codespace
Enter fullscreen mode Exit fullscreen mode

Without a management layer, you may find yourself doing:

switch account
list spaces
find space
start space
generate SSH config
connect
Enter fullscreen mode Exit fullscreen mode

Then repeat everything for another account.

With a workspace-oriented UI, the target becomes:

Accounts
├── Personal
├── Work
└── Client

Codespaces
├── portfolio
├── company-api
└── ecommerce-platform
Enter fullscreen mode Exit fullscreen mode

Select the environment.

Connect.

That is the abstraction I wanted.


The architecture

The project is intentionally built around a few separate responsibilities:

┌──────────────────────────────────────┐
│              IDE UI                  │
│ Cloud Hub / Quick Connect / Accounts │
└──────────────────┬───────────────────┘
                   ↓
┌──────────────────────────────────────┐
│          Authentication Layer         │
│       OAuth / PAT / GitHub CLI        │
└──────────────────┬───────────────────┘
                   ↓
┌──────────────────────────────────────┐
│           GitHub API Layer            │
│     Account-isolated API requests     │
└──────────────────┬───────────────────┘
                   ↓
┌──────────────────────────────────────┐
│             SSH Manager               │
│      Generated + synchronized config  │
└──────────────────┬───────────────────┘
                   ↓
┌──────────────────────────────────────┐
│         GitHub Codespaces             │
│       Remote container / VM           │
└──────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

The goal is separation.

Authentication should not become UI state.

UI state should not become SSH configuration.

SSH configuration should not become account switching.

Each layer has its own job.


What I would recommend for developers with multiple accounts

If you only have one GitHub account and one Codespace, the standard GitHub workflow is probably enough.

I wouldn't install another tool just because it exists.

The management layer becomes interesting when your environment looks more like:

multiple accounts
+
multiple Codespaces
+
Remote-SSH
+
Cursor / Windsurf / VSCodium
+
AI agents
Enter fullscreen mode Exit fullscreen mode

At that point, automation starts saving cognitive overhead rather than just keystrokes.


Why I built this

The original problem wasn't:

I need another GitHub tool.

It was:

I don't want my development environment to depend on remembering which account, command, SSH host, and browser tab I need to use next.

That distinction shaped the entire product.

So Antigravity Codespaces Pro is essentially a workspace manager for GitHub Codespaces that happens to live inside the IDE.

The current project supports Cursor, Antigravity IDE, VS Code / Code-OSS, Windsurf, and VSCodium, alongside multi-account management and SSH automation.


Final thoughts

GitHub has already built most of the underlying infrastructure:

Codespaces
GitHub CLI
SSH
Port Forwarding
Authentication
Remote Development
Enter fullscreen mode Exit fullscreen mode

The interesting engineering problem is what happens between those primitives and the developer's workflow.

That's the layer I decided to work on.

And I'm still iterating on it.

Open source repository:

Nir-Bhay/antigravity-codespaces


Top comments (1)

Collapse
 
nirbhay_hiwse profile image
Nirbhay Hiwse

Core Capabilities
⚡ 1-Click Quick Connect — Alt+C
Press Alt+C anywhere in your editor. A fuzzy-search launcher lists every Codespace across all your GitHub accounts (running instances prioritized, followed by recent activity). Press Enter, and you are connected inside your editor in seconds.

🏢 True Multi-Account Support (Work + Personal + Orgs)
Connect multiple GitHub accounts simultaneously:

Native GitHub OAuth (fast, no terminal popups).
Personal Access Tokens (stored encrypted in your OS keychain via SecretStorage).
GitHub CLI (gh auth). Each account is queried in parallel with isolated tokens. Switching accounts never logs out or disturbs other accounts.
🤖 AI Agent Session KeepAlive (Cursor Agent & Antigravity Agent)
Autonomous agent tasks often run for 10 to 45 minutes without terminal typing. Standard SSH tunnels drop on idle timeout, killing the agent midway. Antigravity Codespaces Pro automatically configures ServerAliveInterval and TCPKeepAlive inside SSH host blocks so your agent keeps working uninterrupted until the job is done.

🛡️ Zero-Password SSH Tunneling & Golden Blocks
The extension automatically detects GitHub CLI authentication keys (~/.ssh/codespaces.auto) and injects proper IdentityFile declarations into your SSH configuration. No more unexpected password prompts or broken proxy commands. Writes are atomic with automatic .bak backups.

🖥️ Bento Grid Cloud Hub Dashboard
Open a full-featured management panel right inside your editor:

KPI Metrics Strip: Total workspaces, running instances, stopped containers, and free storage tier usage.
Account Chips: Filter workspaces by account with a single click.
Live Search (/): Instant search by repository name, Codespace display name, or branch.
View Switcher: Toggle between clean Bento Cards and compact List View.
4-Step Creation Wizard: Account → Repository → Branch → Provision with auto-recovery.
Container Lifecycle Controls: Wake up (cold boot), stop, standard rebuild, clean rebuild, and delete.
🌐 Live Port Forwarding Discovery & Latency Checker
Inspect forwarded web ports (3000, 5173, 8080, etc.) on running containers directly from the sidebar. Run millisecond latency pings before connecting to pick the fastest cloud region.