Skip to content

alexmaze/clink

Repository files navigation

CLINK

Reliable dotfile and configuration deployment for local machines and SSH targets.

中文文档

Go Platform Config

clink describes every destination in one config.yaml, turns that file into an execution plan, previews the writes, captures backups, and then deploys through symlinks, local copies, or SSH uploads. It is built for people who want reproducible dotfiles and small configuration rollouts without giving up inspection and restore.

Describe every target once. Preview every write. Restore when needed.

CLINK web console

How It Works

flowchart LR
  config["config.yaml"] --> plan["Plan"]
  plan --> backup["Backup current targets"]
  backup --> deploy{"Deploy"}
  deploy --> symlink["symlink"]
  deploy --> copy["copy"]
  deploy --> ssh["ssh upload"]
  symlink --> check["check"]
  copy --> check
  ssh --> check
  backup --> restore["restore"]
Loading

Why CLINK

  • One inventory for local and remote targets: manage dotfiles, app config, and server files from the same YAML.
  • Plan before writing: use dry-run output to inspect exactly what clink is going to do.
  • Backups by default: every apply run records previous target state under ~/.clink/<timestamp>/.
  • Drift checks: verify symlink targets, copied file hashes, and SSH target presence before or after deployment.
  • Local web console: inspect status, edit config, preview writes, diff local files, and restore backups from 127.0.0.1.

Installation

curl -fsSL https://raw.githubusercontent.com/alexmaze/clink/main/scripts/install.sh | sh

Install a specific release:

curl -fsSL https://raw.githubusercontent.com/alexmaze/clink/main/scripts/install.sh | sh -s -- v1.2.1

By default, the installer writes to ~/.local/bin. To choose another directory:

curl -fsSL https://raw.githubusercontent.com/alexmaze/clink/main/scripts/install.sh | CLINK_INSTALL_DIR=/usr/local/bin sh

Other options:

go install github.com/alexmaze/clink@latest
make build

Quick Start

Create a config.yaml:

mode: symlink

rules:
  - name: shell
    items:
      - src: ./dotfiles/.zshrc
        dest: ~/.zshrc

Preview the plan:

clink apply -c ./config.yaml --dry-run

Apply it:

clink apply -c ./config.yaml

Validate the current state later:

clink check -c ./config.yaml

Restore from the latest backup in non-interactive mode:

clink restore --non-interactive

Configuration

config.yaml can mix local symlinks, local copies, and SSH uploads:

mode: symlink

hooks:
  pre: echo "start apply"
  post: echo "finish apply"

vars:
  APP_HOME: /opt/myapp

ssh_servers:
  prod:
    host: 192.168.1.10
    port: 22
    user: root
    key: ~/.ssh/id_rsa

rules:
  - name: shell
    items:
      - src: ./dotfiles/.zshrc
        dest: ~/.zshrc

  - name: app-config
    mode: copy
    items:
      - src: ./app/config.yaml
        dest: ${APP_HOME}/config.yaml

  - name: remote-nginx
    mode: ssh
    ssh: prod
    items:
      - src: ./nginx/nginx.conf
        dest: /etc/nginx/nginx.conf

Configuration rules:

  • Top-level mode is the default distribution mode. If omitted, it defaults to symlink.
  • rules[].mode can override the top-level default for one rule.
  • Local src and dest support relative paths, absolute paths, and ~/.
  • SSH mode requires an absolute remote dest.
  • Variables use ${VAR_NAME} syntax.
  • If an SSH server has neither key nor password, the CLI prompts for a password at runtime.

Core Commands

Command Purpose
clink apply -c <config.yaml> Build a plan, back up existing targets, and deploy configured items.
clink check -c <config.yaml> Validate current target state against the config.
clink restore --backup <id-or-path> Restore targets from a backup manifest.
clink add -c <config.yaml> <source> Bring an existing local file under clink management.
clink web -c <config.yaml> Open the local browser console for status, config, and backups.
clink version Print the current version.

Common flags:

  • -c, --config: specify the config file path.
  • -r, --rule: filter rules by name or 1-based index; can be repeated.
  • -d, --dry-run: generate the plan without executing it.
  • -y, --yes: skip confirmation.
  • --non-interactive: disable interactive input.
  • --output text|json: choose text or JSON output.

Safety Model

apply always plans from the config before execution. During execution, it captures the previous destination state first:

  • Local modes back up the original target to ~/.clink/<timestamp>/payload/....
  • SSH mode downloads the original remote file into the same backup directory first.
  • Every run writes config.snapshot.yaml, manifest.json, and payload/.

Example backup layout:

~/.clink/
  20260406_120000/
    config.snapshot.yaml
    manifest.json
    payload/
      shell/
        home/alex/.zshrc
      remote-nginx/
        etc/nginx/nginx.conf

manifest.json records the rule name, mode, source, destination, backup file path, SSH server, path kind, and backup content hash for each backed-up target.

Restore behavior:

  • clink restore opens an interactive backup picker when --backup is omitted.
  • clink restore --non-interactive selects the latest backup when --backup is omitted.
  • Local restore writes through a temporary path and then atomically replaces the target.
  • SSH restore reuses connections grouped by server.
  • Backups from older versions are not supported; a backup without manifest.json cannot be restored.

Web Console

Run:

clink web -c ./config.yaml

The console listens on 127.0.0.1:19877 by default and uses the same config.yaml as the CLI. It can:

  • show status for symlink, copy, and ssh rules;
  • preview and execute linking for all items or a single item;
  • show local diffs for symlink and copy items;
  • list backups, preview restore contents, and execute restore;
  • edit config through a structured form or raw YAML with validation before saving.

SSH operations in the web UI require key or password in ssh_servers; unlike the CLI, the web UI does not prompt for missing SSH passwords.

Security note: the web UI can modify the config file and write to configured destinations. Keep the default localhost binding unless you explicitly trust the network where it is exposed.

Development

make build
make test
make build-all
make release
  • make build creates the local ./clink binary and injects version metadata.
  • make test runs go test github.com/alexmaze/clink/....
  • make build-all builds Linux and macOS release artifacts into dist/.
  • make release asks for a release version, updates release metadata, commits it, then creates and pushes a v* tag to trigger the GitHub Actions release workflow.
  • ./run_tests.sh runs the full test suite in Docker or Podman and prints a coverage summary.

Compatibility

This version has been fully refactored with these constraints:

  • Linux and macOS only.
  • Unified subcommand-based CLI.
  • Runtime output and interaction are in English.
  • Legacy command entrypoints are not supported.
  • Old backup directory layouts are not supported.

When upgrading from an older version, generate new backups and use the new command structure.

About

Centralized dotfile manager — deploy configs via symlink, copy, or SSH.

Resources

Stars

4 stars

Watchers

1 watching

Forks

Packages

 
 
 

Contributors