verseles / flyclone
PHP wrapper for rclone
Installs: 1 726
Dependents: 0
Suggesters: 0
Security: 0
Stars: 5
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/verseles/flyclone
Requires
- php: >=8.4
- ext-json: *
- spatie/once: ^3.0.1
- symfony/process: ^7
Requires (Dev)
- enlightn/security-checker: ^1.9
- laravel/pint: ^1.26
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^12.0
- dev-main
- v4.x-dev
- v4.0.1
- v4.0.0
- v3.0.1
- v3.0.0
- v2.5.0
- v2.4.0
- v2.3.1
- v2.3.0
- v2.2.4
- v2.2.3
- v2.2.2
- v2.2.1
- v2.2.0
- v2.1.0
- v2.0.0
- v1.1.2
- v1.1.1
- v1.1.0
- v1.0.7
- v1.0.6
- v1.0.5
- v1.0.4
- v1.0.3
- v1.0.2
- v1.0.1
- v0.21
- v0.20
- v0.19
- v0.18
- v0.17
- v0.16.3
- 0.16.1
- 0.16
- 0.15
- 0.14
- 0.13
- 0.12
- 0.11
- 0.10
- 0.9
- 0.8
- dev-fix/process-manager-guess-bin-7675654203172392090
- dev-refactor/type-hints-phpstan-level-6-6364721061526976839
- dev-fix/process-manager-guess-bin-11192536405937360082
- dev-fix/check-command-exit-code-2927449446816599270
- dev-feat/improve-types-phpstan-6-17513892186180890901
- dev-feat/add-hashsum-7667133079508747177
- dev-version-cache-improvement-1325462771431874723
- dev-claude/implement-feature-1-LP9yM
- dev-claude/identify-improvements-01GkmKDArifoKkQhGdWYTzvb
This package is auto-updated.
Last update: 2026-02-16 00:52:34 UTC
README
PHP wrapper for rclone - the Swiss army knife of cloud storage.
Flyclone provides an intuitive, object-oriented interface for interacting with rclone. Transfer files between 70+ cloud providers with progress tracking, detailed statistics, and robust error handling.
Features
- 70+ Storage Backends - Local, S3, SFTP, FTP, Dropbox, Google Drive, Mega, B2, and more
- Fluent API - Clean, chainable interface for all rclone operations
- Progress Tracking - Real-time transfer progress with speed, ETA, and percentage
- Transfer Statistics - Detailed stats (bytes, files, speed, errors) after each operation
- Encryption Support - Transparent encryption via CryptProvider
- Union Filesystems - Merge multiple providers into a single virtual filesystem
- Type-Safe Errors - Specific exceptions for each rclone exit code
- Automatic Retry - Exponential backoff for transient failures
- Filtering API - Fluent builder for include/exclude patterns
- Security First - Secrets redaction in errors, credential validation warnings
- Debug Mode - Command introspection and structured logging
Requirements
- PHP >= 8.4
- rclone binary in PATH
Installation
composer require verseles/flyclone
Quick Start
use Verseles\Flyclone\Rclone; use Verseles\Flyclone\Providers\LocalProvider; use Verseles\Flyclone\Providers\S3Provider; // Single provider - operations on one remote $local = new LocalProvider('myDisk'); $rclone = new Rclone($local); $files = $rclone->ls('/path/to/files'); // Two providers - transfer between remotes $s3 = new S3Provider('myS3', [ 'access_key_id' => 'YOUR_KEY', 'secret_access_key' => 'YOUR_SECRET', 'region' => 'us-east-1', ]); $rclone = new Rclone($local, $s3); $result = $rclone->copy('/local/data', 'my-bucket/backup'); if ($result->success) { echo "Transferred {$result->stats->bytes} bytes at {$result->stats->speed_human}"; }
Supported Providers
| Provider | Class | Notes |
|---|---|---|
| Local filesystem | LocalProvider |
|
| Amazon S3 / MinIO | S3Provider |
S3-compatible |
| SFTP | SFtpProvider |
SSH File Transfer |
| FTP | FtpProvider |
|
| Dropbox | DropboxProvider |
|
| Google Drive | GDriveProvider |
|
| Mega.nz | MegaProvider |
|
| Backblaze B2 | B2Provider |
|
| Encryption | CryptProvider |
Wraps any provider |
| Union | UnionProvider |
Merges multiple providers |
All 70+ rclone backends can be used via the generic
Providerclass.
Advanced Features
Encryption with CryptProvider
use Verseles\Flyclone\Rclone; use Verseles\Flyclone\Providers\S3Provider; use Verseles\Flyclone\Providers\CryptProvider; $s3 = new S3Provider('myS3', [/* config */]); $encrypted = new CryptProvider('encrypted', [ 'password' => Rclone::obscure('my-secret-password'), 'password2' => Rclone::obscure('my-salt'), ], $s3); $rclone = new Rclone($encrypted); $rclone->copy('/local/sensitive-data', '/encrypted-bucket/backup'); // Files are transparently encrypted before upload
Union Filesystem
use Verseles\Flyclone\Rclone; use Verseles\Flyclone\Providers\LocalProvider; use Verseles\Flyclone\Providers\S3Provider; use Verseles\Flyclone\Providers\UnionProvider; $local = new LocalProvider('cache', ['root' => '/tmp/cache']); $s3 = new S3Provider('archive', [/* config */]); $union = new UnionProvider('combined', [ 'action_policy' => 'all', 'create_policy' => 'ff', ], [$local, $s3]); $rclone = new Rclone($union); $files = $rclone->ls('/'); // Lists files from both local and S3
Global Configuration
// Set rclone binary path (auto-detected by default) Rclone::setBIN('/custom/path/to/rclone'); // Set global flags for all operations Rclone::setFlags(['checksum' => true, 'verbose' => true]); // Set environment variables Rclone::setEnvs(['RCLONE_BUFFER_SIZE' => '64M']); // Set timeouts Rclone::setTimeout(300); // Max execution time (seconds) Rclone::setIdleTimeout(120); // Idle timeout (seconds) // Obscure passwords $obscured = Rclone::obscure('plain-password');
Error Handling
use Verseles\Flyclone\Exception\FileNotFoundException; use Verseles\Flyclone\Exception\DirectoryNotFoundException; use Verseles\Flyclone\Exception\TemporaryErrorException; try { $rclone->copy($source, $dest); } catch (FileNotFoundException $e) { // File doesn't exist - no retry needed } catch (DirectoryNotFoundException $e) { // Directory doesn't exist } catch (TemporaryErrorException $e) { // Temporary error - retry may succeed if ($e->isRetryable()) { // Can check programmatically } // Rich context available $context = $e->getContext(); // ['command' => '...', 'provider' => '...'] }
Automatic Retry
use Verseles\Flyclone\RetryHandler; // Simple retry configuration $rclone->retry(maxAttempts: 5, baseDelayMs: 1000) ->copy($source, $dest); // Advanced retry with custom handler $handler = RetryHandler::create() ->maxAttempts(5) ->baseDelay(500) ->multiplier(2.0) ->maxDelay(30000) ->onRetry(fn($attempt, $e) => logger("Retry $attempt: {$e->getMessage()}")); $rclone->withRetry($handler)->copy($source, $dest);
Filtering
use Verseles\Flyclone\FilterBuilder; // Filter by extension and size $rclone->withFilter( FilterBuilder::create() ->extensions(['jpg', 'png', 'gif']) ->minSize('100K') ->maxSize('50M') ->exclude('**/thumbnails/**') )->copy($source, $dest); // Filter by age $rclone->withFilter( FilterBuilder::create() ->newerThan('7d') // Last 7 days ->include('*.log') )->sync($source, $dest);
Dry-Run Mode
// Preview what would happen without making changes $rclone->dryRun(true)->sync($source, $dest); // Check if dry-run is enabled if ($rclone->isDryRun()) { echo "Running in simulation mode"; }
Health Check
// Verify provider connectivity $health = $rclone->healthCheck(); if ($health->healthy) { echo "Connected in {$health->latency_ms}ms"; } else { echo "Failed: {$health->error}"; }
Debugging
use Verseles\Flyclone\Logger; // Enable debug mode to log all commands Logger::setDebugMode(true); // After an operation, inspect what was executed $rclone->copy($source, $dest); echo $rclone->getLastCommand(); // "rclone copy ..." // Get redacted environment variables $envs = $rclone->getLastEnvs(); // Secrets are [REDACTED] // Retrieve all debug logs $logs = Logger::getLogs();
Testing
# Install dependencies composer install # Run quick tests (local provider only) make test # Run full offline test suite (requires podman-compose) make test-offline # Run specific provider tests (requires .env configuration) make test_dropbox make test_gdrive
Architecture
Flyclone v4 uses a modular architecture:
| Component | Responsibility |
|---|---|
Rclone |
Main orchestrator, public API |
ProcessManager |
Process execution, binary detection, error mapping |
CommandBuilder |
Command construction, environment variables |
StatsParser |
Transfer statistics parsing |
ProgressParser |
Real-time progress parsing |
RetryHandler |
Exponential backoff retry mechanism |
FilterBuilder |
Fluent API for include/exclude patterns |
SecretsRedactor |
Sensitive data redaction in errors/logs |
Logger |
Structured logging with debug mode |
Contributing
- Fork the repository
- Create a feature branch
- Write tests for new functionality
- Ensure all tests pass:
make test-offline - Submit a pull request
Changelog
v4.0.0 (In Development)
Feature 1: Core Refactoring (alpha)
- Extracted
ProcessManager,CommandBuilder,StatsParser,ProgressParserfrom monolithicRcloneclass - Fixed
CryptProviderandUnionProvider- now fully functional - Added
ConfigurationTest(13 tests) andEdgeCasesTest(13 tests) - Migrated to
podman-compose
Feature 2: Security & DX (beta)
- Added
SecretsRedactor- automatic redaction of sensitive data in errors - Added
RetryHandler- exponential backoff for transient failures - Added
FilterBuilder- fluent API for include/exclude patterns - Added
Logger- structured logging with debug mode - Added
healthCheck()- provider connectivity verification - Added
dryRun()- simulation mode for operations - Added command introspection (
getLastCommand(),getLastEnvs()) - Added exception context (
isRetryable(),getContext()) - Added credential validation warnings for plaintext passwords
- Added
Feature2Test(28 tests), 125+ tests total
Feature 3: Polish & Release (rc)
- Integrated PHPStan (level 5) and Laravel Pint (PSR-12) with CI
- Added new commands:
bisync(),md5sum(),sha1sum() - Added static utilities:
listRemotes(),configFile(),configDump() - Formatted entire codebase with
declare(strict_types=1) - All tests passing (150+ tests)
v3.x
- Transfer operations return detailed statistics object
- Progress tracking improvements
License
Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International