Skip to content

CruxExperts/kilo-sync

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

9 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ”„ kilo-sync

Encrypt and sync your Kilo CLI 1.x profiles across machines through a private git repository.

kilo-sync packs your Kilo configuration files into a compressed tarball, encrypts it with a passphrase (AES-256-GCM or age), commits the ciphertext to a private git repo, and lets you pull and apply it on any other machine β€” with a full backup of whatever it overwrites.


πŸ“š Table of contents


βš™οΈ How it works

graph LR
    subgraph Machine A
        A[~/.config/kilo/kilo.jsonc] -->|kilo-sync export| C((Encrypted .tar.bin))
        B[~/.config/kilo/rules/] -->|kilo-sync export| C
    end

    subgraph Private Git Repo
        C --> D[Commit & Push]
    end

    subgraph Machine B
        D -->|kilo-sync import --pull| E((Review Staging))
        E -->|kilo-sync apply --latest| F[Restores all files]
    end
Loading

πŸ“€ Export collects your Kilo files β†’ tars them β†’ encrypts with your passphrase β†’ writes profiles/<name>.tar.kilosync.bin + profiles/<name>.meta.json to your local clone β†’ optionally commits and pushes.

πŸ“₯ Import pulls (optionally) β†’ decrypts β†’ extracts into ~/.kilo/import-staging/<timestamp>/ for your review.

βœ… Apply copies files from staging to their live locations, backing up any existing files first under ~/.kilo/backups/<timestamp>/.


πŸ“‹ What gets synced

The following files are collected automatically (paths are relative to $HOME):

Archive path Live location Description
πŸ“„ config/kilo/kilo.jsonc ~/.config/kilo/kilo.jsonc Main Kilo config
πŸ“„ config/kilo/opencode.json ~/.config/kilo/opencode.json OpenCode config
πŸ“„ config/kilo/opencode.jsonc ~/.config/kilo/opencode.jsonc OpenCode config (JSONC)
πŸ“ config/kilo/rules/** ~/.config/kilo/rules/ All rule files
πŸ“ config/kilo/skills/** ~/.config/kilo/skills/ All skill files
πŸ”‘ share/kilo/auth.json ~/.local/share/kilo/auth.json Auth tokens
πŸ“ kilo-home/instructions.md ~/.kilo/instructions.md Global instructions
βš™οΈ kilo-home/.env ~/.kilo/.env Environment overrides
βž• include/** ~/... Any extras from paths.include

Note

node_modules/ is always skipped. auth.json is optional β€” a warning is printed if it is missing, but the export still succeeds.

Additional files can be added via paths.include globs; files can be removed from the bundle with paths.exclude patterns (see Configuration).


πŸ“₯ Install

The installer creates a self-contained Python venv at ~/.local/share/kilo-sync-venv and symlinks the kilo-sync binary into ~/.local/bin. This approach works on Ubuntu 24.04, Debian 12, and macOS without requiring sudo, pip, or pipx.

Step 1 β€” Server prerequisite (one-time, needs sudo)

On a fresh Ubuntu or Debian server, python3-venv may not be present:

sudo apt-get install -y python3-venv
# Or use the bundled helper:
sudo bash scripts/ensure-python.sh

Tip

Skip this step on macOS or any machine where python3 -m venv already works.

Step 2 β€” Install (no sudo needed)

🌐 Public repo β€” tracks latest main branch:

curl -fsSL "https://raw.githubusercontent.com/cptnfren/kilo-sync/main/scripts/install.sh" | bash

πŸ”’ Private repo β€” via SSH (no wheel required):

KILO_SYNC_SOURCE=ssh bash <(curl -fsSL "https://raw.githubusercontent.com/cptnfren/kilo-sync/main/scripts/install.sh")

πŸ”„ Upgrade in place β€” re-run the same curl | bash command. The venv is updated and the symlink is refreshed.

πŸ—‘οΈ Uninstall:

rm -rf ~/.local/share/kilo-sync-venv
rm ~/.local/bin/kilo-sync

See docs/PUBLISHING.md for Ansible, cloud-init, and full install reference.


πŸ› οΈ Configuration

Copy the example config and edit it:

cp kilo-sync.yaml.example ~/.kilo/kilo-sync.yaml

Important

Two separate repos: kilo-sync uses two distinct git repositories:

  1. 🧰 Tool repo (cptnfren/kilo-sync, public) β€” this repo, containing the code and install.sh.
  2. πŸ—„οΈ Data repo (your own private repo, e.g. YOUR_USERNAME/kilo-sync-data) β€” where your encrypted profile blobs are stored. You create this repo yourself; it can be named anything.

🎯 Minimal config (~/.kilo/kilo-sync.yaml):

local_clone: ~/repos/kilo-sync-data   # path to YOUR private data repo
profile: default                       # profile name (letters, digits, . _ -)

πŸ”§ Full config with all options:

# Path to YOUR private data repo (not the kilo-sync tool repo)
local_clone: ~/repos/kilo-sync-data
profile: default

# Optional: informational only, records where your data repo lives
github_repo: YOUR_USERNAME/kilo-sync-data

# Encryption backend: omit for auto (age if on PATH, else python AES-GCM)
# encryption: python    # force built-in AES-256-GCM
# encryption: age       # force age (must be on PATH)

# How many import-staging directories to keep (default: 3)
keep_staging: 3

# Maximum tarball size before warning (default: 50 MB)
max_tar_bytes: 52428800

# Include the kilo-sync source tree itself in the bundle (default: false)
include_kilo_sync: false

# Extra files/directories to include (globs relative to $HOME)
paths:
  include:
    - .gitconfig
    - .ssh/config
    - .config/starship.toml
  exclude:
    - "include/.ssh/id_*"      # never sync private keys

# Override default Kilo data locations (rarely needed)
# kilo_config_dir: /custom/path/.config/kilo
# kilo_data_dir:   /custom/path/.local/share/kilo
# kilo_home_dir:   /custom/path/.kilo

Note

The local_clone path is expanded (supports ~) and resolved. It must be an existing directory with a .git subdirectory.


πŸ”„ Typical workflow

πŸ’» First machine β€” initial setup

# 1. Create a private git repo on GitHub for your encrypted data (NOT this tool repo)
#    e.g. github.com/YOUR_USERNAME/kilo-sync-data  (private, can be any name)
git clone [email protected]:YOUR_USERNAME/kilo-sync-data.git ~/repos/kilo-sync-data

# 2. Write your config
cat > ~/.kilo/kilo-sync.yaml <<'EOF'
local_clone: ~/repos/kilo-sync-data
profile: default
EOF

# 3. Export and publish in one step
kilo-sync export --publish
# β†’ prompts for a passphrase
# β†’ writes profiles/default.tar.kilosync.bin + profiles/default.meta.json
# β†’ commits and pushes to origin

πŸ’» Second machine β€” receiving a profile

# 1. Clone your private data repo (the same one used on machine A)
git clone [email protected]:YOUR_USERNAME/kilo-sync-data.git ~/repos/kilo-sync-data

# 2. Write the same config
cat > ~/.kilo/kilo-sync.yaml <<'EOF'
local_clone: ~/repos/kilo-sync-data
profile: default
EOF

# 3. Decrypt into staging (safe β€” nothing is written to live paths yet)
kilo-sync import --pull

# 4. Preview what will change
kilo-sync apply --latest --dry-run

# 5. Apply for real
kilo-sync apply --latest

πŸ—“οΈ Day-to-day sync

# After changing your Kilo config on machine A:
kilo-sync export --publish

# On machine B, pull and apply:
kilo-sync import --pull && kilo-sync apply --latest

πŸ€– Non-interactive / scripted sync (e.g. cron)

# Using env var:
KILO_SYNC_PASSPHRASE="my-passphrase" kilo-sync export --publish

# Or pipe via stdin:
echo "my-passphrase" | kilo-sync export --publish

πŸ“œ Command reference

All commands accept --config PATH to use a non-default config file (default: ~/.kilo/kilo-sync.yaml).

export β€” encrypt and optionally publish

kilo-sync export [--profile NAME] [--publish] [--strict-size] [--force]
Flag Description
--profile NAME Override the profile name from config
--publish After encrypting, git add, git commit, and git push
--strict-size Error (not just warn) if tarball exceeds max_tar_bytes
--force Re-encrypt even if the plaintext tarball is unchanged

Tip

If the profile content hasn't changed since the last export, the tool prints No profile changes to export and skips re-encryption (the ciphertext and passphrase aren't touched). Use --force to generate a new ciphertext with a fresh random salt.

With --publish, the working tree outside profiles/ must be clean (no uncommitted changes). The commit message is: kilo-sync: profile <name> <UTC timestamp>

import β€” decrypt into staging

kilo-sync import [--profile NAME] [--pull] [--dry-run]
Flag Description
--profile NAME Override the profile name from config
--pull Run git pull --ff-only on local_clone before importing
--dry-run Decrypt and diff against live paths, but write nothing

Staging directories are created at ~/.kilo/import-staging/<timestamp_uuid>/. After import, a diff table is printed showing staged vs. live file sizes and mtimes.

apply β€” promote staging to live

kilo-sync apply (--latest | --staging PATH) [--dry-run]
Flag Description
--latest Use the most-recently-modified staging directory
--staging PATH Use a specific staging directory
--dry-run Print what would be copied/backed up, but change nothing

Important

Before overwriting any live file, the existing version is backed up to ~/.kilo/backups/<timestamp>/<relative-path>. Permissions: 0o644 for most files, 0o600 for auth.json.

verify β€” integrity check

kilo-sync verify [--profile NAME]

Decrypts the ciphertext and verifies both ciphertext_sha256 and plaintext_sha256 from the meta file. Exits 0 on success, 1 on any mismatch. Does not write anything to disk.

staging prune β€” clean up old staging dirs

kilo-sync staging prune [--keep N] [--dry-run]
Flag Description
--keep N Number of newest directories to keep (default: value of keep_staging from config, which defaults to 3)
--dry-run Print directories that would be removed, but don't remove them

Directories are sorted by mtime (newest first); the oldest beyond N are deleted.

🌐 Global flags

kilo-sync --version     # print version and exit
kilo-sync -V            # short form
kilo-sync --help        # usage summary
kilo-sync <cmd> --help  # per-command help

πŸ”‘ Passphrase

kilo-sync resolves the passphrase in this order:

  1. Interactive TTY β€” getpass prompts once when stdin is a terminal.
  2. Environment variable β€” KILO_SYNC_PASSPHRASE (evaluated first in non-tty mode).
  3. Piped stdin β€” first line read from stdin when not a tty and the env var is not set.

Warning

Security note: the env var may be visible in /proc/<pid>/environ on shared machines. Prefer piped stdin or an interactive prompt on untrusted hosts.


πŸ›‘οΈ Encryption

Backend How it works When it's used
python PBKDF2-HMAC-SHA256 (600 000 iterations) β†’ AES-256-GCM Default when age is not on PATH
age age passphrase mode When age binary is on PATH, or encryption: age is set

Set encryption: python in config to force the built-in engine even when age is installed. The ciphertext format is auto-detected on import/verify.

The file extension reveals the engine used:

  • πŸ”’ profiles/<name>.tar.kilosync.bin β†’ Python AES-GCM
  • πŸ”’ profiles/<name>.tar.age β†’ age

πŸ’» Development

cd /path/to/kilo-sync
pip install -e ".[dev]"
pytest -q          # run all tests
pytest -v          # verbose output

Requirements: Python 3.10+, cryptography >= 42, PyYAML >= 6.
Optional: age on PATH.


πŸ“– Docs

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors