A GitHub CLI extension that enables Azure DevOps (ADO) authentication with GitHub Codespaces via SSH connections, without requiring VS Code to be running. It also provides automatic port forwarding capabilities.
When working with GitHub Codespaces and Azure DevOps services, authentication can be challenging, especially when connecting via SSH rather than through VS Code. This extension bridges that gap by:
- Securely forwarding your local Azure CLI credentials to your codespace
- Automatically detecting and forwarding application ports from your codespace to your local machine
- Providing a seamless development experience with GitHub Codespaces and Azure DevOps
- GitHub CLI (
gh) installed and authenticated - Azure CLI (
az) installed and logged in to the appropriate tenant - A GitHub Codespace with Artifacts Helper configured
gh extension install scaryrawr/gh-ado-codespacesBefore using the extension, make sure you're logged into Azure CLI with the appropriate scope:
az login --scope 499b84ac-1321-427f-aa17-267ca6975798/.defaultThen, start a new session with your codespace:
gh ado-codespacesThe extension will:
- Start a local authentication service
- Prompt you to select a GitHub Codespace (if not specified)
- Establish a secure port forwarding channel for authentication
- Start an interactive SSH session
- Automatically forward detected application ports from your codespace
Usage:
gh ado-codespaces [flags] [-- ssh-flags...]
Flags:
--codespace, -c string Name of the codespace
--config Write OpenSSH configuration to stdout
--debug, -d Log debug data to a file
--debug-file string Path of the file to log to
--azure-subscription-id string Azure subscription ID to use for authentication (persisted per GitHub account)
--profile string Name of the SSH profile to use
--repo, -R string Filter codespace selection by repository name (user/repo)
--repo-owner string Filter codespace selection by repository owner (username or org)
--server-port int SSH server port number (0 => pick unused)
You can also pass additional SSH flags after --, for example:
gh ado-codespaces -- -L 3000:localhost:3000The extension can read optional configuration values that are scoped per GitHub login. By default it looks for a JSON file at:
$OS_CONFIG_DIR/gh-ado-codespaces/config.json
Set the GH_ADO_CODESPACES_CONFIG environment variable to point at a different file if you prefer a custom location.
The configuration file is a JSON object keyed by GitHub login IDs returned by gh auth switch. Each account can provide Azure-specific overrides, such as the subscription to use when acquiring tokens via the Azure CLI:
{
"login-id-1": {},
"login-id-2": {
"azure": {
"subscription": "00000000-0000-0000-0000-000000000000"
}
}
}If a subscription is set, the extension requests tokens from the Azure CLI using that subscription. When no override is present, the Azure CLI's default subscription continues to be used.
You can create or update this setting directly from the command line by supplying the --azure-subscription-id flag once. The value will be persisted for the active GitHub login so future invocations do not need the flag unless you want to change or clear it. To clear the stored value, edit the config file and remove (or empty) the subscription field for your login.
The extension leverages Azure CLI credentials on your local machine to authenticate with Azure DevOps:
- A Node.js service using the
@azure/identitypackage connects to your Azure CLI credentials - An SSH connection forwards this service to a Unix socket in the codespace
- Development tools inside the codespace request tokens through the ADO Auth Helper
The extension provides browser opening from your codespace to your local machine:
- When you connect, a browser opener script is uploaded to your codespace at
~/browser-opener.sh - The script is automatically configured with the browser service port (no manual configuration needed)
- A local HTTP service is started that listens for browser open requests
- The service port is forwarded to the codespace via SSH reverse port forwarding
- Users can configure their shell to use the browser opener by adding to their shell config (e.g.,
~/.bashrcor~/.zshrc):export BROWSER="$HOME/browser-opener.sh"
- When any tool in the codespace tries to open a URL (e.g., via
xdg-open,python -m webbrowser, etc.), it uses theBROWSERenvironment variable - The script sends an HTTP request to the local machine with the URL
- Your local browser opens automatically with the requested URL
This is particularly useful for:
- Opening documentation links from CLI tools
- Viewing web-based development servers running in your codespace
- Accessing OAuth flows and authentication pages
- Opening links from terminal-based applications
The browser opener works cross-platform and will use your default browser on Windows, macOS, and Linux.
Note: You only need to set the BROWSER environment variable once in your shell configuration. The port is automatically configured in the script when it's uploaded.
The automatic port forwarding system works in two directions:
The extension detects when applications in your codespace start listening on network ports:
- A port monitor runs in your codespace and detects new listening ports
- Port events are sent to your local machine through the SSH connection
- New SSH tunnels are created automatically for each detected port
- Applications running in your codespace become accessible via
localhost:<port>locally
The extension automatically shares local AI services to your codespace:
- When connecting, the extension checks if Ollama (port 11434) or LM Studio (port 1234) are running locally
- If either service is detected, a reverse SSH tunnel is automatically created
- Your codespace can then access these services via
localhost:1234orlocalhost:11434 - This enables you to use your local AI models and services from within your codespace
This is particularly useful for:
- Running Ollama models on your local machine while coding in a codespace
- Using LM Studio's local inference server from your codespace
- Sharing any locally-running AI services with your remote development environment
This project includes a comprehensive unit test suite that covers:
-
Command line argument parsing and validation (
args_test.go)- Azure subscription ID format validation
- Command line flag building for
gh codespace ssh - SSH argument construction with browser service integration
-
Configuration file handling (
config_test.go)- Azure subscription storage and retrieval per GitHub account
- JSON configuration file loading and saving
- Error handling for malformed configuration files
-
Browser opening functionality (
browser_test.go)- HTTP-based browser service creation and lifecycle management
- Cross-platform URL opening support via HTTP endpoint
- HTTP method and parameter validation
- SSH argument integration with browser port forwarding
-
Utility functions (
main_test.go)- Filename sanitization for session directories
- Session ID generation and formatting
- File size formatting for log file listings
-
Codespace operations (
codespace_test.go)- Codespace list item formatting with colors and status indicators
- Git status indicators (ahead commits, uncommitted/unpushed changes)
- Codespace sorting by availability status
-
GitHub integration (
github_login_test.go)- GitHub CLI authentication integration tests
- GitHub username validation
Run all tests:
go test -v ./...Run tests with race detection:
go test -v -race ./...Run only fast unit tests (skip integration tests):
go test -short -v ./...The test suite maintains compatibility with the existing CI/CD pipeline and ensures all functionality works correctly without external dependencies in most cases.
- Authentication is tied to your local Azure CLI session
- Initial setup with Artifacts Helper is required in the codespace
This project builds upon the work done in ADO SSH Auth for GitHub Codespaces, adapting it as a GitHub CLI extension with additional functionality.