Skip to main content
The app stores all downloaded and processed avatar data in a cache/ directory. This directory is created automatically relative to the executable location when the database downloader runs for the first time.

Cache directory location

cache/                        # relative to the executable
├── avatar_entries.ndjson     # streaming NDJSON for the avatar browser
├── avatar_data.json          # aggregate statistics (avatar/author counts, last update)
└── cache_meta.json           # gist version hash for cache invalidation

Cached files

cache/avatar_entries.ndjson

The primary output of the database downloader. A newline-delimited JSON (NDJSON) file where each line is a single JSON-serialized AvatarEntry. The avatar browser reads this file line-by-line using a BufReader, which allows streaming reads without loading the entire database into memory.
NDJSON format means each line is a complete, standalone JSON object. The avatar browser pages through this file sequentially, keeping memory usage low regardless of database size.

cache/avatar_data.json

Contains aggregate database statistics in AvatarData format. The entries array is empty in this file — all avatar records live in avatar_entries.ndjson.

cache/cache_meta.json

Stores the gist commit version hash and the timestamp when the cache was last written. Used for cache invalidation on subsequent launches.
{
  "gist_version": "abc123def456...",
  "saved_at": "2024-01-15T10:30:00Z"
}

AvatarData statistics schema

cache/avatar_data.json uses the following structure:
{
  "avatar_count": 150000,
  "author_count": 45000,
  "last_update": "2024-01-15",
  "entries": []
}
FieldTypeDescription
avatar_countintegerTotal avatar count from the source database file header
author_countintegerUnique author count, computed during processing
last_updatestringDatabase date decoded from the packed 2-byte file header field (YYYY-MM-DD)
entriesarrayAlways empty in this file — avatar records are stored in avatar_entries.ndjson

AvatarEntry NDJSON schema

Each line in avatar_entries.ndjson is one AvatarEntry object:
{
  "name": "Avatar Name",
  "author": "Author Name",
  "description": "Avatar description",
  "avatar_id": "avtr_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "tags": ["tag1", "tag2"],
  "quest": false,
  "ios": false
}
FieldTypeDescription
namestringAvatar display name
authorstringAvatar creator name
descriptionstringAvatar description text
avatar_idstringVRChat avatar ID in avtr_ format
tagsarrayTags extracted from the third tab-separated field in the database
questbooleanWhether the avatar has a Quest-compatible build
iosbooleanWhether the avatar has an iOS-compatible build

Cache invalidation

The app tracks the upstream source version using a CacheMeta structure stored alongside the cache. It records the gist_version from the GitHub Gist that provides the database. On each launch, the app fetches the current Gist version and compares it to the cached value — a re-download only happens when the version has changed. This means the cache remains valid across launches until the upstream database is updated.

Forcing a re-download

To force the app to re-download and reprocess the full database, delete the cache/ directory and relaunch the app:
rm -rf cache/
Deleting the cache/ directory requires a full re-download of all avatar databases. Depending on your connection speed and the current database size, this can take several minutes.

Build docs developers (and LLMs) love