- Rename all user-facing and technical identifiers from OpenPets/Pet to FamiliarOS/Familiar. - Rename packages from @open-pets/* to @familiaros/*; rename install-pet/pet-format packages. - Rename plugin IDs and directories from openpets.* to familiaros.*. - Rename IPC namespace from openpets:* to familiaros:* and state filenames from openpets-* to familiaros-* with legacy migration. - Rename source files (pet-window, built-in-pet, default-pet-controller, etc.) to familiar equivalents. - Update locales (en, es-419, ja, ko, pt-BR, zh-Hans, zh-Hant) and tray/pet context menu strings. - Add Familiar naming feature: preference, settings input, tray menu display. - Update assets and packaging config; all desktop tests pass.
2.9 KiB
2.9 KiB
packages/install-familiar/
Standalone familiar installer from FamiliarOS gallery catalog.
Responsibility
Provides a standalone CLI tool for installing familiars from the FamiliarOS gallery catalog. Can operate through the running desktop app (preferred) or directly download and extract familiar ZIP files.
Design
Dual Install Modes:
- Via Running App: Uses
@familiaros/clientto request installation through the desktop app - Direct Install: Downloads from catalog, validates, extracts to user data directory
Catalog Integration:
- URL:
https://familiaros.dev/familiars/catalog.v2.json - Validation: Schema version, unique IDs, URL host/path allowlisting
- Familiar structure:
{ id, displayName, description, preview, zip }
ZIP Handling:
- Library:
yauzlfor streaming ZIP extraction - Security: Path traversal prevention, symlink rejection, size limits
- Limits: 50MB download, 200MB extracted, 500 files, 100MB per file
- Required files:
familiar.json,spritesheet.webp - Extraction: Atomic (temp dir → rename), permission 0o600/0o700
State Management:
- User data path: Platform-specific (macOS:
~/Library/Application Support/FamiliarOS, Windows:%APPDATA%/FamiliarOS, Linux:~/.config/FamiliarOS) - State file:
familiaros-state.json - Lock file:
.install-familiar.lock(prevents concurrent installs, 10min stale timeout) - Familiar directory:
familiars/<petId>/
Validation:
- Familiar ID:
^[a-z0-9][a-z0-9_-]{0,63}$, excludes "builtin" - Catalog URLs: HTTPS only, specific host allowlist
- ZIP entries: No encryption, supported compression (stored/deflate), valid Unix modes
Flow
installPet({ petId, preferRunningApp })
↓
tryInstallThroughRunningApp() → createFamiliarOSClient().installPet()
↓ (fallback on unavailable/timeout)
installPetDirectly()
↓
acquireDirectInstallLock() → mkdir lock, write owner.json
↓
fetchCatalog() → GET https://familiaros.dev/familiars/catalog.v2.json
↓
getCatalogPet(petId) → Validate exists in catalog
↓
downloadPetZip(zipUrl) → Stream to buffer, validate magic bytes
↓
extractPetZip(buffer, tempDir) → yauzl streaming extract
↓
validateExtractedPet() → Check familiar.json, spritesheet.webp exist
↓
rename(tempDir, finalDir) → Atomic move
↓
writeInstalledPetState() → Update familiaros-state.json
↓
releaseLock() → rm lock directory
Integration Points
Dependencies:
@familiaros/client- Fallback IPC to running appyauzl- ZIP file handling
External Services:
familiaros.dev- Catalog JSON and familiar metadatazip.familiaros.dev- ZIP file downloads
CLI Usage:
- Binary:
install-familiar <familiar-id> - Also invocable via
npx -y install-familiar <familiar-id>
Exports:
installPet()- Main install functionparseArgs()- CLI argument parsinggetFamiliarOSUserDataPath()- Platform-specific path resolutionvalidatePetId()- ID format validation