vflow-cli 0.1.1__tar.gz

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.
Files changed (30) hide show
  1. vflow_cli-0.1.1/PKG-INFO +543 -0
  2. vflow_cli-0.1.1/README.md +531 -0
  3. vflow_cli-0.1.1/pyproject.toml +19 -0
  4. vflow_cli-0.1.1/setup.cfg +4 -0
  5. vflow_cli-0.1.1/src/vflow/__init__.py +1 -0
  6. vflow_cli-0.1.1/src/vflow/actions.py +39 -0
  7. vflow_cli-0.1.1/src/vflow/backup_service.py +684 -0
  8. vflow_cli-0.1.1/src/vflow/config.py +44 -0
  9. vflow_cli-0.1.1/src/vflow/core/__init__.py +6 -0
  10. vflow_cli-0.1.1/src/vflow/core/date_utils.py +114 -0
  11. vflow_cli-0.1.1/src/vflow/core/fs_ops.py +64 -0
  12. vflow_cli-0.1.1/src/vflow/core/media_ops.py +110 -0
  13. vflow_cli-0.1.1/src/vflow/core/patterns.py +98 -0
  14. vflow_cli-0.1.1/src/vflow/delivery_service.py +301 -0
  15. vflow_cli-0.1.1/src/vflow/ingest_service.py +932 -0
  16. vflow_cli-0.1.1/src/vflow/main.py +571 -0
  17. vflow_cli-0.1.1/src/vflow_cli.egg-info/PKG-INFO +543 -0
  18. vflow_cli-0.1.1/src/vflow_cli.egg-info/SOURCES.txt +28 -0
  19. vflow_cli-0.1.1/src/vflow_cli.egg-info/dependency_links.txt +1 -0
  20. vflow_cli-0.1.1/src/vflow_cli.egg-info/entry_points.txt +2 -0
  21. vflow_cli-0.1.1/src/vflow_cli.egg-info/requires.txt +5 -0
  22. vflow_cli-0.1.1/src/vflow_cli.egg-info/top_level.txt +1 -0
  23. vflow_cli-0.1.1/tests/test_braw_and_prores_extensions.py +71 -0
  24. vflow_cli-0.1.1/tests/test_cli_backup_and_verify.py +92 -0
  25. vflow_cli-0.1.1/tests/test_cli_ingest_and_pull_filters.py +124 -0
  26. vflow_cli-0.1.1/tests/test_cli_ingest_report.py +70 -0
  27. vflow_cli-0.1.1/tests/test_cli_list_backups.py +48 -0
  28. vflow_cli-0.1.1/tests/test_cli_restore_folder.py +70 -0
  29. vflow_cli-0.1.1/tests/test_cli_verify_backup_mirror.py +39 -0
  30. vflow_cli-0.1.1/tests/test_patterns_and_duplicates.py +161 -0
