Skip to main content

Invisible, auto-syncing personal storage for any git repo

Project description

Swarf

Invisible, auto-syncing personal storage for any git repo.

Swarf is the metal shavings left on the workshop floor after machining — the byproduct of making something. When you build software (especially with AI agents), you generate a lot of byproduct: research docs, design specs, agent skills, open questions, scratch notes. Swarf gives this material a durable home alongside any project, without touching the project itself.

The problem

You have files that should live near your code but don't belong in the repo:

  • Agent-generated research and design docs
  • Personal notes, roadmaps, and open questions
  • Agent skill files and config (.copilot/skills/, AGENTS.md)
  • Security audits, experiment logs, scratch work

Today these files are either untracked and local-only (one rm -rf from gone) or committed to the repo (polluting history, leaking on public repos). Neither is good.

How it works

Swarf creates a .swarf/ directory inside your project — regular files, invisible to the host repo via .git/info/exclude (managed automatically). A background daemon watches for changes, mirrors them to a central backup store, and syncs to a remote backend (git or rclone).

my-project/                      <- your repo (public)
├── src/
├── tests/
├── .swarf/                      <- private storage (auto-excluded from git)
│   ├── docs/research/           <- durable notes
│   ├── docs/design/             <- specs and decisions
│   ├── links/                   <- files projected into the host tree
│   │   └── AGENTS.md            <- symlinked to ./AGENTS.md
│   └── open-questions.md
└── AGENTS.md -> .swarf/links/AGENTS.md

Files live locally in each project. The daemon mirrors all .swarf/ dirs to ~/.local/share/swarf/ (a git repo), then pushes to your remote.

Install

# Via pip / uvx (any platform — no Go required)
pip install swarf
# or: uvx swarf

# Via Go
go install github.com/mschulkind-oss/swarf@latest

# From source
git clone https://github.com/mschulkind-oss/swarf && cd swarf
just deploy   # builds and copies to ~/.local/bin/

Quick start

cd ~/projects/my-app
swarf init

That's it. If this is your first time, swarf init walks you through everything:

$ swarf init

No global config found. Let's set one up.

Backend (git/rclone) [git]: git
Remote URL: git@github.com:you/my-swarf.git
✓ Wrote ~/.config/swarf/config.toml

Created .mise.local.toml with enter hook.

✓ Initialized swarf in /home/you/projects/my-app/.swarf
  Backend: git
  Remote: git@github.com:you/my-swarf.git

Daemon is not running. Install as system service? [Y/n]: y
✓ Installed and started swarf daemon

Next time you run swarf init in another project, it reuses your config and the daemon picks it up automatically — no prompts.

Rclone backend (Google Drive, Dropbox, S3, etc.)

If you prefer cloud storage over a git repo, install rclone first:

brew install rclone   # or: mise use rclone
rclone config
#   -> n (new remote), name: gdrive, type: drive
#   -> scope: drive.file (option 2 — can only see files rclone created)
#   -> auto config: y (opens browser)

Then run swarf init and enter rclone as the backend and gdrive:swarf as the remote. The drive.file scope means the OAuth token can only access files swarf created — it cannot read your other Google Drive documents.

Verify your setup

swarf doctor
# ✓ Global config: backend=git, remote=git@github.com:you/my-swarf.git
# ✓ Git remote reachable
# ✓ Daemon is running
# ✓ .swarf/ directory exists
# ✓ .swarf/ is gitignored
# ...

Using swarf

Adding content

Put files directly into .swarf/:

# Research notes, design docs, anything you want backed up
echo "# Architecture Notes" > .swarf/docs/design/architecture.md
echo "# Open Questions" >> .swarf/open-questions.md

The daemon auto-commits and syncs after a 5-second quiet period.

Sweeping files into swarf

Use swarf sweep to move existing files into .swarf/links/ and replace them with symlinks. The host repo automatically ignores the symlinks via .git/info/exclude.

# Sweep an existing file into swarf
swarf sweep AGENTS.md
# AGENTS.md -> .swarf/links/AGENTS.md

# Sweep multiple files at once
swarf sweep .copilot/skills/SKILL.md .cursor/rules/project.md

# Verify
ls -la AGENTS.md
# AGENTS.md -> .swarf/links/AGENTS.md

You can also configure auto-sweep in ~/.config/swarf/config.toml to automatically sweep common files (like AGENTS.md) whenever you cd into a project. See Configuration.

Checking health

swarf doctor    # validate setup: gitignore, git repo, remote, links
swarf status    # show all projects, sync state, daemon status

Commands

Command Description
swarf init Initialize .swarf/ in current project
swarf sweep <file>... Move files into .swarf/links/ and symlink back
swarf doctor Validate setup and backend health
swarf status Show all projects and sync status
swarf daemon start Start background sync daemon
swarf daemon stop Stop the daemon
swarf daemon status Check if daemon is running
swarf daemon install Install as systemd user service (auto-start on login)

Daemon as a system service

To have the daemon start automatically on login:

swarf daemon install

This creates a systemd user service. Check logs with:

journalctl --user -u swarf -f

How it works on a company monorepo

The same way. swarf init writes to .git/info/exclude, which is per-repo and never committed. No changes to the monorepo's .gitignore, no submodules, no permission needed.

cd ~/work/big-monorepo
swarf init

Your agent config, personal notes, and research are now durable and synced, completely invisible to your coworkers and CI.

How it works with AI agent containers

If you use containerized agents (like yolo-jail), the daemon runs on the host, not inside the container. The container mounts the workspace directory, so file changes from agents are visible to the host filesystem. The daemon picks them up and syncs automatically. Agents never need credentials.

Configuration

Global config lives at ~/.config/swarf/config.toml (created automatically by swarf init on first run):

[sync]
backend = "git"          # or "rclone"
remote = "origin"        # git remote or rclone remote path
debounce = "5s"          # wait this long after last change before syncing

[auto_sweep]
# Files to automatically sweep into .swarf/links/ when entering a project.
# Only swept if the file exists and isn't already a symlink.
paths = ["AGENTS.md", "CLAUDE.md", ".copilot/skills/"]

This is set once and applies to all projects.

Contributing

See CONTRIBUTING.md for development setup and guidelines.

License

Apache 2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

swarf-0.3.0-py3-none-musllinux_1_2_x86_64.whl (6.0 MB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

swarf-0.3.0-py3-none-musllinux_1_2_aarch64.whl (5.7 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARM64

swarf-0.3.0-py3-none-manylinux_2_17_x86_64.whl (6.0 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

swarf-0.3.0-py3-none-manylinux_2_17_aarch64.whl (5.7 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

swarf-0.3.0-py3-none-macosx_11_0_arm64.whl (5.8 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

swarf-0.3.0-py3-none-macosx_10_9_x86_64.whl (6.2 MB view details)

Uploaded Python 3macOS 10.9+ x86-64

File details

Details for the file swarf-0.3.0-py3-none-musllinux_1_2_x86_64.whl.

File metadata

  • Download URL: swarf-0.3.0-py3-none-musllinux_1_2_x86_64.whl
  • Upload date:
  • Size: 6.0 MB
  • Tags: Python 3, musllinux: musl 1.2+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for swarf-0.3.0-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 69f069bf0dd9d3075ff366fef19ba55328cf8e989d6d179e742436b8b85381b6
MD5 1763cc43280e76d1f6479a20b75871db
BLAKE2b-256 7385d491270acc55ef38e793d3cd9f3440199a5e2d9f29a0e0ca0c11bfbbde90

See more details on using hashes here.

File details

Details for the file swarf-0.3.0-py3-none-musllinux_1_2_aarch64.whl.

File metadata

  • Download URL: swarf-0.3.0-py3-none-musllinux_1_2_aarch64.whl
  • Upload date:
  • Size: 5.7 MB
  • Tags: Python 3, musllinux: musl 1.2+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for swarf-0.3.0-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 909ce19406fce4b7f32b31cfcbba738c735b5c2a48bd58e2cc95c4149b79a85e
MD5 17b7ac86dcc80807b50c8c8f4202b1f0
BLAKE2b-256 bb41dd80fa8d04652801d5f823166b5458251d9c9a4bed355e56f0fbfa7a0a11

See more details on using hashes here.

File details

Details for the file swarf-0.3.0-py3-none-manylinux_2_17_x86_64.whl.

File metadata

  • Download URL: swarf-0.3.0-py3-none-manylinux_2_17_x86_64.whl
  • Upload date:
  • Size: 6.0 MB
  • Tags: Python 3, manylinux: glibc 2.17+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for swarf-0.3.0-py3-none-manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 fe61766190dd9552d2a0de7ae7389f295f99974069596f7994cdf0967d86be9a
MD5 417917d7405f2e3d04f3cf0ffb6d8ff7
BLAKE2b-256 a1993d972080426037ce1dfb1a7b3d9c12d2cb3be9611bcfb8268a10b6365f45

See more details on using hashes here.

File details

Details for the file swarf-0.3.0-py3-none-manylinux_2_17_aarch64.whl.

File metadata

  • Download URL: swarf-0.3.0-py3-none-manylinux_2_17_aarch64.whl
  • Upload date:
  • Size: 5.7 MB
  • Tags: Python 3, manylinux: glibc 2.17+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for swarf-0.3.0-py3-none-manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 d2e13ff0a5cab42be36c2fbdb6e21cc17f175c8ca0dc3c929f559005e1afd331
MD5 6af73c121fd5fb94e6246970dc2db491
BLAKE2b-256 a8fb5f43471784c123938e39cae707676c25fbd0ee89e73dd5c25771afc2b152

See more details on using hashes here.

File details

Details for the file swarf-0.3.0-py3-none-macosx_11_0_arm64.whl.

File metadata

  • Download URL: swarf-0.3.0-py3-none-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 5.8 MB
  • Tags: Python 3, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for swarf-0.3.0-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 e5232f2cb8d5b3ffe29f926f2d714c7d6d29b26c633b36bc624c2dd14e9aa7da
MD5 1b98eb177fe93e6346f4f168dd4adf57
BLAKE2b-256 3c185d6a5835f32f4e7dc78dd2053b09062db67462d9e9e2cc1a873861c37ef7

See more details on using hashes here.

File details

Details for the file swarf-0.3.0-py3-none-macosx_10_9_x86_64.whl.

File metadata

  • Download URL: swarf-0.3.0-py3-none-macosx_10_9_x86_64.whl
  • Upload date:
  • Size: 6.2 MB
  • Tags: Python 3, macOS 10.9+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for swarf-0.3.0-py3-none-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 a25f446fdbbaea65e4e361e9f17f9ef65b01f9af722880cc798d3ef826143a13
MD5 1d87cd222c599e02ddecccaa3cb21614
BLAKE2b-256 ff731940fef51797adb47a2ae9cf88fafe1f89b6b9a0579ac5f257977eee6dfc

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page