PHPackages                             verseles/flyclone - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [File &amp; Storage](/categories/file-storage)
4. /
5. verseles/flyclone

ActiveLibrary[File &amp; Storage](/categories/file-storage)

verseles/flyclone
=================

PHP wrapper for rclone

v5.0.0(1w ago)102.3k↓13.9%1CC-BY-NC-SA-4.0PHPPHP &gt;=8.4CI passing

Since Mar 12Pushed 4d agoCompare

[ Source](https://github.com/verseles/flyclone)[ Packagist](https://packagist.org/packages/verseles/flyclone)[ RSS](/packages/verseles-flyclone/feed)WikiDiscussions main Synced yesterday

READMEChangelog (3)Dependencies (18)Versions (62)Used By (0)

Verseles\\Flyclone
==================

[](#verselesflyclone)

PHP 8.4+ wrapper for [rclone](https://rclone.org/), focused on safe, testable file operations across local disks, S3-compatible storage, SFTP, FTP, Google Drive, Dropbox, Mega, B2, and the rest of rclone's backends.

[![PHPUnit](https://camo.githubusercontent.com/91a3a4e364b341ceb26bc18ebf4332fbc1d86150ebdf2f0221637a703903543e/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f76657273656c65732f666c79636c6f6e652f706870756e69742e796d6c3f7374796c653d666f722d7468652d6261646765266c6162656c3d504850556e6974)](https://github.com/verseles/flyclone/actions)[![PHP](https://camo.githubusercontent.com/d9a2ccc2235ef3e1cf92c8caffb0efd0aabce5ec07c18abe94dd9fff58d99f43/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e342b2d3737376262343f7374796c653d666f722d7468652d6261646765266c6f676f3d706870266c6f676f436f6c6f723d7768697465)](https://www.php.net/)[![License](https://camo.githubusercontent.com/3b36213e329d3585b74d2dd2e7e41940fe9e732bb051f531cadbf08f517ddb12/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d43432d2d42592d2d4e432d2d53412d2d342e302d677265656e3f7374796c653d666f722d7468652d6261646765)](LICENSE.md)

Why Flyclone
------------

[](#why-flyclone)

- Object-oriented providers around rclone remotes.
- Single-remote and two-remote operations through the same `Rclone` class.
- Transfer statistics and optional progress callbacks.
- Typed exceptions for rclone exit codes.
- Retry support with exponential backoff.
- Fluent include/exclude filters.
- Debug logging with secret redaction.
- v5 safety hardening for long-lived workers: instance-scoped options, provider collision detection, safe temporary remotes, private temp directories, and inline SFTP key support.

Requirements
------------

[](#requirements)

- PHP &gt;= 8.4
- `ext-json`
- `rclone` binary available in `PATH`, or configured with `Rclone::setBIN()`

Installation
------------

[](#installation)

```
composer require verseles/flyclone:^5.0
```

Quick Start
-----------

[](#quick-start)

```
use Verseles\Flyclone\Providers\LocalProvider;
use Verseles\Flyclone\Providers\S3Provider;
use Verseles\Flyclone\Rclone;

$local = new LocalProvider('local_disk');

$s3 = new S3Provider('archive_bucket', [
    'access_key_id' => 'YOUR_KEY',
    'secret_access_key' => 'YOUR_SECRET',
    'region' => 'us-east-1',
]);

$rclone = new Rclone($local, $s3);
$result = $rclone->copy('/var/backups', 'my-bucket/backups');

if ($result->success) {
    echo "Transferred {$result->stats->bytes} bytes at {$result->stats->speed_human}";
}
```

For one-remote operations, pass only one provider:

```
$files = (new Rclone($local))->ls('/var/backups');
```

Providers
---------

[](#providers)

BackendClassNotesLocal filesystem`LocalProvider`Local paths and temporary helper remotesAmazon S3 / MinIO / R2`S3Provider`S3-compatible flags map to rclone env configSFTP`SFtpProvider`Supports password, `key_file`, and v5 inline `key_pem`/`private_key`FTP`FtpProvider`FTP/FTPSGoogle Drive`GDriveProvider`OAuth/config-driven rclone backendDropbox`DropboxProvider`OAuth/config-driven rclone backendMega.nz`MegaProvider`Mega backendBackblaze B2`B2Provider`B2 backendEncrypted remote`CryptProvider`Wraps another providerUnion filesystem`UnionProvider`Merges upstream providersAny other rclone backend`Provider`Generic provider classProvider names are normalized to rclone-safe uppercase remote names. In v5, names that normalize to an empty value are rejected, and conflicting provider environment variables fail fast instead of being silently overwritten.

Core Operations
---------------

[](#core-operations)

```
$rclone = new Rclone($sourceProvider, $destProvider);

$rclone->copy('/source/dir', '/dest/dir');
$rclone->copyto('/source/file.txt', '/dest/file.txt');
$rclone->move('/source/dir', '/dest/dir');
$rclone->moveto('/source/file.txt', '/dest/file.txt');
$rclone->sync('/source/dir', '/dest/dir');
$rclone->delete('/path/to/delete');
```

Upload and download helpers create unique temporary local remotes internally:

```
$rclone = new Rclone($s3);

$rclone->upload_file('/tmp/report.pdf', 'bucket/reports/report.pdf');
$download = $rclone->download_to_local('bucket/reports/report.pdf');

echo $download->local_path;
```

SFTP Private Keys
-----------------

[](#sftp-private-keys)

Prefer inline PEM keys in v5. Flyclone passes the value to rclone as `RCLONE_CONFIG__KEY_PEM`; no key file is created by Flyclone.

```
use Verseles\Flyclone\Providers\SFtpProvider;

$sftp = new SFtpProvider('deploy', [
    'host' => 'sftp.example.com',
    'user' => 'deploy',
    'private_key' => $privateKeyPem,
    'key_use_agent' => false,
]);
```

`private_key` is a convenience alias for `key_pem`. `key_pem` and `key_file` are mutually exclusive.

Encryption
----------

[](#encryption)

`CryptProvider` wraps another provider through the required `remote` flag.

```
use Verseles\Flyclone\Providers\CryptProvider;
use Verseles\Flyclone\Providers\S3Provider;
use Verseles\Flyclone\Rclone;

$s3 = new S3Provider('raw_archive', [
    'access_key_id' => 'YOUR_KEY',
    'secret_access_key' => 'YOUR_SECRET',
    'region' => 'us-east-1',
]);

$encrypted = new CryptProvider('encrypted_archive', [
    'remote' => $s3,
    'remote_path' => 'encrypted-prefix',
    'password' => Rclone::obscure('my-secret-password'),
    'password2' => Rclone::obscure('my-salt'),
]);

(new Rclone($encrypted))->copy('/local/sensitive-data', '/');
```

Union Filesystems
-----------------

[](#union-filesystems)

`UnionProvider` receives upstream providers through `upstream_providers`.

```
use Verseles\Flyclone\Providers\LocalProvider;
use Verseles\Flyclone\Providers\S3Provider;
use Verseles\Flyclone\Providers\UnionProvider;
use Verseles\Flyclone\Rclone;

$cache = new LocalProvider('cache', ['root' => '/tmp/cache']);
$archive = new S3Provider('archive', [/* config */]);

$union = new UnionProvider('combined', [
    'upstream_providers' => [$cache, $archive],
    'action_policy' => 'all',
    'create_policy' => 'ff',
]);

$files = (new Rclone($union))->ls('/');
```

Configuration
-------------

[](#configuration)

Static configuration is still available and is captured by new `Rclone` instances at construction time:

```
Rclone::setBIN('/custom/path/to/rclone');
Rclone::setFlags(['checksum' => true]);
Rclone::setEnvs(['RCLONE_BUFFER_SIZE' => '64M']);
Rclone::setTimeout(300);
Rclone::setIdleTimeout(120);
```

For long-lived workers, prefer instance-scoped options:

```
$rclone = (new Rclone($source, $dest))
    ->withFlags(['checksum' => true])
    ->withEnvs(['RCLONE_BUFFER_SIZE' => '64M'])
    ->withTimeout(300)
    ->withIdleTimeout(120);
```

Filtering
---------

[](#filtering)

```
use Verseles\Flyclone\FilterBuilder;

$filter = FilterBuilder::create()
    ->extensions(['jpg', 'png', 'gif'])
    ->minSize('100K')
    ->maxSize('50M')
    ->exclude('**/thumbnails/**');

$rclone->withFilter($filter)->copy('/source', '/dest');
```

Progress, Retry, And Dry Run
----------------------------

[](#progress-retry-and-dry-run)

```
use Verseles\Flyclone\RetryHandler;

$handler = RetryHandler::create()
    ->maxAttempts(5)
    ->baseDelay(500)
    ->multiplier(2.0)
    ->maxDelay(30000)
    ->onRetry(fn (int $attempt, Throwable $e) => logger("Retry {$attempt}: {$e->getMessage()}"));

$progress = function (object $progress): void {
    echo $progress->percentage . "%\n";
};

$rclone->withRetry($handler)
    ->dryRun(false)
    ->copy('/source', '/dest', onProgress: $progress);
```

Error Handling
--------------

[](#error-handling)

```
use Verseles\Flyclone\Exception\DirectoryNotFoundException;
use Verseles\Flyclone\Exception\FileNotFoundException;
use Verseles\Flyclone\Exception\TemporaryErrorException;

try {
    $rclone->copy('/source', '/dest');
} catch (FileNotFoundException|DirectoryNotFoundException $e) {
    // Permanent user/input error.
} catch (TemporaryErrorException $e) {
    if ($e->isRetryable()) {
        // Retry may succeed.
    }

    $context = $e->getContext();
}
```

Debugging
---------

[](#debugging)

```
use Verseles\Flyclone\Logger;

Logger::setDebugMode(true);

$rclone->copy('/source', '/dest');

echo $rclone->getLastCommand();
$envs = $rclone->getLastEnvs(); // Secrets are redacted.
$logs = Logger::getLogs();
```

Utilities
---------

[](#utilities)

```
$remotes = Rclone::listRemotes();
$config = Rclone::configDump();
$md5 = $rclone->md5sum('/path');
$sha1 = $rclone->sha1sum('/path');
$health = $rclone->healthCheck('/');
```

v5 Breaking Changes
-------------------

[](#v5-breaking-changes)

- Provider names that normalize to an empty rclone remote name now throw `InvalidArgumentException`.
- Conflicting provider env vars now throw `LogicException` instead of overwriting values.
- Two providers with the same normalized remote name and different config now fail fast.
- Existing `Rclone` instances no longer observe later changes to static flags/envs/timeouts; use `withFlags()`, `withEnvs()`, `withTimeout()`, and `withIdleTimeout()` for per-instance updates.
- `SFtpProvider` rejects ambiguous `key_pem` plus `key_file` configuration.

See [MIGRATION.md](MIGRATION.md) for migration notes.

Testing
-------

[](#testing)

```
composer install

# Fast local/offline checks
composer test-local
make test

# Full offline provider suite, when podman-compose is available
make test-offline

# Static analysis and formatting
composer analyse
composer run-script format-check
```

Provider-specific tests such as `make test_dropbox` and `make test_gdrive` require a configured `.env`.

Architecture
------------

[](#architecture)

Flyclone v5 is organized around small components:

ComponentResponsibility`Rclone`Public API and operation orchestration`Provider` and subclassesrclone remote configuration`CommandBuilder`Command arguments and environment variables`ProcessManager`Symfony Process execution and binary detection`StatsParser`Transfer statistics parsing`ProgressParser`Real-time progress parsing`RetryHandler`Retry policy and backoff`FilterBuilder`Include/exclude filter construction`TemporaryPath`Private temp directories and unique temporary remote names`SecretsRedactor`Secret redaction for errors/logs/envs`Logger`Structured debug loggingChangelog
---------

[](#changelog)

### v5.0.0

[](#v500)

- Hardened provider configuration for long-lived workers.
- Added instance-scoped flags, envs, and timeouts.
- Added provider env collision detection.
- Added remote-name collision detection.
- Added safe temporary local provider names.
- Added private temporary download directories.
- Added SFTP inline private key support via `key_pem`/`private_key`.
- Added configuration/security tests to the fast test path.

### v4.x

[](#v4x)

- Modularized `Rclone` internals into process, command, stats, progress, retry, filter, logger, and redaction components.
- Added typed exception context, health checks, dry-run mode, command introspection, and static utilities.
- Added `CryptProvider` and `UnionProvider` support.

### v3.x

[](#v3x)

- Added detailed transfer statistics and progress tracking improvements.

License
-------

[](#license)

[Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International](LICENSE.md)

###  Health Score

60

—

FairBetter than 98% of packages

Maintenance99

Actively maintained with recent releases

Popularity27

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity84

Battle-tested with a long release history

 Bus Factor1

Top contributor holds 97.8% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~42 days

Recently: every ~11 days

Total

47

Last Release

13d ago

Major Versions

v0.21 → v1.0.12023-12-01

v1.1.2 → v2.0.02024-05-20

v2.5.0 → v3.0.02025-07-07

v3.0.1 → v4.x-dev2026-01-04

v4.3.0 → v5.0.02026-06-20

PHP version history (3 changes)0.8PHP &gt;=7.4

v0.17PHP &gt;=8.0

v2.2.0PHP &gt;=8.4

### Community

Maintainers

![](https://www.gravatar.com/avatar/934b53b68624e78343e3f3367897cbaf5fb01475511a1650d2c99c972c810ec6?d=identicon)[insign](/maintainers/insign)

---

Top Contributors

[![insign](https://avatars.githubusercontent.com/u/1113045?v=4)](https://github.com/insign "insign (175 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (2 commits)")[![google-labs-jules[bot]](https://avatars.githubusercontent.com/in/842251?v=4)](https://github.com/google-labs-jules[bot] "google-labs-jules[bot] (1 commits)")[![jaytagdamian](https://avatars.githubusercontent.com/u/17107538?v=4)](https://github.com/jaytagdamian "jaytagdamian (1 commits)")

---

Tags

cloudatlasdiskdropboxflysystemhacktoberfestphpphp-wrapperrclonewrapperftpfilesystemabstractions3awscloudsftpfilesstorageWebDAVfilesystemsremotesyncdropboxrackspacercloneCloud Filesfile systems

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/verseles-flyclone/health.svg)

```
[![Health](https://phpackages.com/badges/verseles-flyclone/health.svg)](https://phpackages.com/packages/verseles-flyclone)
```

###  Alternatives

[league/flysystem

File storage abstraction for PHP

13.6k679.9M2.5k](/packages/league-flysystem)[creocoder/yii2-flysystem

The flysystem extension for the Yii framework

2931.7M63](/packages/creocoder-yii2-flysystem)[innoge/laravel-rclone

A sleek PHP wrapper around rclone with Laravel-style fluent API syntax

175.9k](/packages/innoge-laravel-rclone)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
