A "global home folder" for devcontainers. Teeleport gives you persistent state, consistent configuration, and your favorite tools across every ephemeral VS Code / Codespaces / devcontainer workspace.
Add one line to your dotfile repo's install script and Teeleport handles the rest: mounting remote directories, copying config files, installing packages, and launching your AI coding assistant.
Reading docs is so 2024, This is the easiest way to set up Teeleport. Paste this prompt into any AI coding agent (Claude Code, Codex, Copilot, etc.):
Follow the instructions in https://raw.githubusercontent.com/BenjaminBenetti/Teeleport/main/SETUP_SKILL.md to help me set up Teeleport.
In your dotfile repo's install script (e.g., install.sh), add:
curl -fsSL https://raw.githubusercontent.com/BenjaminBenetti/Teeleport/main/install.sh | bashTo pin a specific version:
curl -fsSL https://raw.githubusercontent.com/BenjaminBenetti/Teeleport/main/install.sh | bash -s -- --version v1.0.0Add a teeleport.config to the root of your dotfile repo:
# Install system packages
packages:
- curl
- jq
- ripgrep
# Copy config files from your dotfile repo into the container
copies:
- name: bashrc
source: config/.bashrc
target: ~/.bashrc
mode: replace
- name: git-aliases
source: config/.git_aliases
target: ~/.bashrc
mode: append
- name: gitconfig
source: config/.gitconfig
target: ~/.gitconfig
mode: replace
# Mount remote directories for persistent state (requires FUSE)
mounts:
ssh:
host: my-server.example.com
user: devuser
entries:
- name: claude
source: /home/devuser/.claude
target: ~/.claude
backend: sshfs
# Install and auto-run an AI CLI tool
ai_cli:
- tool: claude-code
startup_prompt: "Review the project and set up your memory."In VS Code or GitHub Codespaces, set your dotfiles repository in settings. Every new container will automatically run your install script, which runs Teeleport, which sets up your entire environment.
When Teeleport runs, it executes these steps in order:
1. Install packages apt/dnf/pacman (auto-detected)
2. Mount remote dirs SSHFS mounts or rsync initial sync
3. Start rsync daemon Background bidirectional sync (if rsync entries exist)
4. Copy config files From your dotfile repo to the right locations
5. Launch AI CLI Install and run with an optional startup prompt
All operations are idempotent -- safe to run on every container creation.
List the packages you need and Teeleport installs them automatically. It detects whether the container uses apt, dnf, or pacman.
packages:
- curl
- wget
- jq
- ripgrep
- htopCopy files from your dotfile repo to the correct locations in the container.
Replace mode overwrites the target file entirely:
copies:
- name: gitconfig
source: config/.gitconfig
target: ~/.gitconfig
mode: replaceAppend mode adds content to an existing file using sentinel markers to ensure idempotency:
copies:
- name: bash-aliases
source: config/.bash_aliases
target: ~/.bashrc
mode: appendMount directories from a remote host into your container for live, bidirectional state. This is how you keep things like ~/.claude persistent across workspaces -- changes sync in real-time.
mounts:
ssh:
host: my-server.example.com
user: devuser
entries:
- name: claude
source: /home/devuser/.claude
target: ~/.claude
backend: sshfsFile mounts work the same way but for individual files. Under the hood, Teeleport mounts the remote parent directory to a staging area and symlinks the file to the target path:
mounts:
ssh:
host: my-server.example.com
user: devuser
entries:
- name: claude-json
source: /home/devuser/.claude.json
target: ~/.claude.json
type: file
backend: sshfsPresets provide predefined mount configurations for common tools:
mounts:
ssh:
host: my-server.example.com
user: devuser
entries:
- name: claude-preset
preset: claudeAvailable presets:
| Preset | Description |
|---|---|
claude |
Mounts ~/.claude directory and ~/.claude.json file from /var/opt/teeleport/ |
codex |
Mounts ~/.codex directory from /var/opt/teeleport/ |
gemini |
Mounts ~/.gemini directory from /var/opt/teeleport/ |
copilot |
Mounts ~/.copilot directory from /var/opt/teeleport/ |
gh |
Mounts ~/.config/gh directory from /var/opt/teeleport/ for GitHub CLI auth and config |
known_hosts |
Mounts ~/.ssh/known_hosts file from /var/opt/teeleport/ so accepted SSH host keys persist across containers |
Prerequisites for SSHFS mounts:
Your devcontainer.json must grant FUSE access. Add one of:
You also need SSH access to the remote host. Devcontainer SSH agent forwarding is the easiest way to set this up.
An alternative to SSHFS that does not require FUSE. Instead of a live filesystem mount, Teeleport runs a background daemon that periodically synchronises files between the container and the remote host using rsync over SSH.
mounts:
ssh:
host: my-server.example.com
user: devuser
rsync:
interval: 30 # seconds between sync cycles (default: 30)
entries:
- name: projects
source: /home/devuser/projects
target: ~/projects
backend: rsync
- name: myconfig
source: /home/devuser/.myconfig
target: ~/.myconfig
type: file
backend: rsyncHow it works:
- On
teeleportstartup, an initial sync pulls the remote state into the container. - A background daemon is launched that runs bidirectional sync cycles at the configured interval.
- Each cycle pushes local changes to the remote, then pulls remote changes to the local side.
- Last-write-wins: the newest version of each file always takes precedence (
rsync --update). - Deletions propagate: files deleted on one side are removed from the other (
rsync --delete). Since push runs before pull, local deletions propagate to the remote; files deleted only on the remote will be removed locally on the next pull. - The daemon is resilient to transient errors -- failures are logged and retried on the next cycle.
Daemon lifecycle:
- Started automatically after the initial sync completes.
- A shell hook checks that the daemon is alive on every interactive shell open and restarts it if it has crashed.
- The daemon writes its PID to
~/.teeleport/rsync.pidand logs to~/.teeleport/rsync.log. - You can also run the daemon manually:
teeleport rsync --config <path>.
When to use rsync vs SSHFS:
| SSHFS | Rsync | |
|---|---|---|
| Sync model | Live FUSE mount (instant) | Periodic copy (interval-based) |
| Requires FUSE | Yes | No |
| Works offline | No (mount hangs) | Yes (local copy persists) |
| Best for | Config dirs, auth state | Larger working trees, no-FUSE environments |
Install and auto-invoke an AI coding CLI on container start. Supported tools:
| Tool | Config value | Install method |
|---|---|---|
| Claude Code | claude-code |
npm install -g @anthropic-ai/claude-code |
| OpenAI Codex | codex |
npm install -g @openai/codex |
| Gemini CLI | gemini-cli |
npm install -g @google/gemini-cli |
| GitHub Copilot | copilot |
gh extension install github/gh-copilot |
Provide a startup prompt inline or from a file:
ai_cli:
- tool: claude-code
startup_prompt: "Review the project and set up your memory."
# Or use an external file:
# startup_prompt_file: prompts/startup.mdAI CLI errors are never fatal. On first run you may need to log in interactively -- once auth is persisted (e.g., via a .claude mount), subsequent runs work automatically.
dotfiles/
├── install.sh # Your dotfile install script
├── teeleport.config # Teeleport configuration
├── config/
│ ├── .bashrc # Copied to ~/.bashrc (replace)
│ ├── .bash_aliases # Appended to ~/.bashrc (append)
│ └── .gitconfig # Copied to ~/.gitconfig (replace)
└── prompts/
└── startup.md # AI CLI startup prompt (optional)
Example install.sh:
#!/bin/bash
# Run Teeleport -- handles packages, mounts, copies, and AI CLI
curl -fsSL https://raw.githubusercontent.com/BenjaminBenetti/Teeleport/main/install.sh | bash
echo "dotfiles setup complete!"Path to the dotfile repo root. All copy source paths resolve relative to this. Supports ~. Optional — defaults to . (current working directory), which is correct in most cases since devcontainers run your install script from the cloned dotfile repo.
| Field | Required | Default | Description |
|---|---|---|---|
host |
Yes | -- | Remote hostname or IP |
user |
No | Current user | SSH username |
port |
No | 22 |
SSH port |
identity_file |
No | -- | Path to SSH key (supports ~). Omit to use SSH agent forwarding (recommended). |
| Field | Required | Default | Description |
|---|---|---|---|
uid |
No | 1000 |
UID to map mounted files to |
gid |
No | 1000 |
GID to map mounted files to |
Settings for the rsync background daemon. Only used when backend: rsync entries exist.
| Field | Required | Default | Description |
|---|---|---|---|
interval |
No | 30 |
Seconds between bidirectional sync cycles |
| Field | Required | Default | Description |
|---|---|---|---|
name |
Yes | -- | Human-readable label for logs |
source |
Yes* | -- | Absolute path on the remote host |
target |
Yes* | -- | Local mount point (supports ~) |
type |
No | directory |
directory or file. For sshfs, file mounts symlink a single file from a staged parent directory mount. For rsync, files are synced directly. |
backend |
No | sshfs |
Mount backend: sshfs (FUSE mount) or rsync (periodic bidirectional sync) |
preset |
No | -- | Use a predefined mount preset instead of source/target/backend (e.g. claude) |
force_mount |
No | false |
If true, unmounts conflicting mounts (wrong filesystem type) before remounting with the configured backend. |
file.default_content |
No | -- | Content to initialize the file with on the remote if it doesn't exist (only for type: file) |
| Field | Required | Description |
|---|---|---|
name |
Yes | Label for logs and sentinel markers |
source |
Yes | Path relative to dotfile_repo |
target |
Yes | Destination path (supports ~) |
mode |
Yes | replace or append |
A flat list of package names. Teeleport auto-detects apt, dnf, or pacman.
A list of AI CLI tools to install and launch. Each entry has these fields:
| Field | Required | Description |
|---|---|---|
tool |
Yes | claude-code, codex, gemini-cli, or copilot |
startup_prompt |
No | Inline prompt string (mutually exclusive with startup_prompt_file) |
startup_prompt_file |
No | Path to prompt file, relative to dotfile_repo |
teeleport [flags]
--config <path> Path to config file (overrides auto-discovery)
--version Print version and exit
teeleport rsync [flags]
--config <path> Path to config file (overrides auto-discovery)
Runs the rsync sync daemon in the foreground. Normally started
automatically by the main teeleport command and the shell hook.
Teeleport auto-discovers the config file in this order:
--configflagTEELEPORT_CONFIGenvironment variable./teeleport.config(current working directory)~/dotfiles/teeleport.config~/.dotfiles/teeleport.config
# Build for current platform
go build -o teeleport ./cmd/teeleport
# Cross-compile static binaries
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o teeleport-linux-amd64 ./cmd/teeleport
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o teeleport-linux-arm64 ./cmd/teeleportGPL-3.0