Workspace Context Switcher — record and replay developer workspace setups
Project description
Spaceload — Workspace Context Switcher
A macOS CLI tool that records and replays developer workspace setups: browser tabs, VPN connections, IDE projects, and terminal sessions.
Overview
spaceload lets you snapshot your entire development environment and restore it later with a single command. Stop context-switching overhead and get back into flow faster.
Features
- Record workspace sessions (browser tabs, VPN, IDE, terminals)
- Replay saved workspaces in one command
- Export/Import workspace definitions as YAML
- List and manage saved workspaces
Installation
Via pip:
pip install spaceload
Via Homebrew:
brew tap tomjosetj31/spaceload
brew install tomjosetj31/spaceload/spaceload
From source:
git clone https://github.com/tomjosetj31/spaceload
cd spaceload
python -m venv .venv
source .venv/bin/activate
pip install -e .
Usage
# Start recording a workspace session
spaceload record my-project
# ... open your browser tabs, connect VPN, open IDE, etc. ...
# Stop recording and save the session
spaceload stop
# Replay a saved workspace
spaceload run my-project
# List all saved workspaces
spaceload list
# Inspect a workspace as YAML
spaceload show my-project
# Delete a workspace
spaceload delete my-project
# Import a workspace from a YAML file
spaceload import my-project.yaml
Recording Options
# Record only new things opened during recording (default)
spaceload record my-project
# Also capture everything already open when recording starts
spaceload record my-project --include-open
# or
spaceload record my-project -i
Privacy & Permissions
Spaceload runs entirely on your machine. It never sends any data to a server, the internet, or any external service. Everything is stored locally in ~/.spaceload/.
macOS will prompt you to grant the following permissions the first time they are needed:
| Permission | Why it's needed |
|---|---|
| Automation | Used to control browsers (Chrome, Safari, Arc), IDEs (VS Code, Cursor), terminals (iTerm2, Terminal.app, Warp), and Tunnelblick via AppleScript to read open tabs, project paths, and connection state. macOS will show a dialog for each app the first time. |
| Accessibility | Used via System Events to list running processes and read window titles (e.g. to detect which IDE projects are open). |
| Full Disk Access | Required to read Firefox's session files (~/Library/Application Support/Firefox/) and VS Code/Cursor workspace state (~/Library/Application Support/Code/ or Cursor/). Without this, those adapters fall back to window-title heuristics. |
You can review and revoke these at any time in System Settings → Privacy & Security.
Supported Integrations
Specialized Adapters (Rich Tracking)
These apps have dedicated adapters that track specific details:
| Category | Supported | What's Tracked |
|---|---|---|
| Browser | Chrome, Safari, Arc, Firefox | Individual tab URLs |
| VPN | Tailscale, WireGuard, Cisco AnyConnect, Mullvad, OpenVPN, Tunnelblick | Connection state & profile |
| IDE | VS Code, Cursor, Zed | Open project/folder paths |
| Terminal | iTerm2, Terminal.app, Warp, Kitty | Working directories per session, commands (with shell hook) |
Generic App Tracking
Any other application you open during recording is automatically tracked as an app_open action with the app name. This includes apps like Notes, Calendar, Slack, Spotify, etc.
Firefox Support
Firefox tab reading requires the lz4 library to parse session files:
# Install with Firefox support
pip install -e ".[firefox]"
# Or install lz4 separately
pip install lz4
Without lz4, Firefox tabs won't be read during recording, but URLs can still be opened during replay.
Terminal Command Tracking
To track terminal commands during recording, add the shell hook to your shell config:
# For zsh (~/.zshrc):
eval "$(spaceload shell-hook zsh)"
# For bash (~/.bashrc):
eval "$(spaceload shell-hook bash)"
Then restart your shell or run source ~/.zshrc.
How it works:
- Commands are only tracked when a recording session is active
- The hook checks for the daemon socket before sending (no overhead when not recording)
- Commands run in the background so they don't slow down your shell
- During replay, commands are displayed but not auto-executed (for safety)
Smart Browser Filtering
The recorder automatically filters out:
- New tab pages (
chrome://newtab/,about:newtab, etc.) - Internal browser pages (
chrome://,about:,safari-resource:, etc.) - Intermediate URLs (pages open less than 3 seconds)
- Redirect chains (multiple URLs from same domain in quick succession)
Logs & Debugging
Logs are written to ~/.spaceload/ for debugging:
# Daemon log (recording)
cat ~/.spaceload/daemon.log
# Replay log
cat ~/.spaceload/replay.log
Architecture
- CLI (
spaceload/cli/) — Click-based command interface - Daemon (
spaceload/daemon/) — Unix socket server that records actions in the background - Store (
spaceload/store/) — SQLite-backed persistence layer with YAML export/import - Replayer (
spaceload/replayer/) — Replays recorded action sequences - Adapters (
spaceload/adapters/) — Per-integration plugins (browser, VPN, IDE, terminal)
Tech Stack
- Python 3.11+
- Click for the CLI
- SQLite (stdlib) for persistence
- PyYAML for export/import
- Unix domain sockets for CLI↔daemon IPC
Contributing
Contributions are welcome! Whether it's a bug fix, a new adapter for an app you use, or a documentation improvement — all PRs are appreciated.
Please read CONTRIBUTING.md for guidelines on how to set up the project locally, run tests, and submit a pull request.
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file spaceload-0.1.1.tar.gz.
File metadata
- Download URL: spaceload-0.1.1.tar.gz
- Upload date:
- Size: 84.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
90678339a70c648160bbf3a971d97c8419cac02a5bd94ea197c4ee73c1ba1b62
|
|
| MD5 |
19d0a7ff1a1996f56311bc73a67198d1
|
|
| BLAKE2b-256 |
6019e33eda54b5ee40e59a1a2720044319f81d8bcf3ef4870ff12abb4e66939e
|
Provenance
The following attestation bundles were made for spaceload-0.1.1.tar.gz:
Publisher:
release.yml on tomjosetj31/spaceload
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
spaceload-0.1.1.tar.gz -
Subject digest:
90678339a70c648160bbf3a971d97c8419cac02a5bd94ea197c4ee73c1ba1b62 - Sigstore transparency entry: 1188025132
- Sigstore integration time:
-
Permalink:
tomjosetj31/spaceload@9d0fe3b4926715a34da5c1fe0d52d9f31b354f26 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/tomjosetj31
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@9d0fe3b4926715a34da5c1fe0d52d9f31b354f26 -
Trigger Event:
push
-
Statement type:
File details
Details for the file spaceload-0.1.1-py3-none-any.whl.
File metadata
- Download URL: spaceload-0.1.1-py3-none-any.whl
- Upload date:
- Size: 74.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7cfb1eee0ff6825c1600f97773656d4f5d26ccfe652623ea3c5f66d43c24a084
|
|
| MD5 |
989887b332c63a509129d5ab52a0e1df
|
|
| BLAKE2b-256 |
49cfa63fd5492121beeed2dd057bca67998d22f8b250b26f29b0732700cc73f1
|
Provenance
The following attestation bundles were made for spaceload-0.1.1-py3-none-any.whl:
Publisher:
release.yml on tomjosetj31/spaceload
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
spaceload-0.1.1-py3-none-any.whl -
Subject digest:
7cfb1eee0ff6825c1600f97773656d4f5d26ccfe652623ea3c5f66d43c24a084 - Sigstore transparency entry: 1188025137
- Sigstore integration time:
-
Permalink:
tomjosetj31/spaceload@9d0fe3b4926715a34da5c1fe0d52d9f31b354f26 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/tomjosetj31
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@9d0fe3b4926715a34da5c1fe0d52d9f31b354f26 -
Trigger Event:
push
-
Statement type: