A local-first remote development platform. Work with remote files and commands as if they were local.

Note: This project is still in alpha development. Breaking changes may be made. Issues and contributions are welcome!
Supported Platforms
| Local (client) | Remote (target) |
|---|
| macOS | yes | |
| Linux | yes | yes |
Install
curl --proto '=https' --tlsv1.2 -sSf https://graft.run/install.sh | sh
Options: --install-dir <dir>, --version <tag>
Alternative Installation methods:
Nix Flakes
# In your flake inputs add graft:
inputs = {
# ...
graft.url = "github:edaniels/graft";
# ...
}
# In your configuration add graft to your systemPackages:
# ${system} should be defined as your current platform. Ex: "x86_64-linux" or "aarch64-darwin".
environment.systemPackages = [
# ...
graft.packages.${system}.default
# ...
]
Quick Start
1. Activate shell integration (add to your shell rc file):
# bash: ~/.bashrc, zsh: ~/.zshrc
eval "$(graft activate zsh)"
This lets graft track your working directory so commands like run, shell, sync, and forward can automatically detect which connection to use.
2. Start the daemon:
graft daemon service install # auto-start on login
The daemon runs in the background and manages your remote connections.
3. Connect to a remote machine:
graft connect . user@host:~/project --sync
This connects your current directory (.) to ~/project on the remote host, with --sync to enable bidirectional file synchronization. You can also use graft init to save connection settings to a graft.yaml file for repeated use.
4. Use it from within the connected directory:
graft run make build # run a command remotely
graft shell # open a remote shell
graft sync # sync files to the remote
graft forward go make # forward commands to the remote
All of these commands detect the connection from your current directory. You can also specify a connection explicitly with --to <connection>, or pin a connection to your shell session with graft use <connection>.
Use with Claude Code
If you use Claude Code, install the graft plugin so Claude knows how to use graft for remote development. It covers running commands, syncing files, forwarding ports, and diagnosing connection issues:
/plugin marketplace add edaniels/graft
/plugin install graft@graft
The plugin auto-triggers when you're working in a graft-managed directory, so you can keep using Claude Code normally; it will reach for graft run, graft sync, and graft status instead of raw ssh/scp where appropriate.
Commands
| Command | Description |
|---|
connect | Connect to a remote machine (SSH or Docker) |
disconnect | Disconnect from a remote connection |
run | Run a command on the remote |
shell | Open a remote shell |
sync | Sync files to the remote |
forward | Forward local commands to the remote |
use | Pin a connection to the current shell session |
status | Show connection status |
doctor | Check environment setup and diagnose issues |
init | Generate a graft.yaml configuration file for future graft connects |
Connection selection
When you run a command like graft run or graft shell, graft needs to know which connection to use. It follows this hierarchy:
- Explicit -
--to <connection> on the command line
- Session pin - set with
graft use <connection>, applies to the current shell
- CWD-based - automatically detected from your working directory based on each connection's local root
graft use is useful when you have multiple connections and want to lock your shell to a specific one: