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.2.0-py3-none-musllinux_1_2_x86_64.whl (6.0 MB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

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

Uploaded Python 3musllinux: musl 1.2+ ARM64

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

Uploaded Python 3manylinux: glibc 2.17+ x86-64

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

Uploaded Python 3manylinux: glibc 2.17+ ARM64

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

Uploaded Python 3macOS 11.0+ ARM64

swarf-0.2.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.2.0-py3-none-musllinux_1_2_x86_64.whl.

File metadata

  • Download URL: swarf-0.2.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.2.0-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 0a9b4f554693eaab5c3184b94fceb2a548c9b30cd8f06dd20a101a838327822f
MD5 e1d297f5913c0104cd366b7deaaf2faa
BLAKE2b-256 54081b8452f8525b955df78705095b2bb29bfe1f836abb06da4cfc10e8db3b38

See more details on using hashes here.

File details

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

File metadata

  • Download URL: swarf-0.2.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.2.0-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 c7c9f093bd704e7533de397dd11b4ee15a3468c96ee954075d7fcf756a406759
MD5 f4a9b26474c24928b802764ce692cb4c
BLAKE2b-256 a7f043f99add801c22e60841a3743ea4c00e63120608fae4c8e31c1bc62ad815

See more details on using hashes here.

File details

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

File metadata

  • Download URL: swarf-0.2.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.2.0-py3-none-manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 fbcc11f62e9eb6ee96a65a09f30d8ead1cb67dd9f1539a7c0328083dd08f8566
MD5 d2e5d35d4249512b9a958ce43cabd200
BLAKE2b-256 d5f5a0add420f9821a0c34ab03f620f42e1b5675c9cc7aef9571e497dc522b18

See more details on using hashes here.

File details

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

File metadata

  • Download URL: swarf-0.2.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.2.0-py3-none-manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 e577cf05ecb20de963fb9f45e6eddec1301048cd513277b57021cf801d66b725
MD5 15fdf26f19393ba32505ad5d590db44b
BLAKE2b-256 0e2a2b91d6c2ff065939df56fdf78bd1c168abaa97bca4065f7f8c92a112fb63

See more details on using hashes here.

File details

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

File metadata

  • Download URL: swarf-0.2.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.2.0-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 9110e1289b1537625811cf565a7f9d340fed3ec2ecdfc99be5f909fbb9b26e84
MD5 233fc6cb71fdff53b7d48279872be885
BLAKE2b-256 caed080028009c29ac2817d1328b34a42b2ac821be838603d4ac5c4bdc3a76a5

See more details on using hashes here.

File details

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

File metadata

  • Download URL: swarf-0.2.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.2.0-py3-none-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 fa5f019277044e19d7b2f572877434c3a87851723bfa35eff6ec8c0dc019a9c7
MD5 92cd43d060db744ae7dcddec0dbf833a
BLAKE2b-256 0c91619ec94bd9a70984fa062d5874ef2100530921a66929d10068989fea35b9

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