From 2caa09702ffae57f8e2ac04485c97e75e43047fe Mon Sep 17 00:00:00 2001 From: snow Date: Thu, 11 Jun 2026 23:40:26 -0700 Subject: [PATCH] sfs v0.1: mountable synced file system for AI agents - sfs mnt/umnt/sync/status/log/remote/whoami CLI (cobra) - per-device append-only journals + content-addressed blob store - deterministic lamport-ordered merge, LWW with conflict-copy preservation - cloud-agnostic backends: S3, GCS, file:// (S3-compatible via AWS_ENDPOINT_URL) - offline-first: real files on disk, journal locally, push on reconnect - background sync daemon per mount with change tracking (device/author/time) - macOS + Linux; Homebrew formula + goreleaser release pipeline Co-Authored-By: Claude Fable 5 --- .gitignore | 3 + .goreleaser.yaml | 46 ++ .../a75ed46b-65f6-4b00-b5ee-f946ec2826ab.json | 8 + LICENSE | 21 + README.md | 162 +++++ cmd/sfs/cmds.go | 251 ++++++++ cmd/sfs/helpers.go | 99 +++ cmd/sfs/main.go | 77 +++ cmd/sfs/mount.go | 170 +++++ go.mod | 77 +++ go.sum | 171 ++++++ internal/config/config.go | 166 +++++ internal/daemon/daemon.go | 212 +++++++ internal/journal/journal.go | 139 +++++ internal/journal/journal_test.go | 95 +++ internal/remote/gcs.go | 86 +++ internal/remote/local.go | 95 +++ internal/remote/remote.go | 51 ++ internal/remote/s3.go | 108 ++++ internal/store/store.go | 255 ++++++++ internal/store/store_test.go | 111 ++++ internal/syncer/syncer.go | 579 ++++++++++++++++++ internal/syncer/syncer_test.go | 264 ++++++++ packaging/homebrew/sfs.rb | 27 + 24 files changed, 3273 insertions(+) create mode 100644 .gitignore create mode 100644 .goreleaser.yaml create mode 100644 .omc/sessions/a75ed46b-65f6-4b00-b5ee-f946ec2826ab.json create mode 100644 LICENSE create mode 100644 README.md create mode 100644 cmd/sfs/cmds.go create mode 100644 cmd/sfs/helpers.go create mode 100644 cmd/sfs/main.go create mode 100644 cmd/sfs/mount.go create mode 100644 go.mod create mode 100644 go.sum create mode 100644 internal/config/config.go create mode 100644 internal/daemon/daemon.go create mode 100644 internal/journal/journal.go create mode 100644 internal/journal/journal_test.go create mode 100644 internal/remote/gcs.go create mode 100644 internal/remote/local.go create mode 100644 internal/remote/remote.go create mode 100644 internal/remote/s3.go create mode 100644 internal/store/store.go create mode 100644 internal/store/store_test.go create mode 100644 internal/syncer/syncer.go create mode 100644 internal/syncer/syncer_test.go create mode 100644 packaging/homebrew/sfs.rb diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5b009bc --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/sfs +/dist/ +.DS_Store diff --git a/.goreleaser.yaml b/.goreleaser.yaml new file mode 100644 index 0000000..0d39b0e --- /dev/null +++ b/.goreleaser.yaml @@ -0,0 +1,46 @@ +# Release automation: `goreleaser release` on a tagged commit builds +# macOS/Linux binaries and publishes the Homebrew formula to +# runbear-io/homebrew-tap, enabling `brew install runbear-io/tap/sfs`. +version: 2 + +project_name: sfs + +builds: + - id: sfs + main: ./cmd/sfs + binary: sfs + env: + - CGO_ENABLED=0 + goos: + - darwin + - linux + goarch: + - amd64 + - arm64 + ldflags: + - -s -w -X main.version={{.Version}} + +archives: + - formats: [tar.gz] + name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}" + +checksum: + name_template: checksums.txt + +brews: + - name: sfs + repository: + owner: runbear-io + name: homebrew-tap + homepage: https://github.com/runbear-io/sfs + description: "Synced file system for AI agents: mount, sync, and track folders" + license: MIT + test: | + assert_match "sfs", shell_output("#{bin}/sfs version") + +changelog: + sort: asc + filters: + exclude: + - "^docs:" + - "^test:" diff --git a/.omc/sessions/a75ed46b-65f6-4b00-b5ee-f946ec2826ab.json b/.omc/sessions/a75ed46b-65f6-4b00-b5ee-f946ec2826ab.json new file mode 100644 index 0000000..a0bb563 --- /dev/null +++ b/.omc/sessions/a75ed46b-65f6-4b00-b5ee-f946ec2826ab.json @@ -0,0 +1,8 @@ +{ + "session_id": "a75ed46b-65f6-4b00-b5ee-f946ec2826ab", + "ended_at": "2026-06-12T06:15:19.362Z", + "reason": "other", + "agents_spawned": 0, + "agents_completed": 0, + "modes_used": [] +} \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..46f4bd5 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Runbear, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..3077b12 --- /dev/null +++ b/README.md @@ -0,0 +1,162 @@ +# sfs — a synced file system for AI agents + +**sfs** mounts any folder as a synced volume: its contents stay synchronized +across all your devices through cloud object storage, every change is +tracked (who, when, on which device), and everything keeps working offline. + +It is built for AI agent workflows — give your agents on every machine the +same `~/agent-workspace`, and notes, plans, memory files, and artifacts +follow them everywhere, with a full audit trail of which agent or human +changed what. + +```console +$ sfs mnt ./workspace --remote s3://my-bucket/workspace +mounted /Users/snow/workspace + volume: workspace + remote: s3://my-bucket/workspace + device: macbook (d380dea58598) as snow@runbear.io + daemon: running (pid 55434, scan 3s, remote sync 30s) +``` + +On another machine: + +```console +$ sfs mnt ./workspace --remote s3://my-bucket/workspace +# … the same files appear, and stay in sync from now on +``` + +## Features + +- **Mount anywhere** — `sfs mnt ./folder` turns any folder into a synced + volume. Files are *real files on disk*: every tool, editor, and agent can + use them with zero integration work. +- **Multi-device sync** — devices converge through a shared remote. Each + device only writes its own append-only journal, so no locking service or + server is needed — any object store works. +- **Change tracking** — `sfs log` shows which device and author changed + which file, when. Content is stored content-addressed, so history is + never lost, even for overwritten or deleted files. +- **Cloud-provider agnostic** — Amazon S3 (`s3://`), Google Cloud Storage + (`gs://`), any S3-compatible store (MinIO, Cloudflare R2 via + `AWS_ENDPOINT_URL`), or a plain shared directory (`file://`, e.g. a NAS). +- **Offline-first** — the working folder is always fully usable with no + network. Changes are journaled locally and pushed when the remote becomes + reachable again. +- **Conflict-safe** — concurrent edits resolve deterministically + (last-writer-wins), and the losing version is preserved as a + `name.sfs-conflict--