Repository navigation
AI AGENTS
Languages: English | العربية | Čeština | Deutsch | Español | فارسی | Français | हिन्दी | Bahasa Indonesia | Italiano | 日本語 | 한국어 | Nederlands | Polski | Português | Русский | Svenska | ไทย | Türkçe | Tiếng Việt | 中文
VDBackup is built so an AI assistant or agent can administer every content and action of the module headlessly, the same way a person does through the WebUI. The WebUI is just one client of a small JSON API; your agent is another. Use the API, do not scrape the WebUI.
Everything goes through one entry point, run as root on the device:
sh /data/adb/modules/vdbackup/scripts/helper.sh <verb> <base64(JSON-args)>
- Arguments are a single JSON object, base64-encoded, passed as one argv token.
- The command prints one JSON object on stdout:
{"ok":true,...}or{"ok":false,"code":"ERR_...","message":"..."}. Parse that; never scrape text. - Long operations (
backup,restore,import) return{"ok":true,"opid":"..."}immediately and run detached (they survive the caller/WebUI going away). Poll their progress; they are not finished when the call returns. -
progressandcanceltake base64 of the raw opid string, not a JSON object.
A tiny helper for your shell:
b64() { printf '%s' "$1" | base64 -w0; }
H=/data/adb/modules/vdbackup/scripts/helper.sh
sh "$H" backup "$(b64 '{"package":"com.example.app","mode":"full"}')"To drive it from a workstation, run that over your usual root channel to the device
(adb shell as root, or an SSH-to-root setup). The module ships bundled binaries, so
once installed it needs no internet for local backup/restore; only cloud
destinations (rclone/restic/ssh) talk to the network.
| Verb | Args (JSON) | Returns |
|---|---|---|
ping |
{} |
{ok,version,abi} |
config-get |
{} |
{ok,config} |
config-set |
the config object (or {key,value}) |
{ok} |
keygen |
{} |
generates the age keypair for encryption |
list-apps |
{user?} |
{ok,apps:[{package,label,system,versionCode}]} (dex, shell fallback) |
label |
{package,user?} |
{ok,label} (real localized app name, context-free) |
icon |
{package,user?,vc?} |
{ok,package,icon} (base64 PNG; cached per package+vc) |
backup |
see below |
{ok,opid} (detached) |
restore |
see below |
{ok,opid} (detached) |
import |
{from,ref,password,ssaid,user} |
{ok,opid} (detached) |
import-scan |
{from,path} |
{ok,backups:[...]} |
progress |
base64(opid) | the live progress-<opid>.json
|
cancel |
base64(opid) | {ok,cancelled} |
list-ops |
{} |
{ok,ops:[...]} (reattach after reconnecting) |
list-apps/icons
|
{user?} / {user?,items:[{package,vc}]}
|
app list / batch base64 icons |
list-backups |
{package?} |
{ok,backups:[{ref,package,label,versionName,versionCode,created_at,mode,items}]} |
backup-info |
{ref} |
{ok,...} one backup's full details (version, install source, state, date, mode, size, items, permission counts, device) |
backup-icon |
{ref} |
{ok,icon} base64 PNG from the manifest (works when the app is uninstalled) |
delete-backup |
{ref} |
{ok,deleted} (ref must be under the backups dir) |
prune |
{package,user?,keep} |
{ok,pruned:[...]} keep newest N of a package |
log-read |
{limit?} |
{ok,entries:[...]} audit log, newest first |
special-categories |
{} |
{ok,categories:[{id,available}]} (messages/contacts/wifi/bluetooth) |
special-backup |
{categories,compression?,password?,portable?} |
{ok,opid} system-wide backup (detached) |
special-restore |
{ref,confirm:true,categories?,password?} |
{ok,opid} (reboot-required; confirm gates it) |
special-list |
{} |
{ok,backups:[{ref,created_at,categories}]} |
sysmount-status |
{} |
{ok,nomount,nm,ksu,live_capable} |
sysmount-add / sysmount-del / sysmount-list
|
{package,priv?} |
mount an installed app as a system app (systemless sub-module; live via NoMount else next boot) |
companion-status / companion-install
|
{} |
Google Drive companion status / on-demand install |
dests-list / dest-add / dest-test / dest-del
|
{id,type,...} |
destination management |
remote-add / remote-list / remote-del
|
{name,backend,params:{...}} |
rclone remote management (creates the rclone.conf entry a type:"rclone" dest points to) |
schedule-set / schedule-list / schedule-delete
|
{id,package,mode,dest,cron,at,keep,items} |
scheduled jobs |
scheduler-tick |
{} |
runs due jobs + applies retention + the auto-backup observer (the boot heartbeat calls this) |
{
"package": "com.example.app",
"user": 0,
"mode": "full", // full | snapshot | mirror
"compression": "zstd:10", // none | lz4 | zstd[:N] | gzip
"items": ["apk","data","data_de","obb","external","media"],
"encrypt_data": false,
"encrypt_apk": false,
"dest": "local", // local | <destination id>
"verify": true, // re-hash each archive vs the manifest (default on for Full)
"dry_run": false, // true = report a size plan, write nothing
"ssaid": false // OPT-IN, see below
}restore/import take {ref} (a backup dir / scan ref). restore also accepts:
"items" (a subset of the backup's item types to restore; omit for all), "test": true
(extract to a temp dir and verify, without touching the live app), "mode" for
snapshot/mirror, "password" for an encrypted backup, "ssaid" (opt-in), and the
install-source options "spoof_installer" (default from config, sets the installer to the
Play Store at install time) and "deep_spoof": true (advanced opt-in; also forges the
initiating package and package source by editing the package database, applies after a
reboot). import takes "from": "neo" | "databackup" and, for an encrypted Neo backup,
"password".
A cloud destination is a type:"rclone" dest that names an rclone remote; create
that remote first with remote-add. Password fields are stored obscured, never in
clear. Supported backend values and their params:
sftp : host, port, user, pass smb : host, port, user, pass
ftp : host, port, user, pass webdav: url, vendor, user, pass
s3 : provider, access_key_id, secret_access_key, endpoint, region
drive : token, scope (token = output of `rclone authorize "drive"`)
Google Drive has two paths: this drive remote (no Google Cloud project needed, uses
rclone's own OAuth - run rclone authorize "drive" once on any computer and pass the
token) or the opt-in companion app (your own OAuth client id). Both end up as ordinary
destinations.
The config field network_policy controls which connection cloud transfers may use:
any (default), wifi, or mobile. Set it with config-set. When it is wifi or
mobile, every cloud transfer (Full rclone/Drive upload, Mirror sync, remote
restic snapshot backup/restore, Mirror restore) checks the active transport first and
aborts with ERR_NET_POLICY if it does not match - for both manual and scheduled jobs.
Local destinations are never gated.
-
ssaidis strictly opt-in (default off). It backs up / restores the device ANDROID_ID by rewriting a system file; a restore applies only after a reboot, and the previous file is always saved first for rollback. Only send"ssaid": trueon a direct, deliberate user request - never by default. -
Mutating actions (restore, delete, import) are destructive and are logged to a
local audit trail (
logs/audit.jsonl). Restore is faithful (wipe-then-extract), so it reverts the app to the backup's exact state. Confirm intent before you call them. -
Never weaken preservation (SELinux/uid/gid/modes/xattr) or the APK rule (APKs
are always compressed, never encrypted unless
encrypt_apkis set). - Treat the JSON output as the source of truth; check
ok/code, pollprogress, and surfaceERR_*codes rather than guessing.
See ARCHITECTURE.md and FILE-STRUCTURE.md for the internals.
This documentation was generated with Claude (Anthropic) and is maintained by VD171. Corrections and improvements are welcome - see CONTRIBUTING.md.