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.
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": []
}
| Field | Type | Description |
|---|
avatar_count | integer | Total avatar count from the source database file header |
author_count | integer | Unique author count, computed during processing |
last_update | string | Database date decoded from the packed 2-byte file header field (YYYY-MM-DD) |
entries | array | Always 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
}
| Field | Type | Description |
|---|
name | string | Avatar display name |
author | string | Avatar creator name |
description | string | Avatar description text |
avatar_id | string | VRChat avatar ID in avtr_ format |
tags | array | Tags extracted from the third tab-separated field in the database |
quest | boolean | Whether the avatar has a Quest-compatible build |
ios | boolean | Whether 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:
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.