WARNING: EARLY PROTOTYPE — EXPECT BREAKING CHANGES.
relocal is under active development. Commands, config format, and sync behavior may change without notice between commits. If you're using it, watch the changelog until this notice is removed.
Bugs or misconfiguration can delete local files. There are safety checks but the tool has not been battle-tested.
relocal runs AI coding agents (Claude Code, Codex) on a remote Ubuntu host while keeping your local repo in sync. Your
code is pushed to the remote at session start, and a background loop continuously pulls remote changes back to local
while the agent works. You review output locally in your editor while the session runs in your terminal. Local edits
during a session are not synced to the remote — use relocal sync push between sessions to send local changes.
relocal runs agents unsandboxed on the remote (Claude with --dangerously-skip-permissions, Codex with --yolo) and
syncs your repo with rsync --delete, including the entire .git/ directory. Your code is pushed at session start, and
a background loop continuously pulls remote changes to local while the session runs.
This design is intended to provide enough isolation to run agents unsandboxed in many setups, but there are real caveats and exposure paths you should treat as in-scope risk.
If your remote is localhost (or the same machine/account as your workstation), there is no real isolation. In that
setup, remote execution is effectively local unsandboxed execution.
Because .git/ is synced both directions, a compromised or misused remote can affect local host behavior after a pull.
Important examples:
.git/hooks/*can be modified remotely and later execute locally when you run Git commands..git/configcan be modified remotely (for examplecore.hooksPath,sshCommand, credential helpers, remotes, signing programs), which can trigger local command execution or credential leakage.- Full Git metadata is exposed remotely: history, reflogs, stashes, and unreachable objects may contain sensitive data you thought was removed.
rsync --deleteover.git/can propagate ref/config/state tampering back to local even when repository object integrity checks pass.
git fsck checks in relocal reduce accidental destructive pulls, but they do not make remote-sourced .git content
trustworthy.
Operational expectations:
- Treat the remote host as disposable sandbox infrastructure, not a trusted long-lived environment.
- Prefer a dedicated throwaway VM/user and a dedicated local clone for relocal sessions.
- Do not authenticate to external services from the remote sandbox (GitHub CLI, cloud CLIs, package registries, databases, internal systems, etc.).
- Agent authentication on the remote (Claude login, Codex API key) is the only expected exception needed for relocal to function.
- Keep sensitive credentials and privileged operations on your local machine.
- If credentials are entered on the remote, rotate/revoke them promptly.
Local machine:
sshrsync- Rust toolchain (if installing with
cargo install --path .)
Remote machine:
- Ubuntu host reachable over SSH
# Run on the remote Ubuntu box as root.
# Replace values first:
NEW_USER="alice"
SSH_PUBKEY="ssh-ed25519 AAAA... yourname@laptop"
# 1) Create user
adduser --disabled-password --gecos "" "$NEW_USER"
usermod -aG sudo "$NEW_USER"
# 2) Install SSH key for that user
install -d -m 700 -o "$NEW_USER" -g "$NEW_USER" "/home/$NEW_USER/.ssh"
printf '%s\n' "$SSH_PUBKEY" > "/home/$NEW_USER/.ssh/authorized_keys"
chown "$NEW_USER:$NEW_USER" "/home/$NEW_USER/.ssh/authorized_keys"
chmod 600 "/home/$NEW_USER/.ssh/authorized_keys"
# 3) Grant passwordless sudo
printf '%s ALL=(ALL) NOPASSWD:ALL\n' "$NEW_USER" > "/etc/sudoers.d/90-$NEW_USER-relocal"
chmod 440 "/etc/sudoers.d/90-$NEW_USER-relocal"
visudo -cf "/etc/sudoers.d/90-$NEW_USER-relocal"
# 4) Verify passwordless sudo works
su - "$NEW_USER" -c 'sudo -n true && echo "passwordless sudo OK"'# Install relocal locally
cargo install --path .
# In your project directory, create a config file
cd ~/my-project
relocal init
# Follow the prompts and set remote to user@host
grep -qxF 'relocal.toml' .gitignore 2>/dev/null || echo 'relocal.toml' >> .gitignore
# Install dependencies on the remote (Rust, Node, Claude Code, Codex, etc.)
relocal remote install
# Start a session (run one or both concurrently)
relocal claude # Claude Code
relocal codex # CodexOnce a session is running, a background loop keeps local in sync with remote changes automatically. Multiple tools can run against the same session simultaneously — each gets its own interactive SSH session while sharing the sync loop.
Both Claude and Codex authenticate during relocal remote install. Codex uses a device code flow (prints a URL and
one-time code to enter in any browser).
relocal ssh [session-name] # open a shell in the remote session directory
relocal sync pull [session-name] # fetch remote changes to local
relocal sync push [session-name] # push local changes to remote
relocal status [session-name] # show session info
relocal log [session-name] # tail the daemon log for a session
relocal list # list sessions on the remote
relocal destroy [session-name] # remove one session's remote directory
relocal remote nuke # wipe all relocal state on the remotecargo build
cargo run -- --helpUnit tests (no remote needed):
cargo testIntegration tests require SSH access to a remote host (localhost works):
RELOCAL_TEST_REMOTE=$USER@localhost cargo test -- --ignored --test-threads=1The --test-threads=1 flag is required because integration tests share remote state.
See SPEC.md for the full design and architecture details.