A (work in progress and unofficial) Python implementation of a Filen Command Line Interface for encrypted cloud storage with path-based operations, batching with resume support, and comprehensive file management.
This is an unofficial, open-source project and is not affiliated with, endorsed by, or supported by Filen. It is a personal project built for learning and to provide an alternative interface. Use it at your own risk.
- β Chunk-level resume: Interrupted uploads/downloads resume from the exact chunk where they stopped.
- β Batch state persistence: All progress saved automatically, survive crashes and network failures.
- β Pattern filtering: Include/exclude files with glob patterns during batch operations.
- β Conflict handling: Smart conflict resolution (skip/overwrite/newer) for uploads and downloads.
- β Progress tracking: Real-time progress for individual files and entire batches.
- β
Human-readable paths: Use
/Documents/report.pdfinstead of UUIDs. - β
Client-side search: Find files recursively with wildcard patterns like
*.pdf. - β Tree visualization: See your folder structure at a glance.
- β Path navigation: Browse folders like your local filesystem.
- β Path resolution: Automatic path-to-UUID conversion with caching.
- β Timestamp Preservation: Preserves original file modification dates on upload and download.
- β Secure authentication: Login/logout with 2FA support.
- β File verification: SHA-512 hash verification without re-downloading files.
- β Trash operations: Move to trash, restore, and permanent deletion.
- β Folder management: Create folders recursively, move, rename, copy.
- β Zero-knowledge encryption: AES-256-GCM client-side encryption with metadata protection.
- β Start/Stop control: Manage background WebDAV server instances.
- β Status checking: Monitor server health and availability.
- β Mount instructions: Platform-specific mounting guides.
- β SSL certificate management: Auto-generate and validate self-signed certificates.
β οΈ Note: Full WebDAV server implementation requires additional dependencies (not included).
# Install dependencies
pip install -r requirements.txt
# Login to your account
python filen.py login
# Use path-based commands
python filen.py ls /Documents -d
python filen.py upload -r -p ./my-docs /Backups
python filen.py download-path -r /Photos ./local-photos -p
python filen.py find / "*.pdf" --maxdepth 3
python filen.py tree /Projects -l 2# Login with interactive prompts
python filen.py login
# Check current user
python filen.py whoami
# Logout and clear credentials
python filen.py logoutThe CLI will automatically detect if 2FA is required and prompt for the code.
# List root folder with readable paths
python filen.py ls /
# List specific folders
python filen.py ls /Documents
python filen.py ls /Photos/2023/Summer
# Show detailed information (size, date, UUID)
python filen.py ls /Documents -d --uuids
# Show folder structure as tree
python filen.py tree /
python filen.py tree /Projects -l 2 # Limit depth to 2 levels# Client-side recursive search with wildcards
python filen.py find / "*.pdf" # All PDF files
python filen.py find /Documents "report*" # Files starting with "report"
python filen.py find /Photos "*.jpg" --maxdepth 2 # JPGs, max 2 levels deep
# Simple search (uses find with wildcards)
python filen.py search "*.pdf"
# Debug path resolution
python filen.py resolve "/Documents/report.pdf"# Upload a single file, preserving timestamp
python filen.py upload ./report.pdf -t /Documents -p
# Upload folder recursively with timestamps
python filen.py upload -r -p ./my-project -t /Backups
# Upload with pattern filtering
python filen.py upload -r ./photos -t /Photos --include "*.jpg" --include "*.png"
# Upload with conflict handling
python filen.py upload ./file.pdf -t /Docs --on-conflict overwrite
python filen.py upload -r ./folder -t /Backup --on-conflict newer # Only if local is newer
# Resume interrupted upload (automatic)
# If upload is interrupted, just run the same command again:
python filen.py upload -r ./large-folder -t /Backups -p
# β Will automatically resume from last completed chunkBatch Features:
- Each batch gets a unique ID (shown at start)
- State saved after every chunk (throttled to avoid excessive I/O)
- Re-running the same command automatically resumes
- State cleaned up on successful completion
# Download single file by path
python filen.py download /Documents/report.pdf
# Download single file by UUID
python filen.py download a1b2c3d4-e5f6-7890-abcd-ef1234567890
# Download with custom output name
python filen.py download /file.pdf -o ./local-file.pdf
# Download folder recursively
python filen.py download-path -r /Photos -t ./local-photos -p
# Download with pattern filtering
python filen.py download-path -r /Music -t ./my-music --include "*.mp3" --exclude "demo_*"
# Download with conflict handling
python filen.py download-path /folder -t ./local --on-conflict newer
# Resume interrupted download (automatic)
python filen.py download-path -r /LargeFolder -t ./local -p
# β Will automatically resume from where it stopped# Verify upload without re-downloading (compares SHA-512 hashes)
python filen.py verify /Documents/report.pdf ./local-report.pdf
python filen.py verify a1b2c3d4-uuid ./local-file.pdf
# Returns exit code 0 if hashes match, 1 if they don't# Create folders (recursive)
python filen.py mkdir /Projects/NewProject/src
# Move items
python filen.py mv /Documents/old.pdf /Archive
# Copy files (download + re-upload)
python filen.py cp /file.pdf /Backup/file-copy.pdf
# Rename items
python filen.py rename /Documents/old-name.pdf new-name.pdf# Move to trash (recoverable)
python filen.py trash /OldFolder
python filen.py trash /Documents/outdated.pdf # With confirmation prompt
python filen.py trash /file.pdf -f # Skip confirmation
# List trash contents
python filen.py list-trash
python filen.py list-trash --uuids # Show full UUIDs
# Restore from trash
python filen.py restore-uuid a1b2c3d4-uuid # By UUID
python filen.py restore-path "filename.pdf" # By name (errors if multiple matches)
# Permanent delete (β οΈ cannot be undone)
python filen.py delete-path /TempFile.txt # With warning and confirmation
python filen.py delete-path /folder -f # Skip confirmationNote: These commands control WebDAV server instances. Full server implementation requires additional dependencies (like wsgidav).
# Start WebDAV server
python filen.py webdav-start # Foreground mode
python filen.py webdav-start -b # Background mode
python filen.py webdav-start --port 8080 # Custom port
# Check server status
python filen.py webdav-status
python filen.py webdav-status --port 8080
# Test server connection
python filen.py webdav-test
python filen.py webdav-test --port 8080
# Show mount instructions for your OS
python filen.py webdav-mount
python filen.py webdav-mount --port 8080
# Show server configuration
python filen.py webdav-config
# Stop server
python filen.py webdav-stopDefault WebDAV credentials:
- URL:
http://localhost:8080 - Username:
filen - Password:
filen-webdav
# Show configuration and paths
python filen.py config
# Get help
python filen.py --help
python filen.py <command> --help
# Enable verbose debug output
python filen.py -v upload ./file.pdf -t /Documents
# Force operations (skip confirmations)
python filen.py -f trash /folder# Clone the repository
git clone https://github.com/yourusername/filen-python-cli.git
cd filen-python-cli
# Install dependencies
pip install -r requirements.txt
# Create directory structure
mkdir -p filen_cli/config filen_cli/services
# Copy all files to appropriate locations:
# - filen.py (entry point)
# - filen_cli/cli.py
# - filen_cli/config/config.py
# - filen_cli/services/auth.py
# - filen_cli/services/api.py
# - filen_cli/services/crypto.py
# - filen_cli/services/drive.py
# - filen_cli/services/network_utils.py
# Start using immediately
python filen.py login
python filen.py ls /- Python 3.8+
- Dependencies:
cryptography- AES-256-GCM encryptionrequests- HTTP API client
requests>=2.28.0
cryptography>=41.0.0This CLI implements the same security model as official Filen clients:
- Client-side encryption: All files encrypted on your device before upload (AES-256-GCM).
- Zero-knowledge: Filen servers never see your unencrypted data or keys.
- Metadata protection: File names and metadata encrypted with version "002" format.
- PBKDF2 key derivation: 200,000 iterations for password-based key derivation.
- Per-chunk encryption: Each 1MB chunk encrypted separately with unique IV.
- SHA-512 hashing: File integrity verification with SHA-512 hashes.
- Secure credentials: Stored locally in
~/.filen-cli/credentials.json.
- File encryption: AES-256-GCM, 1MB chunks, 12-byte IV prepended to each chunk
- Metadata encryption: AES-256-GCM with "002" version prefix, 12-byte IV
- Filename hashing: HMAC-SHA-256 using master key + email
- File hashing: SHA-512 computed in 1MB chunks
- Key derivation: PBKDF2-HMAC-SHA512, 200,000 iterations, 64-byte output
filen-python-cli/
βββ filen.py # Entry point
βββ filen_cli/
β βββ cli.py # Main CLI interface
β βββ config/
β β βββ config.py # Configuration & state management
β βββ services/
β βββ auth.py # Authentication & session management
β βββ api.py # HTTP API client with retry logic
β βββ crypto.py # Encryption/decryption/hashing
β βββ drive.py # File operations, batching, caching
β βββ network_utils.py # WebDAV utilities & SSL management
βββ requirements.txt
config.py
- Directory structure:
~/.filen-cli/ - Credentials storage (unencrypted JSON)
- Batch state persistence (individual JSON files per batch)
- WebDAV configuration and PID management
- Batch ID generation (SHA1-based)
crypto.py
- PBKDF2 key derivation (200k iterations)
- AES-256-GCM encryption/decryption
- Metadata encryption with "002" prefix
- Filename hashing with HMAC-SHA256
- File hashing with SHA-512
api.py
- Automatic retry with exponential backoff
- All Filen API endpoints (v3)
- Upload/download chunk handling
- Error handling and status checks
drive.py (largest module, ~1000 lines)
- Path resolution with caching (10-minute TTL)
- Chunked upload/download (1MB chunks)
- Batch operations with resume support
- File/folder operations (create, move, rename, copy, delete)
- Trash operations (trash, restore, list, permanent delete)
- Search and find functionality
- Tree visualization
- SHA-512 verification
auth.py
- Login flow with 2FA support
- Master key decryption
- Session validation
- Credential management
network_utils.py
- WebDAV server status checking
- SSL certificate generation and validation
- Process management (start/stop servers)
- Connection testing
# Clone and setup development environment
git clone https://github.com/yourusername/filen-python-cli.git
cd filen-python-cli
# Create virtual environment
python -m venv venv
source venv/bin/activate # Linux/macOS
# or
venv\Scripts\activate # Windows
# Install dependencies
pip install -r requirements.txt
# Run tests (if implemented)
python -m pytest tests/
# Try it out
python filen.py login
python filen.py ls /- Batch ID Generation: SHA1 hash of operation type + sources + target (first 16 chars)
- State Structure: JSON file per batch with tasks array
- Task States:
pending,uploading,interrupted,completed,skipped_*,error_* - Resume Detection: Checks for
interruptedoruploadingstatus withlastChunk >= 0 - State Persistence: Saved after each chunk (throttled: every 10 chunks or 5 seconds)
- Cleanup: State deleted on successful completion
{
"batchId": "a1b2c3d4e5f67890",
"operation": "upload",
"source": ["./folder"],
"target": "/Backups",
"createdAt": "2024-12-01T12:00:00Z",
"updatedAt": "2024-12-01T12:05:30Z",
"tasks": [
{
"localPath": "./folder/file1.pdf",
"remotePath": "/Backups/file1.pdf",
"status": "completed",
"fileUuid": "uuid-here",
"uploadKey": "key-here",
"lastChunk": 10
},
{
"localPath": "./folder/file2.pdf",
"remotePath": "/Backups/file2.pdf",
"status": "interrupted",
"fileUuid": "uuid-here",
"uploadKey": "key-here",
"lastChunk": 5
}
]
}# Start upload
python filen.py upload -r ./large-folder -t /Backups -p
# Batch ID: abc123def4567890
# Uploading file1.pdf... 50% (5/10 chunks)
# [Connection lost or Ctrl+C]
# Resume upload (same command)
python filen.py upload -r ./large-folder -t /Backups -p
# Batch ID: abc123def4567890 (same ID)
# β
Resuming from previous batch
# Uploading file1.pdf... Resuming from chunk 6/10
# β
file1.pdf completed
# Uploading file2.pdf...Backup local folder to Filen:
python filen.py upload -r -p ~/Documents /Backups/Documents-$(date +%Y%m%d)Download entire project folder:
python filen.py download-path -r /Projects/MyApp -t ~/code/MyApp -pSync photos (only newer files):
python filen.py upload -r -p ~/Photos /Photos --on-conflict newerFind all PDFs and verify one:
python filen.py find / "*.pdf"
python filen.py verify /Documents/important.pdf ~/local-copy.pdfClean up trash:
python filen.py list-trash
python filen.py restore-path "important-file.pdf"
python filen.py delete-path /trash/old-stuff -f # Permanent deleteBrowse and explore:
python filen.py tree / -l 3 # Overview
python filen.py ls /Projects -d # Detailed view
python filen.py resolve "/path/to/file" # Debug resolution# Enable verbose mode to see full error details
python filen.py -v login
# Check credentials file
cat ~/.filen-cli/credentials.json
# Clear credentials and re-login
python filen.py logout
python filen.py login# Enable verbose mode
python filen.py -v upload ./file.pdf -t /Documents
# Check batch state (if interrupted)
ls ~/.filen-cli/batch_states/
# Force overwrite conflicts
python filen.py upload ./file.pdf -t /Documents --on-conflict overwrite
# Clear batch state manually (if corrupt)
rm ~/.filen-cli/batch_states/<batch-id>.json# Debug path resolution
python filen.py resolve "/path/to/item"
# List parent folder to verify
python filen.py ls /path/to
# Check folder structure
python filen.py tree /path -l 3