@@ -0,0 +1,543 @@
1
+ Metadata-Version: 2.4
2
+ Name: vflow-cli
3
+ Version: 0.1.1
4
+ Summary: The v-flow CLI and Claude skills bundle for automating media backup and processing workflows for videographers.
5
+ Author-email: Kaung <kaungzinye@gmail.com>
6
+ Requires-Python: >=3.8
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: typer[all]
9
+ Requires-Dist: pyyaml
10
+ Provides-Extra: test
11
+ Requires-Dist: pytest; extra == "test"
12
+
13
+ # v-flow
14
+
15
+ > A CLI + Claude skills bundle to automate media backup and processing workflows for videographers.
16
+
17
+ **Last updated:** 2026-03-05
18
+
19
+ ---
20
+
21
+ ## Quick Start
22
+
23
+ ### For videographers (recommended)
24
+
25
+ 1. Install v-flow and its Claude skills in one step:
26
+
27
+ ```bash
28
+ curl -fsSL https://raw.githubusercontent.com/kaungzinye/v-flow/main/install_vflow.sh | bash
29
+ ```
30
+
31
+ 2. Configure storage paths (runs once per machine):
32
+
33
+ In a terminal, run:
34
+
35
+ ```bash
36
+ v-flow make-config
37
+ ```
38
+
39
+ Then edit `~/.vflow_config.yml` to point to your laptop ingest folder, work SSD, and archive drive.
40
+
41
+ Alternatively, in Claude Code or Cursor you can say:
42
+
43
+ > “Set up v-flow on this machine.”
44
+
45
+ and the **v-flow Setup Assistant** skill will guide you through the same wizard.
46
+
47
+ 3. After setup, in Claude Code or Cursor just ask:
48
+
49
+ - “Ingest my card and set up a project on my SSD.”
50
+ - “Back up my ingest folder and free up space.”
51
+ - “Show me duplicate clips from the last day.”
52
+
53
+ The bundled v-flow skills will call the local `v-flow` CLI for you using that config.
54
+
55
+ ### For developers
56
+
57
+ 1. Install the CLI:
58
+ - `pip install v-flow` (or run `pip install -e .` from this repo for local development).
59
+ 2. Configure: `v-flow make-config` and edit `~/.vflow_config.yml`.
60
+ 3. Explore commands:
61
+ - `v-flow --help` and `v-flow ingest --help`.
62
+
63
+ ---
64
+
65
+ ## Using v-flow with Claude skills
66
+
67
+ This repo includes a set of Claude-compatible Agent Skills under the `skills/` directory (for ingest, setup, backup, maintenance, and delivery/tagging).
68
+
69
+ - When you run the installer from Quick Start, those skills are copied into:
70
+ - `~/.claude/skills` for Claude Code.
71
+ - `~/.cursor/skills` for Cursor.
72
+ - In Claude / Cursor, the skills:
73
+ - Listen for intents like “ingest my card”, “back up my ingest folder”, “clean up duplicates”, or “archive this export”.
74
+ - Decide which `v-flow` commands to run (`v-flow ingest`, `v-flow backup`, `v-flow list-duplicates`, etc.).
75
+ - Ask you short clarification questions before doing anything destructive.
76
+
77
+ If you prefer manual setup instead of the installer, you can copy the folders from `skills/` into your tool’s skills directory and follow the same natural-language prompts.
78
+
79
+ ---
80
+
81
+ ## Table of Contents
82
+
83
+ - [Overview](#overview)
84
+ - [The v-flow Workflow](#the-v-flow-workflow)
85
+ - [Setup](#setup)
86
+ - [Workflow Commands](#workflow-commands)
87
+ - [ingest](#v-flow-ingest)
88
+ - [prep](#v-flow-prep)
89
+ - [pull](#v-flow-pull)
90
+ - [create-select](#v-flow-create-select)
91
+ - [archive](#v-flow-archive)
92
+ - [Utility Commands](#utility-commands)
93
+ - [consolidate](#v-flow-consolidate)
94
+ - [copy-meta](#v-flow-copy-meta)
95
+ - [backup](#v-flow-backup)
96
+ - [verify-backup](#v-flow-verify-backup)
97
+ - [list-backups](#v-flow-list-backups)
98
+ - [restore-folder](#v-flow-restore-folder)
99
+
100
+ ---
101
+
102
+ ## Overview
103
+
104
+ v-flow is designed around a professional media workflow that separates your storage into:
105
+
106
+ - **Archive** (large HDD) - Long-term storage for all raw footage and final exports
107
+ - **Workspace** (fast SSD) - Temporary workspace for active projects
108
+
109
+ This separation keeps your SSD clean and your media library organized.
110
+
111
+ ---
112
+
113
+ ## The v-flow Workflow
114
+
115
+ The lifecycle of a project follows these steps:
116
+
117
+ ### 1. **Ingest** → Backup new footage
118
+ Copy footage from SD card to both laptop and archive for immediate backup.
119
+
120
+ ### 2. **Prep or Pull** → Move to workspace
121
+ - **`prep`** - Move files from laptop ingest folder to work SSD (moves files)
122
+ - **`pull`** - Copy files from archive to work SSD (keeps archive intact, perfect for older footage)
123
+
124
+ ### 3. **Edit & Grade** → Create content
125
+ Work on your project and create reusable, graded clips.
126
+
127
+ ### 4. **Create Select** → Save graded clips
128
+ Tag and save graded clips for future use. Archives to permanent storage and places a copy in your project's selects folder.
129
+
130
+ ### 5. **Archive** → Finalize project
131
+ Tag the final export, archive it, and clean up source files from the SSD to free up space.
132
+
133
+ ---
134
+
135
+ ## Setup
136
+
137
+ ### Step 1: Create Configuration File
138
+
139
+ ```bash
140
+ v-flow make-config
141
+ ```
142
+
143
+ This creates `~/.vflow_config.yml` in your home directory.
144
+
145
+ ### Step 2: Configure Storage Paths
146
+
147
+ Edit `~/.vflow_config.yml` and update the paths to match your setup:
148
+
149
+ ```yaml
150
+ locations:
151
+ laptop: "/path/to/your/laptop/ingest/folder"
152
+ work_ssd: "/path/to/your/fast/ssd/projects"
153
+ archive_hdd: "/path/to/your/archive/hdd"
154
+ ```
155
+
156
+ **Important:** You must configure these paths before using v-flow commands.
157
+
158
+ ---
159
+
160
+ ## Workflow Commands
161
+
162
+ These commands follow the standard v-flow workflow from ingest to archive.
163
+
164
+ ---
165
+
166
+ ### `v-flow ingest`
167
+
168
+ Safely copies footage from an SD card to two separate locations (laptop and archive) for immediate backup. Supports automatic shoot naming by file date range and safety checks for duplicates.
169
+
170
+ #### Prerequisites
171
+ - Configured `~/.vflow_config.yml` file
172
+
173
+ #### Options
174
+
175
+ | Flag | Description |
176
+ |------|-------------|
177
+ | `--source, -s` | **(required)** Exact folder where videos exist (e.g., `.../M4ROOT/CLIP`) |
178
+ | `--shoot, -n` | **(optional if `--auto`)** Shoot folder name, e.g., `2025-10-12_ShootName` or `2025-10-12_to_2025-10-15_ShootName` |
179
+ | `--auto, -a` | Infer shoot name from date range of media files. If multiple days detected, uses a range |
180
+ | `--force, -f` | Bypass date-range validation warnings when `--shoot` name doesn't match detected file dates |
181
+ | `--skip-laptop` | Skip copying files to the laptop ingest folder (saves space) |
182
+ | `--workspace, -w` | Also ingest directly to the Workspace SSD (creates project structure) |
183
+ | `--split-by-gap` | Automatically split footage into multiple shoots if a time gap of X hours is detected (overrides config default) |
184
+
185
+ #### Configuration
186
+
187
+ You can set a default split gap in your `~/.vflow_config.yml`:
188
+
189
+ ```yaml
190
+ settings:
191
+ default_split_gap: 24 # Automatically split trips separated by 24+ hours
192
+ ```
193
+
194
+ #### Examples
195
+
196
+ **Standard ingest:**
197
+ ```bash
198
+ v-flow ingest --source "/Volumes/SDCARD/private/M4ROOT/CLIP" --auto
199
+ ```
200
+
201
+ **Ingest directly to Workspace (skipping laptop) and split trips:**
202
+ ```bash
203
+ v-flow ingest --source "/Volumes/SDCARD/private/M4ROOT/CLIP" --auto --skip-laptop --workspace --split-by-gap 24
204
+ ```
205
+
206
+ #### Behavior
207
+ - Recursively finds common video formats (.mp4, .mov, .mxf, .mts, .avi, .m4v)
208
+ - Derives date range from file creation/modification dates
209
+ - **Smart Splitting:** If `--split-by-gap` is set (or configured), splits footage into separate shoots based on time gaps
210
+ - **Storage Fallback:** If a destination drive is full, it skips that drive and continues to the Archive (ensuring backup)
211
+ - **Cross-shoot duplicate check:** Skips any file (by name + size) already present anywhere in laptop ingest or archive, not just in the current shoot folder. So if the 28th was already ingested, ingesting 28th+29th will only copy new files from the 29th.
212
+ - Detects existing shoots in laptop ingest and archive locations; copies only missing files
213
+ - Creates target shoot folders if needed
214
+
215
+ ---
216
+
217
+ ### `v-flow prep`
218
+
219
+ Prepares a shoot for editing by moving it from the laptop ingest folder to your fast work SSD. Creates a standard project structure.
220
+
221
+ #### Prerequisites
222
+ - Shoot must be in the laptop ingest folder (from `ingest`)
223
+
224
+ #### Usage
225
+ ```bash
226
+ v-flow prep --shoot <YYYY-MM-DD_ShootName>
227
+ ```
228
+
229
+ #### Project Structure Created
230
+ ```
231
+ <shoot_name>/
232
+ ├── 01_Source/ # Raw footage moved here
233
+ ├── 02_Resolve/ # DaVinci Resolve project files
234
+ ├── 03_Exports/ # Your exports go here
235
+ ├── 04_FinalRenders/ # Final renders
236
+ └── 05_Graded_Selects/ # Reusable graded clips
237
+ ```
238
+
239
+ #### Note
240
+ This **moves** files from ingest to work SSD. If your files are already archived and not in the ingest folder, use `pull` instead.
241
+
242
+ ---
243
+
244
+ ### `v-flow pull`
245
+
246
+ Pulls files from archive to your work SSD for editing. Copies (doesn't move) files so they remain safely in archive. Perfect for working with archived footage or creating quick edits.
247
+
248
+ #### Prerequisites
249
+ - Shoot must exist in the archive at:
250
+ - `/Video/RAW/[shoot_name]` for raw files
251
+ - `/Video/Graded_Selects/[shoot_name]` for graded selects
252
+
253
+ #### Options
254
+
255
+ | Flag | Description |
256
+ |------|-------------|
257
+ | `--shoot, -n` | **(required)** Name of the shoot to pull from archive |
258
+ | `--source, -s` | **(optional, default: `raw`)** What to pull:<br>• `raw` - Pull raw files from `Video/RAW/` → `01_Source/` (default)<br>• `selects` - Pull graded selects from `Video/Graded_Selects/` → `05_Graded_Selects/`<br>• `both` - Pull both raw files and graded selects to their respective folders |
259
+ | `--files, -f` | **(optional)** Specific filenames, patterns, or ranges to pull. Can be specified multiple times. Supports ranges like `C3317-C3351` (matches C3317 through C3351). If omitted, pulls all video files |
260
+
261
+ #### Examples
262
+
263
+ **Pull all raw files (for full grade):**
264
+ ```bash
265
+ v-flow pull --shoot 2025-10-12_Germany_Trip --source raw
266
+ ```
267
+
268
+ **Pull only graded selects (for quick TikTok edit):**
269
+ ```bash
270
+ v-flow pull --shoot 2025-10-12_Germany_Trip --source selects
271
+ ```
272
+
273
+ **Pull both raw and graded selects:**
274
+ ```bash
275
+ v-flow pull --shoot 2025-10-12_Germany_Trip --source both
276
+ ```
277
+
278
+ **Pull specific files with filter:**
279
+ ```bash
280
+ v-flow pull --shoot 2025-10-12_Germany_Trip --source selects --files "sunset" --files "beach"
281
+ ```
282
+
283
+ **Pull a range of files (e.g., C3317 to C3351):**
284
+ ```bash
285
+ v-flow pull --shoot Germany --source raw --files "C3317-C3351"
286
+ ```
287
+
288
+ #### Behavior
289
+ - Creates standard project structure on work SSD
290
+ - Raw files → `01_Source/` folder
291
+ - Graded selects → `05_Graded_Selects/` folder
292
+ - Files remain in archive (copy operation, not move)
293
+ - Skips files that already exist (based on filename and size)
294
+ - If a source directory doesn't exist, shows warning and continues with available sources
295
+
296
+ ---
297
+
298
+ ### `v-flow create-select`
299
+
300
+ Creates a reusable, tagged, graded clip from an export. Archives a copy to `/Video/Graded_Selects/` and places another copy in your active project's `05_Graded_Selects` folder on your SSD for immediate use.
301
+
302
+ #### Prerequisites
303
+ - Project must have been prepped
304
+ - Must have an exported video file in the `03_Exports` folder
305
+
306
+ #### Usage
307
+ ```bash
308
+ v-flow create-select --shoot <YYYY-MM-DD_ShootName> --file <graded_clip.mov> --tags "Graded Select, Tag, Another Tag"
309
+ ```
310
+
311
+ #### What Happens
312
+ 1. Tags the file with metadata (both universal metadata and macOS Finder tags)
313
+ 2. Copies metadata from original source file if available
314
+ 3. Archives a copy to `/Video/Graded_Selects/[shoot_name]/` in your archive
315
+ 4. Places a copy in `05_Graded_Selects/` folder on your work SSD
316
+
317
+ ---
318
+
319
+ ### `v-flow archive`
320
+
321
+ Archives a final project export. Embeds metadata tags, sends the file to `/Video/Graded/` in your archive, and optionally cleans up source files from the work SSD to save space.
322
+
323
+ #### Prerequisites
324
+ - Project must have been prepped
325
+ - Must have a final exported video file in the `03_Exports` folder
326
+
327
+ #### Usage
328
+ ```bash
329
+ v-flow archive --shoot <YYYY-MM-DD_ShootName> --file <final_export.mp4> --tags "Final, Project, Tag"
330
+ ```
331
+
332
+ #### Options
333
+
334
+ | Flag | Description |
335
+ |------|-------------|
336
+ | `--shoot, -n` | **(required)** Name of the shoot |
337
+ | `--file, -f` | **(required)** Filename of the exported video to archive |
338
+ | `--tags, -t` | **(required)** Comma-separated metadata tags |
339
+ | `--keep-log` | **(optional)** Do not delete source files from `01_Source/` folder |
340
+
341
+ #### What Happens
342
+ 1. Tags the file with metadata
343
+ 2. Archives to `/Video/Graded/` in your archive
344
+ 3. Optionally deletes source files from `01_Source/` folder (unless `--keep-log` is used)
345
+
346
+ ---
347
+
348
+ ## Utility Commands
349
+
350
+ These commands help with maintenance and migration tasks.
351
+
352
+ ---
353
+
354
+ ### `v-flow consolidate`
355
+
356
+ A utility for migrating legacy media. Finds and copies unique media from an external drive or folder into your archive without creating duplicates. Best used for importing old projects into the v-flow structure.
357
+
358
+ #### Prerequisites
359
+ - Configured `~/.vflow_config.yml` file
360
+
361
+ #### Usage
362
+ ```bash
363
+ v-flow consolidate --source <path-to-external-folder> --output-folder <NewFolderNameInArchive>
364
+ ```
365
+
366
+ #### Behavior
367
+ - Builds an index of existing archive files (by name and size)
368
+ - Scans source directory and copies only unique files
369
+ - Creates log files (`copied_files.txt` and `skipped_duplicates.txt`) in the output folder
370
+
371
+ ---
372
+
373
+ ### `v-flow copy-meta`
374
+
375
+ Copies metadata (like creation date) from original camera files to final exports by matching filenames in two folders. Useful for preserving original file metadata in your exports.
376
+
377
+ #### Prerequisites
378
+ - `ffmpeg` must be installed
379
+ - Source and target folders must contain files with matching filenames (extensions can differ)
380
+
381
+ #### Usage
382
+ ```bash
383
+ v-flow copy-meta --source-folder <path-to-originals> --target-folder <path-to-exports>
384
+ ```
385
+
386
+ #### Behavior
387
+ - Matches files by filename stem (ignoring extensions)
388
+ - Copies all metadata from source to target using ffmpeg
389
+ - Preserves video/audio streams from target file
390
+ - Uses stream copy (no re-encoding)
391
+
392
+ ---
393
+
394
+ ### `v-flow backup`
395
+
396
+ Backs up media from an arbitrary source folder (for example, an ingest folder on your laptop or SSD) into your archive with duplicate checks. This is a friendly wrapper around the `consolidate` logic and is ideal for safely emptying ingest folders after you have already ingested from SD.
397
+
398
+ #### Prerequisites
399
+ - Configured `~/.vflow_config.yml` file
400
+
401
+ #### Usage
402
+ ```bash
403
+ v-flow backup --source "/Users/you/Desktop/Ingest" --destination "Video/RAW/Desktop_Ingest"
404
+ ```
405
+
406
+ #### Options
407
+
408
+ | Flag | Description |
409
+ |------|-------------|
410
+ | `--source, -s` | **(required)** Source directory to back up (e.g., your ingest folder) |
411
+ | `--destination, -d` | **(required)** Path **relative to the archive root** where files will be copied (e.g., `Video/RAW/Desktop_Ingest`) |
412
+ | `--files, -f` | **(optional)** Specific filenames, patterns, or ranges to back up (e.g. `C3317`, `C3317-C3351`, or partial names). Can be specified multiple times |
413
+ | `--tags, -t` | **(optional)** Comma-separated metadata tags to add to copied files |
414
+ | `--dry-run` | Analyze what would be backed up without copying any files. Shows which files would be copied or skipped as duplicates |
415
+ | `--delete-source` | After copying, prompt to optionally delete source files that were successfully backed up |
416
+
417
+ #### Behavior
418
+ - Builds an index of existing archive files (by name and size) so it can skip duplicates that are already in the archive, even if they live in other folders.
419
+ - Scans the source directory and copies only unique files into `archive_hdd/<destination>`.
420
+ - Creates log files (`copied_files.txt` and `skipped_duplicates.txt`) in the destination folder.
421
+ - With `--delete-source`, tracks which files were actually copied and **after the copy completes** offers an interactive prompt to delete those source files.
422
+
423
+ #### Example: Backup and clean an ingest folder
424
+
425
+ ```bash
426
+ # 1) Dry-run to see what would be copied and what could be deleted
427
+ v-flow backup \
428
+ --source "/Users/you/Desktop/Ingest" \
429
+ --destination "Video/RAW/Desktop_Ingest" \
430
+ --dry-run \
431
+ --delete-source
432
+
433
+ # 2) Real backup with interactive delete prompt
434
+ v-flow backup \
435
+ --source "/Users/you/Desktop/Ingest" \
436
+ --destination "Video/RAW/Desktop_Ingest" \
437
+ --delete-source
438
+ ```
439
+
440
+ ---
441
+
442
+ ### `v-flow verify-backup`
443
+
444
+ Verifies that files in a source folder exist in a destination folder with matching sizes. Can be used directly after `backup` or after any other manual/automated copy to confirm that your backup is complete before deleting source files.
445
+
446
+ #### Usage
447
+
448
+ ```bash
449
+ # Simple path-for-path mirror check
450
+ v-flow verify-backup \
451
+ --source "/Users/you/Desktop/Ingest" \
452
+ --destination "/Volumes/Archive/Video/RAW/Desktop_Ingest"
453
+
454
+ # Archive-wide safety check (recommended for ingest folders)
455
+ v-flow verify-backup \
456
+ --source "/Users/you/Desktop/Ingest" \
457
+ --destination "/Volumes/Archive" \
458
+ --archive-wide
459
+ ```
460
+
461
+ #### Options
462
+
463
+ | Flag | Description |
464
+ |------|-------------|
465
+ | `--source, -s` | **(required)** Source directory to verify |
466
+ | `--destination, -d` | **(required)** Destination directory to check against |
467
+ | `--archive-wide` | Treat destination as an **archive root** and verify that each source file exists **anywhere under it** by name + size (ignores path differences) |
468
+ | `--allow-delete` | After a successful verification, prompt to delete all files under the source folder |
469
+
470
+ #### Behavior
471
+ - Compares all files under the source folder:
472
+ - In **mirror mode** (default), it checks that each file exists at the same relative path under destination with the same size.
473
+ - In **archive-wide mode**, it checks that each file exists **somewhere under the destination tree** with the same filename and size, regardless of exact path.
474
+ - Prints a summary (files checked, missing files, size mismatches) and lists a sample of any problems.
475
+ - If `--allow-delete` is set and verification **passes with no missing/mismatched files**, offers an interactive prompt to delete the source files.
476
+
477
+ ---
478
+
479
+ ### `v-flow list-backups`
480
+
481
+ Lists backup folders under a given subpath of your archive, including file counts, total sizes, and last modified times. Useful for quickly seeing what has been consolidated and how large each backup set is.
482
+
483
+ #### Usage
484
+
485
+ ```bash
486
+ v-flow list-backups --subpath "Video/RAW/Desktop_Ingest"
487
+ ```
488
+
489
+ #### Options
490
+
491
+ | Flag | Description |
492
+ |------|-------------|
493
+ | `--subpath, -p` | **(optional, default: `Video/RAW/Desktop_Ingest`)** Subpath under the archive root to scan for backup folders |
494
+
495
+ #### Behavior
496
+ - Uses the configured `archive_hdd` path from `~/.vflow_config.yml`.
497
+ - Looks under `archive_hdd/<subpath>` for immediate subfolders (each treated as a backup set).
498
+ - For each backup folder, prints:
499
+ - Folder name
500
+ - Number of files
501
+ - Total size (human-readable)
502
+ - Last modified timestamp (based on newest file inside)
503
+ - Sorted so that the most recently modified backups appear first.
504
+
505
+ ---
506
+
507
+ ### `v-flow restore-folder`
508
+
509
+ Restores (copies) an arbitrary folder tree from one location to another. This is the inverse of `backup` for general folders and can be used to pull a backup folder from your archive back to a workspace path.
510
+
511
+ #### Usage
512
+
513
+ ```bash
514
+ # Dry-run to see what would be restored
515
+ v-flow restore-folder \
516
+ --source "/Volumes/Archive/Video/RAW/Desktop_Ingest/2026-01-28_to_2026-01-29_Ingest" \
517
+ --destination "/Users/you/Workspace/Restored_2026-01-28" \
518
+ --dry-run
519
+
520
+ # Real restore
521
+ v-flow restore-folder \
522
+ --source "/Volumes/Archive/Video/RAW/Desktop_Ingest/2026-01-28_to_2026-01-29_Ingest" \
523
+ --destination "/Users/you/Workspace/Restored_2026-01-28"
524
+ ```
525
+
526
+ #### Options
527
+
528
+ | Flag | Description |
529
+ |------|-------------|
530
+ | `--source, -s` | **(required)** Source folder to restore from (e.g., an archive backup folder) |
531
+ | `--destination, -d` | **(required)** Destination folder to restore into (e.g., a workspace or temp folder) |
532
+ | `--dry-run` | Simulate the restore without copying any files. Shows what would be copied or overwritten |
533
+ | `--overwrite` | Allow overwriting destination files that differ in size. If false (default), such conflicts are reported and skipped |
534
+
535
+ #### Behavior
536
+ - Recreates the directory structure from `source` under `destination`.
537
+ - For each file:
538
+ - If the destination file **does not exist**, it is copied.
539
+ - If the destination file exists and has the **same size**, it is skipped.
540
+ - If the destination file exists and has a **different size**:
541
+ - With `--overwrite` **off** (default), the conflict is reported and the file is left unchanged.
542
+ - With `--overwrite` **on**, the destination file is overwritten.
543
+ - In `--dry-run` mode, logs which files **would** be copied or overwritten without touching disk.