| name | onboard |
| description | First-run setup for android-media-importer. Walk the user through defining one or more source→destination mappings (phone path → local path), pick layout options per mapping (flat / date-stamped / orientation-split), choose move-vs-copy semantics, and write everything to <workspace>/config.yaml. Use whenever the user says "set up the importer", "configure my phone import", or no config.yaml exists yet. |
android-media-importer: onboard
Interactive setup. Produces <workspace>/config.yaml consumed by import-media.
See _shared/workspace.md for how to resolve <workspace>.
Procedure
0. Preflight
adb devices — must show one device. If not, ask the user to plug in the phone, enable USB debugging, and confirm the trust dialog.
- Verify tools:
adb, file, exiftool, ffprobe. If any are missing, suggest the install command for the user's distro (Debian/Ubuntu: sudo apt install android-tools-adb file libimage-exiftool-perl ffmpeg).
1. Discover source candidates
Probe the phone for common camera / media roots and report which exist:
for p in /sdcard/DCIM/Camera /sdcard/DCIM /sdcard/Pictures/Screenshots \
/sdcard/Movies /sdcard/Recordings /sdcard/Music /sdcard/Download \
/sdcard/WhatsApp/Media; do
adb shell "[ -e $p ] && echo EXISTS $p || echo MISSING $p"
done
Show the user the list of EXISTS paths.
2. Define mappings (loop)
For each mapping the user wants, collect:
| Field | Notes |
|---|
label | human name, e.g. camera-photos, screenshots, voice-memos |
source | absolute phone path (must exist) |
recursive | true if the source is a tree (e.g. /sdcard/Recordings/ASR/ASR); false if just the directory's own files |
dest_root | absolute local path, e.g. /home/alice/Pictures/Phone |
route_by_mime | if true, split into image_dest / video_dest subtrees; if false, everything goes to dest_root |
image_dest | (only if route_by_mime) e.g. Photos, joined onto dest_root |
video_dest | (only if route_by_mime) e.g. Videos, joined onto dest_root |
date_folder | one of none / DDMM / DD-MM / YYYY-MM-DD / YYYYMMDD — date is "today at import time" |
orientation_split | true adds portrait/ and landscape/ leaf dirs (only meaningful for image/video mappings) |
mime_filter | optional allowlist: any / image,video / image / video / audio etc. Files outside the allowlist are skipped. |
mode | move (delete from phone after byte-size-verified copy) or copy (leave on phone) |
Default suggestions to offer the user:
- Camera →
route_by_mime=true, image_dest=Photos, video_dest=Videos, date_folder=YYYY-MM-DD, orientation_split=true, mode=move.
- Screenshots → flat,
date_folder=none, orientation_split=false, mode=move.
- Voice recordings → flat,
date_folder=none, mode=move, recursive=true, mime_filter=audio.
- Downloads / WhatsApp → flat or by mime, user's call.
After defining each mapping, offer to "add another" until they're done.
3. Global options
Ask once:
incremental_default: true / false — only files newer than the newest already in the destination. Default true.
verify_before_delete: must be true for mode=move (don't make this user-toggleable; just enforce it). Document it.
collision_strategy: suffix (default — append _1, _2) or skip.
4. Write config
Write <workspace>/config.yaml:
version: 1
options:
incremental_default: true
collision_strategy: suffix
mappings:
- label: camera
source: /sdcard/DCIM/Camera
recursive: false
dest_root: /home/alice/Pictures/Phone
route_by_mime: true
image_dest: Photos
video_dest: Videos
date_folder: YYYY-MM-DD
orientation_split: true
mime_filter: image,video
mode: move
- label: screenshots
source: /sdcard/Pictures/Screenshots
recursive: false
dest_root: /home/alice/Pictures/Phone/Screenshots
route_by_mime: false
date_folder: none
orientation_split: false
mime_filter: image
mode: move
- label: recordings
source:
5. Dry-run preview
After writing, offer to run import-media in dry-run mode (list what would move, show counts and bytes, no transfer) so the user can sanity-check before committing.
6. Re-running onboard
If config.yaml already exists, ask whether the user wants to:
- Edit an existing mapping by label,
- Add a new mapping,
- Remove a mapping,
- Replace the whole config (back up old to
config.yaml.bak.<timestamp> first).
Never silently overwrite an existing config.