vault-link/docs/guide/cli-client.md
2025-11-30 15:24:52 +00:00

10 KiB

CLI Client

Sync vaults without Obsidian. Works on servers, automation, backups, headless systems.

Installation

Pull the latest image:

docker pull ghcr.io/schmelczer/vault-link-cli:latest

npm

Install globally:

npm install -g @schmelczer/local-client-cli

Verify installation:

vaultlink --version

From Source

Build from the repository:

git clone https://github.com/schmelczer/vault-link.git
cd vault-link/frontend/local-client-cli
npm install
npm run build
node dist/cli.js --help

Usage

Basic Usage

vaultlink \
  --local-path /path/to/vault \
  --remote-uri wss://sync.example.com \
  --token your-auth-token \
  --vault-name default

Docker Usage

docker run -v /path/to/vault:/vault \
  ghcr.io/schmelczer/vault-link-cli:latest \
  -l /vault \
  -r wss://sync.example.com \
  -t your-auth-token \
  -v default

Docker Compose

Create docker-compose.yml:

services:
    vaultlink-cli:
        image: ghcr.io/schmelczer/vault-link-cli:latest
        restart: unless-stopped
        volumes:
            - ./vault:/vault
        command:
            - "-l"
            - "/vault"
            - "-r"
            - "wss://sync.example.com"
            - "-t"
            - "your-token"
            - "-v"
            - "default"

Start the client:

docker compose up -d

Configuration Options

Required Arguments

Argument Short Description Example
--local-path -l Local directory to sync /vault
--remote-uri -r Server WebSocket URI wss://sync.example.com
--token -t Authentication token abc123...
--vault-name -v Vault name on server default

Optional Arguments

Argument Default Description
--sync-concurrency 1 Concurrent file operations
--max-file-size-mb 10 Max file size in MB
--ignore-pattern - Glob pattern to ignore (repeatable)
--websocket-retry-interval-ms 3500 Reconnection interval
--log-level INFO Log level: DEBUG, INFO, WARNING, ERROR

Environment Variables

Alternative to command-line arguments:

export VAULTLINK_LOCAL_PATH="/vault"
export VAULTLINK_REMOTE_URI="wss://sync.example.com"
export VAULTLINK_TOKEN="your-token"
export VAULTLINK_VAULT_NAME="default"

vaultlink

Examples

Basic Sync

Sync a local directory to the server:

vaultlink \
  -l ./my-notes \
  -r wss://sync.example.com \
  -t my-secure-token \
  -v personal

With Ignore Patterns

Exclude specific files or directories:

vaultlink \
  -l ./vault \
  -r wss://sync.example.com \
  -t token123 \
  -v default \
  --ignore-pattern "*.tmp" \
  --ignore-pattern ".DS_Store" \
  --ignore-pattern "node_modules/**"

Debug Logging

Enable verbose logging:

vaultlink \
  -l ./vault \
  -r wss://sync.example.com \
  -t token123 \
  -v default \
  --log-level DEBUG

High Concurrency

Faster initial sync:

vaultlink \
  -l ./vault \
  -r wss://sync.example.com \
  -t token123 \
  -v default \
  --sync-concurrency 5

Large Files

Allow larger file uploads:

vaultlink \
  -l ./vault \
  -r wss://sync.example.com \
  -t token123 \
  -v default \
  --max-file-size-mb 50

Docker Deployment

Long-Running Sync

Run as a daemon for continuous synchronization:

docker run -d \
  --name vaultlink-sync \
  --restart unless-stopped \
  -v $(pwd)/vault:/vault \
  ghcr.io/schmelczer/vault-link-cli:latest \
  -l /vault \
  -r wss://sync.example.com \
  -t your-token \
  -v default

Monitor logs:

docker logs -f vaultlink-sync

Health Monitoring

The Docker image includes built-in health checks:

# Check health status
docker ps

# View detailed health info
docker inspect --format='{{json .State.Health}}' vaultlink-sync | jq

Health check verifies:

  • Health file exists
  • Status updated within last 30 seconds
  • WebSocket connection is active

Configure custom health check:

services:
    vaultlink-cli:
        image: ghcr.io/schmelczer/vault-link-cli:latest
        healthcheck:
            test: ["CMD", "node", "/app/healthcheck.js"]
            interval: 15s
            timeout: 5s
            retries: 5
            start_period: 20s

Read-Only Vault

Mount vault as read-only to prevent local changes:

docker run -d \
  -v $(pwd)/vault:/vault:ro \
  ghcr.io/schmelczer/vault-link-cli:latest \
  -l /vault \
  -r wss://sync.example.com \
  -t token \
  -v default

::: warning The CLI needs write access to create .vaultlink metadata directory. Mount as read-write or provide a separate writeable directory. :::

How It Works

Initial Sync

On startup:

  1. Creates .vaultlink/ directory for metadata
  2. Scans local filesystem
  3. Uploads all local files to server
  4. Downloads files from server not present locally
  5. Resolves conflicts using operational transformation

