CLI for managing GitHub workspaces with git worktrees and secure remote terminal access
npm install gitspaceA powerful CLI tool for managing GitHub repository workspaces using git worktrees and optional Linear integration. Work on multiple features/tasks simultaneously, each in its own isolated workspace. Features an interactive TUI and support for repo config bundles for team onboarding.
- Interactive TUI: Beautiful terminal interface for managing projects and workspaces
- Git Worktrees: Work on multiple branches simultaneously without stashing
- Linear Integration: Create workspaces directly from Linear issues with automatic markdown documentation
- Smart Branch Management: Automatic detection of remote branches
- Workspace Status: Track uncommitted changes, stale workspaces, and more
- Custom Scripts: Convention-based scripts for setup, select, pre-setup, and removal phases
- Repo Config Bundles: Share onboarding configurations with your team, including scripts and setup steps
- Secure Secrets: Store sensitive values in OS keychain via Bun.secrets
The following tools must be installed and available in your PATH:
- GitHub CLI (gh) - for listing repositories
- Git - for worktree management
- jq - for JSON processing
GitHub Authentication: You must authenticate the GitHub CLI before using GitSpace:
``bash`
gh auth login
`bashnpm
npm install -g gitspace
Quick Start
$3
Simply run
gssh with no arguments to launch the interactive TUI:`bash
gssh
`The TUI provides a two-panel interface:
- Left panel: Your projects
- Right panel: Workspaces in the selected project
Key Bindings:
| Key | Action |
|-----|--------|
|
Enter | Select project / Open workspace |
| Tab | Switch between panels |
| n | New project / workspace |
| d | Delete selected item |
| ? | Show help |
| q | Quit |$3
You can also use traditional CLI commands:
#### 1. Add Your First Project
`bash
gssh add project
`Select a GitHub repository, and GitSpace will:
- Clone the repository to
~/gitspace/
- Detect the default branch
- Run onboarding steps if a bundle is present
- Create project configuration#### 2. Create a Workspace
`bash
Create a workspace from a Linear issue (if configured)
gssh addOr create a workspace with a custom name
gssh add my-feature
`#### 3. Switch Between Workspaces
`bash
Interactive selection
gssh switchSwitch to a specific workspace
gssh switch my-feature
`Repo Config Bundles
Repo config bundles allow repository owners to share onboarding configurations with their team. When someone clones a project that contains a bundle, they'll be guided through setup steps and have scripts automatically installed.
$3
A bundle is a directory (typically
.gitspace/) containing:`
.gitspace/
├── bundle.json # Bundle manifest with onboarding steps
├── pre/ # Scripts to run before setup
│ └── 01-copy-env.sh
├── setup/ # Scripts to run on first workspace creation
│ └── 01-install-deps.sh
├── select/ # Scripts to run every time workspace is opened
│ └── 01-status.sh
└── remove/ # Scripts to run before workspace deletion
└── 01-cleanup.sh
`$3
`json
{
"version": "1.0",
"name": "my-app-bundle",
"description": "Setup bundle for my-app",
"onboarding": [
{
"id": "welcome",
"type": "info",
"title": "Welcome",
"description": "Let's get you set up!"
},
{
"id": "node",
"type": "confirm",
"title": "Node.js",
"description": "Node.js 18+ is required",
"checkCommand": "node",
"installUrl": "https://nodejs.org"
},
{
"id": "api-key",
"type": "secret",
"title": "API Key",
"description": "Enter your API key",
"configKey": "apiKey"
},
{
"id": "team-name",
"type": "input",
"title": "Team Name",
"description": "Enter your team name",
"configKey": "teamName",
"defaultValue": "engineering"
}
]
}
`$3
| Type | Purpose | Storage |
|------|---------|---------|
|
info | Display information | N/A |
| confirm | Verify installation (can check command in PATH) | N/A |
| secret | Collect sensitive values (masked input) | OS Keychain |
| input | Collect plain text values | Project config |$3
Bundle values are passed to scripts as environment variables:
-
SPACE_VALUE_ - Regular values from input steps
- SPACE_SECRET_ - Secret values from secret steps (fetched from OS keychain)Example script:
`bash
#!/bin/bash
.gitspace/select/01-status.sh
WORKSPACE_NAME=$1
REPOSITORY=$2
Access bundle values
if [ -n "$SPACE_VALUE_TEAMNAME" ]; then
echo "Welcome, $SPACE_VALUE_TEAMNAME team!"
fiAccess secrets (stored securely in OS keychain)
if [ -n "$SPACE_SECRET_APIKEY" ]; then
echo "API Key configured"
fi
`$3
Bundles can be loaded from:
1. In-repo (automatic):
.gitspace/ directory in the cloned repository
2. Local path: gssh add project --bundle-path /path/to/bundle/
3. Remote URL: gssh add project --bundle-url https://example.com/bundle.zipCommands Reference
$3
Launch the interactive terminal UI.
$3
Add a new project from GitHub.
`bash
gssh add project [options]Options:
--bundle-url Load bundle from remote URL (zip archive)
--bundle-path Load bundle from local directory
--skip-bundle Skip bundle detection and onboarding
--no-clone Create project structure without cloning
--org Filter repos to specific organization
--linear-key Provide Linear API key via flag
`$3
Create a new workspace in the current project.
`bash
gssh add [workspace-name] [options]Options:
--branch Specify different branch name from workspace name
--from Create from specific branch instead of base
--no-setup Skip setup commands
`$3
Switch to a workspace in the current project.
`bash
gssh switch [workspace-name]
Alias: gssh sw
`$3
Switch to a different project.
$3
List projects or workspaces.
`bash
gssh list [subcommand] [options]
Alias: gssh ls
Subcommands:
projects List all projects
workspaces List workspaces in current project (default)
Options:
--json Output in JSON format
--verbose Show additional details
`$3
Remove a workspace.
`bash
gssh remove workspace [workspace-name] [options]
Alias: gssh rm workspace
Options:
--force Skip confirmation prompts
--keep-branch Don't delete git branch when removing workspace
`$3
Remove a project.
`bash
gssh remove project [project-name] [options]
Alias: gssh rm project
Options:
--force Skip confirmation prompts
`$3
Print the current project directory path.
`bash
gssh directory
Alias: gssh dir
`Configuration
$3
Located at
~/gitspace/.config.json:`json
{
"currentProject": "my-app",
"projectsDir": "/Users/username/gitspace",
"defaultBaseBranch": "main",
"staleDays": 30
}
`$3
Located at
~/gitspace/:`json
{
"name": "my-app",
"repository": "myorg/my-app",
"baseBranch": "main",
"linearApiKey": "lin_api_...",
"linearTeamKey": "ENG",
"bundleValues": {
"teamName": "engineering"
},
"bundleSecretKeys": ["apiKey"],
"appliedBundle": {
"name": "my-app-bundle",
"version": "1.0",
"source": "/path/to/bundle",
"appliedAt": "2025-01-01T00:00:00Z"
}
}
`-
bundleValues: Values collected from input steps during onboarding
- bundleSecretKeys: Keys of secrets stored in OS keychain (values are NOT stored in config)
- appliedBundle: Information about the bundle that was applied$3
GitSpace uses convention over configuration for custom scripts. Scripts live
inside each workspace so they can vary by branch:
`
~/gitspace//workspaces//.gitspace/
├── pre/ # Run before setup (terminal)
├── setup/ # Run once on workspace creation
├── select/ # Run every time workspace is opened
└── remove/ # Run before workspace deletion
`#### Script Execution Rules
1. Scripts must be executable (
chmod +x)
2. Scripts run alphabetically (use 01-, 02- prefixes)
3. Working directory: The workspace directory
4. Arguments: $1 = workspace name, $2 = repository name
5. Environment: Bundle values available as SPACE_VALUE_ and SPACE_SECRET_#### Script Phases
| Phase | When | Use Case |
|-------|------|----------|
|
pre/ | Once, before setup | Copy .env files, create directories |
| setup/ | Once, on workspace creation | Install dependencies, initial build |
| select/ | Every workspace open | Git fetch, status checks |
| remove/ | Before deletion | Cleanup, notifications |$3
`bash
Set the current project (overrides global config)
export SPACES_CURRENT_PROJECT="my-app"Available in scripts (from bundle onboarding):
SPACE_VALUE_ - Regular values
SPACE_SECRET_ - Secret values (from OS keychain)
`Directory Structure
`
~/gitspace/
├── .config.json # Global configuration
├── /
│ ├── .config.json # Project configuration
│ ├── base/ # Base repository clone
│ ├── workspaces/ # Git worktrees
│ │ └── /
│ │ ├── gitspace.lock # Setup completion marker
│ │ └── .prompt/ # Linear issue details (if applicable)
│ │ └── issue.md
│ └── workspaces/
│ └── /
│ └── .gitspace/ # Custom scripts (per worktree)
│ ├── pre/
│ ├── setup/
│ ├── select/
│ └── remove/
│ ├── pre/
│ ├── setup/
│ ├── select/
│ └── remove/
`Remote Access
GitSpace provides secure remote terminal access with end-to-end encryption. Access your terminal sessions from anywhere via web browser or CLI.
$3
The easiest way to get remote access is through gitspace.sh:
`bash
1. Authenticate with GitHub
gssh auth login2. Reserve your subdomain (e.g., yourname.gitspace.sh)
gssh host reserve yourname3. Start serving (creates identity if needed)
gssh serve4. Access from browser at https://yourname.gitspace.sh
`$3
For complete control, run your own relay:
`bash
Terminal 1: Start relay server
gssh relay start --port 4480Terminal 2: Initialize identity and start serving
gssh identity init --label "My MacBook"
gssh serve --relay ws://localhost:4480/wsTerminal 3: Create invite for remote access
gssh share createShare the invite URL with collaborators
`$3
Every machine and client has a cryptographic identity (Ed25519 + X25519 keypair):
`bash
Create machine identity (stored in ~/gitspace/.identity/)
gssh identity init --label "My MacBook"View identity fingerprint
gssh identity show
`$3
Control who can connect to your machine:
`bash
List authorized clients
gssh access listAdd a client by public key
gssh access add spcs_pk_abc123... --label "Work Laptop"Remove client access
gssh access remove spcs_pk_abc123...
`$3
Share access via signed invite tokens:
`bash
Create invite (24h default)
gssh share createCustom expiration
gssh share create --expires 7d
`$3
`bash
Connect using invite token
gssh connect Connect via TUI with relay
gssh --relay wss://relay.example.com
`$3
| Command | Description |
|---------|-------------|
|
gssh auth login | Authenticate with gitspace.sh (GitHub OAuth) |
| gssh auth logout | Sign out of gitspace.sh |
| gssh host reserve | Reserve a subdomain on gitspace.sh |
| gssh host status | Show hosting status |
| gssh identity init | Create machine/client identity |
| gssh identity show | Display identity fingerprint |
| gssh access add | Authorize a client |
| gssh access list | List authorized clients |
| gssh access remove | Revoke client access |
| gssh serve | Start machine daemon |
| gssh serve start | Start serve as background daemon |
| gssh serve stop | Stop background serve daemon |
| gssh share create | Create invite token |
| gssh connect | Connect to remote machine |
| gssh status | Show all daemon statuses |$3
For self-hosted relay servers:
| Command | Description |
|---------|-------------|
|
gssh relay start | Start relay server |
| gssh relay authorize | Authorize a machine |
| gssh relay revoke | Revoke machine authorization |
| gssh relay machines | List registered machines |
| gssh relay trusted | List trusted relays |
| gssh relay untrust | Remove relay trust |$3
Manage terminal sessions:
| Command | Description |
|---------|-------------|
|
gssh tmux start | Start tmux-lite daemon |
| gssh tmux stop | Stop tmux-lite daemon |
| gssh tmux list | List sessions |
| gssh tmux attach | Attach to session |
| gssh tmux new | Create new session |
| gssh tmux kill | Kill session |$3
`bash
Relay server
RELAY_PORT=4480 # Default relay port
RELAY_BIND=0.0.0.0 # Bind addressMachine identity
GSSH_IDENTITY_PATH=~/gitspace/.identity/ # Identity storagegitspace.sh
GITSPACE_API_URL=https://api.gitspace.sh # API endpoint
`$3
- E2E Encryption: All terminal I/O encrypted with AES-256-GCM
- X3DH Handshake: Forward-secret session key establishment
- Ed25519 Signatures: Cryptographic identity verification
- Zero-knowledge Relay: Relay cannot decrypt terminal content
See docs/GETTING-STARTED.md for detailed setup and docs/REMOTE-DESIGN.md for architecture.
Troubleshooting
$3
`
Error: GitHub CLI is not authenticated
`Solution: Run
gh auth login and follow the prompts.$3
Solution: Install the missing dependencies using the provided URLs in the error message.
$3
If
SPACE_SECRET_* variables are empty, ensure:
1. You completed the onboarding secret steps
2. Your OS keychain service is running (libsecret on Linux, Keychain on macOS)Development
`bash
Install dependencies
bun installDevelopment mode
bun run devType checking
bun run typecheckRun linter
bun run lint
``MIT
Contributions are welcome! Please feel free to submit a Pull Request.