Git-style Google Drive sync from your terminal.
Aethel brings a snapshot → diff → stage → commit workflow to Google Drive. Track changes on both sides, resolve conflicts explicitly, and keep a full sync history — all without leaving the command line. It also ships with a dual-pane TUI for hands-on file management.
npm install -g aethelInstall from source
git clone https://github.com/CCJ-0617/Aethel.git
cd Aethel
npm install
npm run install:cli # symlinks `aethel` into ~/.local/binRequires Node.js >= 18
- Go to Google Cloud Console
- Create a project (or select an existing one)
- Enable the Google Drive API (APIs & Services → Library)
- Go to APIs & Services → Credentials
- Click Create Credentials → OAuth 2.0 Client ID
- Application type: Desktop application
- Download the JSON file
Save the downloaded JSON as ~/.config/aethel/credentials.json:
mkdir -p ~/.config/aethel
mv ~/Downloads/client_secret_*.json ~/.config/aethel/credentials.jsonYou can also place credentials.json in the current directory, or pass a custom path with --credentials.
aethel auth # opens browser, saves token.jsonaethel init --local-path ./my-drive # sync entire My Drive
aethel init --local-path ./workspace --drive-folder <folder-id> # sync specific folder
aethel pull --all -m "initial pull" # hydrate local files from the current remote tree
credentials.jsonandtoken.jsonare local secrets — never commit them.
aethel status # local vs remote changes at a glance
aethel diff --side all # detailed file-level diff
aethel add --all # stage default suggested actions
aethel commit -m "sync" # execute staged operations
aethel pull -m "pull" # fetch remote changes and apply
aethel pull --all # download the full remote tree to local
aethel push -m "push" # push local changes to Drivepull applies remote changes relative to the latest snapshot. Use pull --all for the first full download or to rehydrate a local workspace from the current remote tree.
When both local and remote change the same path:
aethel status # identify conflicts
aethel resolve <path> --keep local # or: remote, both
aethel commit -m "resolve"Multi-device conflicts can leave duplicate folders on Drive:
aethel dedupe-folders # dry run — report only
aethel dedupe-folders --execute # merge duplicates, trash emptiesProcesses deepest-first for single-pass convergence, caches child state to minimize API calls, and runs independent merge groups in parallel.
| Command | Description |
|---|---|
auth |
OAuth flow — creates token.json, verifies Drive access |
init |
Initialize a local sync workspace |
status |
Show local vs remote changes |
diff |
Detailed file differences |
add |
Stage changes |
reset |
Unstage changes |
commit |
Execute staged sync operations |
pull |
Fetch and apply remote changes (--all for full remote download) |
push |
Push local changes to Drive |
log |
Sync history |
fetch |
Refresh remote state without applying |
resolve |
Resolve conflicts (local / remote / both) |
ignore |
Manage .aethelignore patterns |
show |
Inspect a saved snapshot |
restore |
Restore files from the last snapshot |
rm |
Remove local files and stage remote deletion |
mv |
Move or rename local files |
clean |
List and optionally trash/delete Drive files |
dedupe-folders |
Detect and merge duplicate remote folders |
tui |
Launch interactive terminal UI |
aethel tuiDual-pane file browser — local filesystem on the left, Google Drive on the right.
| Key | Action |
|---|---|
Tab |
Switch panes |
Left / Right |
Navigate up / into directories |
u |
Upload selected local file or folder to Drive |
s |
Batch sync local folder to current Drive directory |
U |
Upload from a manually entered path |
n |
Rename selected local item |
x |
Delete selected local item |
Space |
Toggle selection in Drive pane |
t / d |
Trash / permanently delete selected Drive items |
/ |
Filter by name |
f |
Open the commands page and choose a TUI action |
: |
Run any Aethel CLI command inside the TUI |
Large directories with many small files (e.g., node_modules, vendor) can be slow to sync. Aethel can pack these into compressed archives for faster transfers.
Create .aethelconfig in your workspace root:
packing:
enabled: true
compression:
default:
algorithm: gzip # gzip, brotli, zstd, xz, or none
level: 6
rules:
- path: node_modules
strategy: full
- path: vendor
strategy: full- Tree Hash: Directories are fingerprinted using mtime+size (30x faster than MD5)
- Pack Detection:
aethel statusshows pack states (P+, PL, PR, P=, P!) - Compression: Archives use gzip/brotli (built-in) or zstd/xz (if installed)
| Code | Meaning |
|---|---|
P+ |
New pack (not yet synced) |
PL |
Pack changed locally |
PR |
Pack changed on Drive |
P= |
Pack up to date |
P! |
Pack conflict |
Use aethel status --verbose to show synced packs.
Create .aethelignore (gitignore syntax) in your workspace root — or run aethel init to generate a default one.
.venv/
node_modules/
__pycache__/
.idea/
dist/
build/| Variable | Default | Description |
|---|---|---|
GOOGLE_DRIVE_CREDENTIALS_PATH |
~/.config/aethel/credentials.json |
Path to OAuth credentials |
GOOGLE_DRIVE_TOKEN_PATH |
~/.config/aethel/token.json |
Path to cached OAuth token |
AETHEL_DRIVE_CONCURRENCY |
40 |
Max concurrent Drive API requests |
Aethel uses a Repository pattern — a single Repository class (src/core/repository.js) wraps all core modules and serves as the unified data-access layer for both the CLI and the TUI.
src/
├── cli.js CLI entry — all handlers use Repository
├── core/
│ ├── repository.js Unified data-access layer
│ ├── auth.js OAuth authentication
│ ├── config.js Workspace config & state persistence
│ ├── diff.js Change detection between states
│ ├── drive-api.js Google Drive API wrapper
│ ├── local-fs.js Local filesystem operations
│ ├── remote-cache.js Short-lived remote file cache
│ ├── snapshot.js Local scanning & snapshot creation
│ ├── staging.js Stage/unstage operations
│ ├── sync.js Execute staged changes
│ ├── ignore.js .aethelignore pattern matching
│ ├── compress.js Multi-algorithm compression (gzip, brotli, zstd, xz)
│ ├── pack.js Tar archive operations & tree hash
│ └── pack-manifest.js Pack manifest CRUD operations
└── tui/
├── app.js React (Ink) dual-pane component
├── index.js TUI entry
├── commands.js CLI command parser for TUI
└── command-catalog.js Available TUI commands
See docs/ARCHITECTURE.md for detailed module structure and data flow.
See CONTRIBUTING.md for development setup and guidelines.