Real-Time Synchronization

After initial sync:

  1. Watches filesystem for changes using fs.watch
  2. Uploads changed files immediately
  3. Receives real-time updates from server via WebSocket
  4. Handles bidirectional sync automatically

Graceful Shutdown

On SIGINT (Ctrl+C) or SIGTERM:

  1. Completes pending uploads
  2. Closes WebSocket connection cleanly
  3. Flushes metadata to disk
  4. Exits gracefully

Use Cases

Automated Backups

Continuously backup vaults to a remote server:

docker run -d \
  --name vault-backup \
  -v /important/notes:/vault:ro \
  ghcr.io/schmelczer/vault-link-cli:latest \
  -l /vault -r wss://backup.example.com -t backup-token -v backups

CI/CD Documentation

Sync documentation in automated pipelines:

# In your CI pipeline
docker run \
  -v $(pwd)/docs:/vault \
  ghcr.io/schmelczer/vault-link-cli:latest \
  -l /vault -r wss://docs.example.com -t ci-token -v prod-docs

Multi-Location Sync

Sync between different geographic locations:

# Location A
vaultlink -l /data/vault -r wss://hub.example.com -t token -v shared

# Location B
vaultlink -l /backup/vault -r wss://hub.example.com -t token -v shared

Development Environment

Keep documentation in sync across dev environments:

# In docker-compose.yml for your dev stack
services:
  docs-sync:
    image: ghcr.io/schmelczer/vault-link-cli:latest
    volumes:
      - ./docs:/vault
    command: ["-l", "/vault", "-r", "wss://docs-server", "-t", "dev-token", "-v", "dev"]

Troubleshooting

Client won't connect

Check server accessibility:

curl https://sync.example.com/vaults/test/ping

Verify WebSocket protocol:

  • Use ws:// for HTTP servers
  • Use wss:// for HTTPS servers

Check authentication:

  • Token must match server config
  • User must have access to the vault

Permission errors

Docker volume permissions:

# Ensure directory is writable
chmod 755 /path/to/vault

# Check Docker user ID
docker run --rm ghcr.io/schmelczer/vault-link-cli:latest id

SELinux issues:

# Add :z flag to volume mount
docker run -v /path/to/vault:/vault:z ...

Files not syncing

Check ignore patterns:

  • View logs to see which files are skipped
  • Ensure patterns don't match unintentionally

File size limits:

  • Check --max-file-size-mb setting
  • Large files are skipped with a warning

Check metadata:

# View sync metadata
cat /path/to/vault/.vaultlink/metadata.json

High memory usage

Reduce concurrency:

--sync-concurrency 1

Limit file sizes:

--max-file-size-mb 5

Check vault size:

  • Very large vaults may need more resources
  • Consider splitting into multiple vaults

Connection keeps dropping

Increase retry interval:

--websocket-retry-interval-ms 5000

Check network stability:

# Monitor connection
docker logs -f vaultlink-sync | grep -i websocket

Server timeout settings:

  • Verify reverse proxy WebSocket timeout
  • Check server response_timeout_seconds

Advanced Usage

Custom Healthcheck Script

Create your own health monitoring:

#!/bin/bash
HEALTH_FILE="/tmp/vaultlink-health.json"

if [ ! -f "$HEALTH_FILE" ]; then
    exit 1
fi

# Check file is recent (within 60 seconds)
if [ $(( $(date +%s) - $(stat -c %Y "$HEALTH_FILE") )) -gt 60 ]; then
    exit 1
fi

# Check WebSocket is connected
if ! jq -e '.connected == true' "$HEALTH_FILE" > /dev/null; then
    exit 1
fi

exit 0

Automated Recovery

Restart on failure with exponential backoff:

#!/bin/bash
RETRY_DELAY=5

while true; do
    vaultlink -l /vault -r wss://server -t token -v default

    echo "Client exited, restarting in ${RETRY_DELAY}s..."
    sleep $RETRY_DELAY

    # Exponential backoff up to 5 minutes
    RETRY_DELAY=$((RETRY_DELAY * 2))
    if [ $RETRY_DELAY -gt 300 ]; then
        RETRY_DELAY=300
    fi
done

Integration with systemd

Create /etc/systemd/system/vaultlink-cli.service:

[Unit]
Description=VaultLink CLI Sync
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
Restart=always
RestartSec=10
Environment="VAULTLINK_LOCAL_PATH=/data/vault"
Environment="VAULTLINK_REMOTE_URI=wss://sync.example.com"
Environment="VAULTLINK_TOKEN=your-token"
Environment="VAULTLINK_VAULT_NAME=default"
ExecStart=/usr/local/bin/vaultlink

[Install]
WantedBy=multi-user.target

Enable and start:

sudo systemctl daemon-reload
sudo systemctl enable vaultlink-cli
sudo systemctl start vaultlink-cli

Next Steps