drift

command module
v0.1.2-alpha Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 19, 2026 License: MIT Imports: 1 Imported by: 0

README

drift

A terminal TUI for browsing, diffing, and syncing files with remote hosts — think PHPStorm's "Browse Remote Host" and "Sync with Deployed To", but in your terminal.

Supports SFTP/SSH and FTP targets. Runs on Linux and macOS.

drift screenshot

[!WARNING] Alpha: drift is in an early public stage. Expect rough edges, incomplete polish, and breaking changes between releases.


Features

  • File browser with multi-select (Space) and recursive directory marking
  • Side-by-side diff view for local vs. remote files
  • Per-file sync direction control: upload ↑, download ↓, delete local ✗, delete remote ✗, or skip —
  • Bulk sync direction toggle (A key cycles all files at once)
  • Auto pre-selection of sync direction based on file modification time
  • Sync current file (s) or all marked files (S) in one keystroke
  • Per-host path mappings (like PHPStorm's Deployment Mappings tab)
  • Host manager: create, edit, delete, and test connections
  • Global config (~/.config/drift/config.toml) + project-level config (.drift/config.toml)
  • Skips .git, node_modules, .idea, and other irrelevant directories automatically

Installation

From source (requires Go 1.25+)
git clone https://github.com/WariKoda/drift.git
cd drift
make install

This builds the binary and installs it to ~/.local/bin/drift.

Directly with Go
go install github.com/WariKoda/drift@latest
Update after code changes
make update

Usage

# Start in the current directory
drift

# Show version
drift version

Navigate to any file or directory, press Space to mark it, then s to open the sync target picker.

Typical workflow
  1. Run drift in your project directory
  2. Mark one or more files/directories with Space
  3. Press s and choose a host
  4. Review diffs and suggested sync directions
  5. Sync the current file with s or all files with S

Key Bindings

File Browser
Key Action
j / k or / Navigate
Space Mark / unmark file or directory
Enter Open directory
Backspace Go up one level
s Sync marked files (opens host selector)
h Open host manager
q / Esc Quit
Diff View
Key Action
j / k Navigate file list
J / K Scroll diff content
Space Cycle sync direction for current file
A Cycle sync direction for all files
s Sync current file
S Sync all files
r Refresh diffs
Esc Back to browser
Host Manager
Key Action
n New host
e / Enter Edit host
d Delete host
t Test connection
Esc Back

Configuration

Global config: ~/.config/drift/config.toml
[defaults]
user = "deploy"

[[hosts]]
name       = "prod"
hostname   = "example.com"
port       = 22
user       = "deploy"
root_path  = "/var/www/html"
protocol   = "sftp"

  [hosts.auth]
  type     = "keyfile"
  key_file = "~/.ssh/id_ed25519"
Project config: .drift/config.toml

Place this file in your project root. drift walks up from the working directory to find it.

[[hosts]]
name      = "staging"
hostname  = "shopdev.example.com"
port      = 21
user      = "webuser"
root_path = "/var/www"
protocol  = "ftp"

  [hosts.auth]
  type     = "password"
  password = "$DEPLOY_PASSWORD"

  [[hosts.mappings]]
  local  = "plugins/plugin1"
  remote = "html/custom/plugins/plugin1"

  [[hosts.mappings]]
  local  = "plugins/plugin2"
  remote = "html/custom/plugins/plugin2"
Path Mappings

local paths are relative to the project root. remote paths are relative to the host's root_path.

When effective mappings are configured, only files that fall under a mapping rule can be synced. Files outside all mappings are excluded. Without mappings, all files sync relative to root_path.

Auth types
Type Fields
keyfile key_file, passphrase (optional)
password password (supports $ENV_VAR)
agent none — uses SSH agent

Project Structure

internal/
  config/       config types, loader, writer
  diff/         diff engine, result types, renderer
  ftp/          FTP client (jlaffaye/ftp)
  fs/           local file walker, directory reader
  pathmap/      local ↔ remote path resolution with mapping rules
  remote/       protocol-agnostic Client interface
  sftp/         SFTP/SSH client
  sync/         sync plan types
  tui/
    app.go      root Bubble Tea model, screen routing
    browser/    file browser screen
    diffview/   diff + sync screen
    hostform/   host create/edit form (incl. mapping manager)
    hostmanager/host list screen
    hostselector/sync target picker
    styles.go   shared lipgloss styles

Development

go test ./...
go vet ./...
go build ./...
Local install
make install
Versioned build
go build -ldflags "-X github.com/WariKoda/drift/cmd.Version=v0.1.0" -o drift .

Contributing

Issues and pull requests are welcome.

For development notes and contribution workflow, see CONTRIBUTING.md.


License

MIT — see LICENSE.

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
internal
config
Package config defines drift's configuration types and loading logic.
Package config defines drift's configuration types and loading logic.
diff
Package diff compares local and remote files and produces structured diff results.
Package diff compares local and remote files and produces structured diff results.
fs
Package fs defines the shared FileEntry type used for both local and remote files.
Package fs defines the shared FileEntry type used for both local and remote files.
ftp
Package ftp provides an FTP client that implements remote.Client.
Package ftp provides an FTP client that implements remote.Client.
pathmap
Package pathmap resolves local filesystem paths to remote paths and vice versa using the Mapping rules from the project config.
Package pathmap resolves local filesystem paths to remote paths and vice versa using the Mapping rules from the project config.
remote
Package remote defines the protocol-agnostic interface for remote file operations and provides a factory that returns the right implementation (SFTP or FTP) based on host.Protocol.
Package remote defines the protocol-agnostic interface for remote file operations and provides a factory that returns the right implementation (SFTP or FTP) based on host.Protocol.
sftp
Package sftp provides an SFTP client that wraps SSH connection + SFTP session.
Package sftp provides an SFTP client that wraps SSH connection + SFTP session.
ssh
Package ssh provides SSH authentication helpers.
Package ssh provides SSH authentication helpers.
styles
Package styles defines all lipgloss colors and styles used across drift's TUI.
Package styles defines all lipgloss colors and styles used across drift's TUI.
sync
Package sync handles building and executing file sync plans.
Package sync handles building and executing file sync plans.
tui
Package tui re-exports styles for convenience within the tui package itself.
Package tui re-exports styles for convenience within the tui package itself.
tui/browser
Package browser implements the yazi-like local file browser TUI component.
Package browser implements the yazi-like local file browser TUI component.
tui/diffview
Package diffview implements the split-pane local/remote diff screen.
Package diffview implements the split-pane local/remote diff screen.
tui/hostform
Package hostform implements the create/edit host form screen.
Package hostform implements the create/edit host form screen.
tui/hostmanager
Package hostmanager implements the host list / CRUD screen.
Package hostmanager implements the host list / CRUD screen.
tui/hostselector
Package hostselector implements the host picker modal shown when the user presses [s].
Package hostselector implements the host picker modal shown when the user presses [s].
tui/statusbar
Package statusbar renders the persistent one-line status bar at the bottom.
Package statusbar renders the persistent one-line status bar at the bottom.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL