Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Sync Fs Laravel Package

velikonja/sync-fs

A Laravel/PHP filesystem synchronization package for keeping files and directories in sync across local and remote disks. It provides a simple way to compare and mirror storage using Flysystem, making deployment, backups, and environment file syncing easier.

View on GitHub
Deep Wiki
Context7

Getting Started

SyncFS is a small, single-purpose library: you declare folder pairs in a configuration file and it copies changed files from source to destination, either through a CLI binary or by instantiating the library classes directly. It predates Laravel's filesystem abstractions being idiomatic for this job, so treat it as a thin wrapper around copy/compare logic rather than a deployment tool.

Minimal steps:

  1. Install as a dev dependency so it never ships to production:
    composer require --dev velikonja/sync-fs
    
  2. Confirm the binary is exposed at vendor/bin/syncfs (older packages sometimes ship a bin/ script you invoke directly). Run vendor/bin/syncfs --help and vendor/bin/syncfs list if the CLI is Symfony Console–based — that tells you the real command name and options faster than the README will.
  3. Look first at the repo's example configuration (usually example/, config/, or the README snippet). The config is a plain structured file declaring named jobs, each with a source and a destination path. Copy it into your project as syncfs.json (or .yml, depending on the format the parser expects) rather than hand-writing keys.
  4. Define one job and dry-run it against a scratch directory:
    {
      "jobs": {
        "assets": {
          "source": "/var/www/app/public/build",
          "target": "/mnt/staging/public/build"
        }
      }
    }
    
  5. Execute vendor/bin/syncfs assets (or vendor/bin/syncfs sync assets) and diff the two trees to confirm behavior before trusting it.

First use case: mirroring a build output directory or an uploads folder between two local paths or mounted volumes — not S3, not FTP, not a real deployment pipeline.

Implementation Patterns

Composer script hooks. The lowest-friction integration is a post-build or post-install hook, so asset mirroring happens without anyone remembering to run it:

"scripts": {
  "post-install-cmd": ["@sync-assets"],
  "sync-assets": "syncfs assets"
}

Artisan command wrapper. If you want logging, env-aware config, and a proper exit code, wrap the library rather than shelling out:

class SyncAssets extends Command
{
    protected $signature = 'sync:assets {job=assets}';

    public function handle()
    {
        $config = config('syncfs');           // your own Laravel config
        $syncer = new \Velikonja\SyncFS\...;  // check the concrete class name in the source

        $syncer->run($config['jobs'][$this->argument('job')]);

        $this->info('Sync complete.');
        return self::SUCCESS;
    }
}

Wrapping also lets you inject Storage-style path helpers and swap in a fake during tests.

Environment-specific job files. Keep one config per environment (syncfs.local.json, syncfs.staging.json) and select via .env, since paths for a mounted volume on a laptop never match the server. Pass the file path as a CLI option where supported, or resolve it in your wrapper.

Scheduler-driven mirroring. For periodic one-way copies (e.g. syncing a media directory to a backup mount), schedule the wrapper and guard against overlap:

$schedule->command('sync:media')->hourly()->withoutOverlapping();

Deploy pipeline step. Run it as a discrete task after the build artifact is produced and before the app is switched live. Because it is one-way and stateless, it composes cleanly with Envoy or Deployer tasks — but keep it off the critical path until you've verified behavior.

API over CLI inside tests. Instantiate the syncer directly in a feature test to assert that a fixture directory lands where expected; this is faster and more debuggable than asserting on subprocess output.

Gotchas and Tips

  • It is unmaintained (last release 2015). Pin the exact version, and expect friction on PHP 8: old Symfony Console constraints and PHP 5-era syntax are common failure points. Run it on the same PHP version your app uses before committing to it.
  • Audit the dependency tree. Zero stars and a decade of silence mean no security review has happened. composer why and a quick read of the source (it's small) is worth more than trusting the abstraction.
  • Confirm delete semantics before pointing it at anything real. One-way sync tools differ on whether extra files at the target are removed. Test with a junk file at the destination and observe. Treat destructive mode as production-unsafe.
  • Relative paths resolve from the current working directory, not the config file. Always use absolute paths or resolve them explicitly in your wrapper; otherwise artisan from a different directory silently syncs the wrong tree.
  • No locking. Concurrent runs against the same target can interleave and corrupt state. Use withoutOverlapping() in the scheduler or flock in CI.
  • Permissions drift. Files copied by a CLI user under a web-served directory can end up unreadable by www-data (or vice versa). Set the umask or chown in the deploy step.
  • Don't commit secrets. If the config format supports remote credentials, source them from env vars; the file lives in the repo by default.
  • Check exit codes in scripts. syncfs job || exit 1 — a silent non-zero in a deploy hook is worse than a hard failure.
  • Extension points are thin. The library is small enough to fork; if you need excludes, checksums, or atomic rename behavior, patching the syncer is often faster than layering config workarounds. At that point, though, evaluate rsync or rclone first.
  • Debugging strategy: run against two small temp directories, add verbosity flags if the CLI exposes them, and read the syncer source to learn exactly which files it considers "changed." Don't infer it from file timestamps alone.

Given the maintenance status, the honest recommendation is: use it for a throwaway internal asset mirror, keep it isolated behind a thin wrapper so you can swap the implementation, and default to rsync for anything durable.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums