aethel 0.2.5 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/README.md +86 -102
- package/package.json +1 -1
- package/src/cli.js +92 -181
- package/src/core/diff.js +7 -9
- package/src/core/drive-api.js +56 -13
- package/src/core/repository.js +309 -0
- package/src/core/snapshot.js +14 -3
- package/src/tui/app.js +530 -70
- package/src/tui/command-catalog.js +140 -0
- package/src/tui/commands.js +74 -0
- package/src/tui/index.js +12 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.0 (2026-04-05)
|
|
4
|
+
|
|
5
|
+
- Refactor to Repository pattern; add TUI command system with catalog, CLI runner, and tests
|
|
6
|
+
|
|
7
|
+
## 0.2.6 (2026-04-05)
|
|
8
|
+
|
|
9
|
+
- Rewrite README with clearer structure and usage examples
|
|
10
|
+
|
|
3
11
|
## 0.2.5 (2026-04-05)
|
|
4
12
|
|
|
5
13
|
- Fix Node.js v25 Proxy invariant violation in withDriveRetry
|
package/README.md
CHANGED
|
@@ -5,12 +5,11 @@
|
|
|
5
5
|
[](LICENSE)
|
|
6
6
|
[](https://nodejs.org)
|
|
7
7
|
|
|
8
|
-
**Git-style Google Drive sync
|
|
8
|
+
**Git-style Google Drive sync from your terminal.**
|
|
9
9
|
|
|
10
|
-
Aethel
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
across local and remote directories.
|
|
10
|
+
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.
|
|
11
|
+
|
|
12
|
+
---
|
|
14
13
|
|
|
15
14
|
## Install
|
|
16
15
|
|
|
@@ -18,96 +17,89 @@ across local and remote directories.
|
|
|
18
17
|
npm install -g aethel
|
|
19
18
|
```
|
|
20
19
|
|
|
21
|
-
|
|
20
|
+
<details>
|
|
21
|
+
<summary>Install from source</summary>
|
|
22
22
|
|
|
23
23
|
```bash
|
|
24
|
-
git clone https://github.com/
|
|
25
|
-
cd
|
|
24
|
+
git clone https://github.com/CCJ-0617/Aethel.git
|
|
25
|
+
cd Aethel
|
|
26
26
|
npm install
|
|
27
27
|
npm run install:cli # symlinks `aethel` into ~/.local/bin
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
</details>
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
**Requires Node.js >= 18**
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
- publish contents are restricted through the `files` allowlist
|
|
36
|
-
- local secrets such as `credentials.json` and `token.json` are excluded from Git and npm publish
|
|
37
|
-
- release validation runs with `npm test` and `npm run pack:check`
|
|
34
|
+
## Setup
|
|
38
35
|
|
|
39
|
-
|
|
36
|
+
1. Create a project in the [Google Cloud Console](https://console.cloud.google.com/)
|
|
37
|
+
2. Enable the **Google Drive API**
|
|
38
|
+
3. Create an **OAuth 2.0 Client ID** (Desktop application)
|
|
39
|
+
4. Download the credentials JSON and save it as `credentials.json` in your project root
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
```bash
|
|
42
|
+
aethel auth # opens browser, saves token.json
|
|
43
|
+
aethel init --local-path ./workspace --drive-folder <folder-id>
|
|
44
|
+
```
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
> `credentials.json` and `token.json` are local secrets — never commit them.
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
- owner: `CCJ-0617`
|
|
50
|
-
- repository: `Aethel`
|
|
51
|
-
- workflow filename: `version.yml`
|
|
48
|
+
## Usage
|
|
52
49
|
|
|
53
|
-
|
|
50
|
+
```bash
|
|
51
|
+
aethel status # local vs remote changes at a glance
|
|
52
|
+
aethel diff --side all # detailed file-level diff
|
|
53
|
+
aethel add --all # stage default suggested actions
|
|
54
|
+
aethel commit -m "sync" # execute staged operations
|
|
54
55
|
|
|
55
|
-
|
|
56
|
+
aethel pull -m "pull" # fetch remote changes and apply
|
|
57
|
+
aethel push -m "push" # push local changes to Drive
|
|
58
|
+
```
|
|
56
59
|
|
|
57
|
-
|
|
58
|
-
2. Enable the **Google Drive API**.
|
|
59
|
-
3. Create an **OAuth 2.0 Client ID** (application type: Desktop).
|
|
60
|
-
4. Download the credentials JSON and save it as `credentials.json` in your
|
|
61
|
-
project root (or set `GOOGLE_DRIVE_CREDENTIALS_PATH`).
|
|
60
|
+
### Conflict Resolution
|
|
62
61
|
|
|
63
|
-
|
|
62
|
+
When both local and remote change the same path:
|
|
64
63
|
|
|
65
|
-
|
|
64
|
+
```bash
|
|
65
|
+
aethel status # identify conflicts
|
|
66
|
+
aethel resolve <path> --keep local # or: remote, both
|
|
67
|
+
aethel commit -m "resolve"
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Deduplication
|
|
71
|
+
|
|
72
|
+
Multi-device conflicts can leave duplicate folders on Drive:
|
|
66
73
|
|
|
67
74
|
```bash
|
|
68
|
-
#
|
|
69
|
-
aethel
|
|
70
|
-
|
|
71
|
-
# Initialize a sync workspace
|
|
72
|
-
aethel init --local-path ./workspace
|
|
73
|
-
|
|
74
|
-
# Optional: target a specific Drive folder
|
|
75
|
-
aethel init --local-path ./workspace \
|
|
76
|
-
--drive-folder <folder-id> \
|
|
77
|
-
--drive-folder-name "My Project"
|
|
78
|
-
|
|
79
|
-
# Check status and sync
|
|
80
|
-
aethel status
|
|
81
|
-
aethel diff --side all
|
|
82
|
-
aethel add --all
|
|
83
|
-
aethel commit -m "initial sync"
|
|
84
|
-
aethel pull -m "pull"
|
|
85
|
-
aethel push -m "push"
|
|
86
|
-
aethel log -n 10
|
|
75
|
+
aethel dedupe-folders # dry run — report only
|
|
76
|
+
aethel dedupe-folders --execute # merge duplicates, trash empties
|
|
87
77
|
```
|
|
88
78
|
|
|
79
|
+
Processes deepest-first for single-pass convergence, caches child state to minimize API calls, and runs independent merge groups in parallel.
|
|
80
|
+
|
|
89
81
|
## Commands
|
|
90
82
|
|
|
91
83
|
| Command | Description |
|
|
92
84
|
|---------|-------------|
|
|
93
|
-
| `auth` |
|
|
85
|
+
| `auth` | OAuth flow — creates `token.json`, verifies Drive access |
|
|
94
86
|
| `init` | Initialize a local sync workspace |
|
|
95
|
-
| `status` | Show
|
|
96
|
-
| `diff` |
|
|
97
|
-
| `add` | Stage changes
|
|
87
|
+
| `status` | Show local vs remote changes |
|
|
88
|
+
| `diff` | Detailed file differences |
|
|
89
|
+
| `add` | Stage changes |
|
|
98
90
|
| `reset` | Unstage changes |
|
|
99
91
|
| `commit` | Execute staged sync operations |
|
|
100
|
-
| `pull` | Fetch remote changes
|
|
101
|
-
| `push` |
|
|
102
|
-
| `log` |
|
|
103
|
-
| `fetch` | Refresh remote state without applying
|
|
104
|
-
| `resolve` | Resolve conflicts
|
|
105
|
-
| `ignore` |
|
|
106
|
-
| `show` |
|
|
92
|
+
| `pull` | Fetch and apply remote changes |
|
|
93
|
+
| `push` | Push local changes to Drive |
|
|
94
|
+
| `log` | Sync history |
|
|
95
|
+
| `fetch` | Refresh remote state without applying |
|
|
96
|
+
| `resolve` | Resolve conflicts (local / remote / both) |
|
|
97
|
+
| `ignore` | Manage `.aethelignore` patterns |
|
|
98
|
+
| `show` | Inspect a saved snapshot |
|
|
107
99
|
| `restore` | Restore files from the last snapshot |
|
|
108
100
|
| `rm` | Remove local files and stage remote deletion |
|
|
109
101
|
| `mv` | Move or rename local files |
|
|
110
|
-
| `clean` | List and optionally trash/delete
|
|
102
|
+
| `clean` | List and optionally trash/delete Drive files |
|
|
111
103
|
| `dedupe-folders` | Detect and merge duplicate remote folders |
|
|
112
104
|
| `tui` | Launch interactive terminal UI |
|
|
113
105
|
|
|
@@ -117,56 +109,36 @@ aethel log -n 10
|
|
|
117
109
|
aethel tui
|
|
118
110
|
```
|
|
119
111
|
|
|
120
|
-
Dual-pane file browser
|
|
121
|
-
the right.
|
|
112
|
+
Dual-pane file browser — local filesystem on the left, Google Drive on the right.
|
|
122
113
|
|
|
123
114
|
| Key | Action |
|
|
124
115
|
|-----|--------|
|
|
125
|
-
| `Tab` | Switch
|
|
116
|
+
| `Tab` | Switch panes |
|
|
126
117
|
| `Left` / `Right` | Navigate up / into directories |
|
|
127
|
-
| `u` | Upload selected local file or folder to
|
|
128
|
-
| `s` | Batch sync local folder
|
|
129
|
-
| `U` | Upload from a manually entered
|
|
118
|
+
| `u` | Upload selected local file or folder to Drive |
|
|
119
|
+
| `s` | Batch sync local folder to current Drive directory |
|
|
120
|
+
| `U` | Upload from a manually entered path |
|
|
130
121
|
| `n` | Rename selected local item |
|
|
131
122
|
| `x` | Delete selected local item |
|
|
132
123
|
| `Space` | Toggle selection in Drive pane |
|
|
133
124
|
| `t` / `d` | Trash / permanently delete selected Drive items |
|
|
134
125
|
| `/` | Filter by name |
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
When duplicate folders accumulate from multi-device conflicts, run:
|
|
139
|
-
|
|
140
|
-
```bash
|
|
141
|
-
# Dry run — report duplicates without changing anything
|
|
142
|
-
aethel dedupe-folders
|
|
143
|
-
|
|
144
|
-
# Execute — merge duplicates and trash empty losers
|
|
145
|
-
aethel dedupe-folders --execute
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
The deduplication engine processes folders deepest-first to guarantee
|
|
149
|
-
single-pass convergence, caches child state in memory to minimize API calls,
|
|
150
|
-
and runs independent merge groups in parallel. Paths matching `.aethelignore`
|
|
151
|
-
are excluded automatically.
|
|
126
|
+
| `f` | Open the commands page and choose a TUI action |
|
|
127
|
+
| `:` | Run any Aethel CLI command inside the TUI |
|
|
152
128
|
|
|
153
129
|
## Ignore Patterns
|
|
154
130
|
|
|
155
|
-
Create
|
|
156
|
-
exclude paths from sync and deduplication:
|
|
131
|
+
Create `.aethelignore` (gitignore syntax) in your workspace root — or run `aethel init` to generate a default one.
|
|
157
132
|
|
|
158
133
|
```gitignore
|
|
159
134
|
.venv/
|
|
160
135
|
node_modules/
|
|
161
136
|
__pycache__/
|
|
162
137
|
.idea/
|
|
163
|
-
.vscode/
|
|
164
138
|
dist/
|
|
165
139
|
build/
|
|
166
140
|
```
|
|
167
141
|
|
|
168
|
-
A default `.aethelignore` is created on `init`.
|
|
169
|
-
|
|
170
142
|
## Environment Variables
|
|
171
143
|
|
|
172
144
|
| Variable | Default | Description |
|
|
@@ -177,19 +149,31 @@ A default `.aethelignore` is created on `init`.
|
|
|
177
149
|
|
|
178
150
|
## Architecture
|
|
179
151
|
|
|
180
|
-
|
|
181
|
-
flow.
|
|
182
|
-
|
|
183
|
-
## Publishing
|
|
152
|
+
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.
|
|
184
153
|
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
154
|
+
```
|
|
155
|
+
src/
|
|
156
|
+
├── cli.js CLI entry — all handlers use Repository
|
|
157
|
+
├── core/
|
|
158
|
+
│ ├── repository.js Unified data-access layer
|
|
159
|
+
│ ├── auth.js OAuth authentication
|
|
160
|
+
│ ├── config.js Workspace config & state persistence
|
|
161
|
+
│ ├── diff.js Change detection between states
|
|
162
|
+
│ ├── drive-api.js Google Drive API wrapper
|
|
163
|
+
│ ├── local-fs.js Local filesystem operations
|
|
164
|
+
│ ├── remote-cache.js Short-lived remote file cache
|
|
165
|
+
│ ├── snapshot.js Local scanning & snapshot creation
|
|
166
|
+
│ ├── staging.js Stage/unstage operations
|
|
167
|
+
│ ├── sync.js Execute staged changes
|
|
168
|
+
│ └── ignore.js .aethelignore pattern matching
|
|
169
|
+
└── tui/
|
|
170
|
+
├── app.js React (Ink) dual-pane component
|
|
171
|
+
├── index.js TUI entry
|
|
172
|
+
├── commands.js CLI command parser for TUI
|
|
173
|
+
└── command-catalog.js Available TUI commands
|
|
189
174
|
```
|
|
190
175
|
|
|
191
|
-
|
|
192
|
-
the published npm version.
|
|
176
|
+
See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for detailed module structure and data flow.
|
|
193
177
|
|
|
194
178
|
## Contributing
|
|
195
179
|
|