02 — Manifest (locara.json)
The manifest is the central design artifact. Everything review, runtime, and registry rely on it.
Top-level structure
{
"schema": "locara/v1",
"name": "transcribe",
"publisher": "kingtongchoo",
"version": "0.1.0",
"displayName": "Transcribe",
"description": "Fully-local audio and meeting transcription.",
"longDescription": "...",
"license": "Apache-2.0",
"homepage": "https://example.com/transcribe",
"repository": "https://github.com/kingtongchoo/transcribe-locara",
"author": { "name": "King Tong Choo", "email": "..." },
"icon": "./public/icon.png",
"screenshots": ["./screenshots/main.png", "./screenshots/search.png"],
"category": "productivity",
"tags": ["audio", "transcription", "meetings"],
"capabilities": { ... },
"profiles": { ... },
"storage": { ... },
"entry": { ... },
"build": { ... }
}
Field reference
Identity
| Field | Required | Type | Notes |
|---|---|---|---|
schema | yes | string | Locked to "locara/v1" for spec v1. |
name | yes | string | Lowercase, alphanumeric + hyphens. Unique within publisher. |
publisher | yes | string | Must match verified publisher account. |
version | yes | string | Strict semver (MAJOR.MINOR.PATCH). |
The full app identifier is <publisher>/<name>@<version> — e.g., kingtongchoo/transcribe@0.1.0.
Display
| Field | Required | Type | Notes |
|---|---|---|---|
displayName | yes | string | Shown in catalog. ≤40 chars. |
description | yes | string | One-line. ≤140 chars. |
longDescription | no | string | Markdown. App-page body. |
license | yes | string | SPDX identifier. |
homepage | no | URL | Project site. |
repository | no | URL | Source repo. Required for verification. |
author | yes | object | { name, email, url? } |
icon | yes | path | 512x512 PNG, ≤200KB. |
screenshots | yes | array | At least 1, max 5. PNG/JPG, ≤2MB each. |
category | yes | string | One of [enumerated categories]. |
tags | no | array | Free-form, max 10. |
Modalities & Tooling (developer-facing primary declarations)
See 04-modalities.md for full reference. These are the high-level declarations developers use; they expand into capabilities + models + SDK access deterministically.
"modalities": [
"speech-to-text",
"text-to-text"
],
"tooling": [
"filesystem.search",
"code-exec.python"
]
Apps can declare modalities/tooling in either simple form (just names) or expanded form (with overrides for specific models). Most apps use the simple form; the framework picks defaults.
Capabilities (low-level, mostly auto-derived)
See 03-capabilities.md for full reference.
Most capability declarations are auto-derived from modalities + tooling. Power users can declare them directly when they need precise control.
"capabilities": {
"net": false,
"fs": {
"user-selected": "read-write",
"app-data": "read-write"
},
"device": {
"microphone": true,
"camera": false,
"screen-recording": false
},
"models": [
"whisper-large-v3-q4@sha256:abc...",
"qwen2.5-3b-instruct-q4@sha256:def..."
],
"tools": ["wasm.text-utils@1.0"],
"ipc": []
}
All keys are required. Omitting a key implies false / [] / minimal — but explicit is required for clarity and review tooling.
Profiles
Device-tier hardware requirements. Authors define what the app needs at each tier; the registry filters apps by user device fit.
"profiles": {
"low": {
"min_ram_gb": 8,
"min_disk_gb": 4,
"models_override": { "transcribe": "whisper-base-q4@sha256:..." }
},
"mid": {
"min_ram_gb": 16,
"min_disk_gb": 8
},
"high": {
"min_ram_gb": 32,
"min_disk_gb": 16,
"models_override": { "chat": "qwen2.5-7b-instruct-q4@sha256:..." }
}
}
The models_override swaps in different model variants per profile. Models referenced in overrides must also exist in capabilities.models[] (or be declared specifically with override prefix).
At least one profile must be declared. Most apps will have mid and high; low is encouraged for accessibility.
Storage
"storage": {
"schema": "./db/schema.sql",
"migrations": "./db/migrations",
"vector": { "engine": "sqlite-vec" }
}
| Field | Required | Notes |
|---|---|---|
schema | yes | Path to schema.sql. CREATE TABLE statements, etc. |
migrations | no | Directory of timestamped migration scripts. |
vector.engine | no | "sqlite-vec" (default), "zvec", or omit if app uses no vectors. |
Migrations are auto-generated by locara from schema diffs between versions, but can be hand-edited for non-trivial cases. See 08-storage.md.
Entry
"entry": {
"frontend": "./src/main.tsx",
"preload": "./src/preload.ts"
}
Tauri entry points. frontend is the main webview entry; preload is optional (rarely needed).
Build
"build": {
"tauri_config": "./src-tauri/tauri.conf.json",
"icon_set": "./src-tauri/icons"
}
Pointers to Tauri build artifacts. Generated by locara init; rarely edited.
Validation
The CLI runs locara verify which checks:
- Schema validity. JSON schema (
@locara/manifest) validates structure. - Identity consistency.
name,publisher,versionmatch local config + git. - File existence. Icon, screenshots, schema, entry files all exist.
- Capability reasonableness. Declared capabilities are well-formed; no unknown keys.
- Profile consistency. All
models_overridereferences exist; profiles ordered low→high by RAM. - Model hashes. All model entries have valid SHA pins (or
?placeholder for dev mode). - Static analysis vs capabilities. AST scan of source — does the app try to use APIs it didn’t declare? (Run automatically; opt out only with explicit
--skip-static-analysis.) - License. SPDX validity.
Submission to registry requires locara verify passing without warnings.
Lockfile (locara.lock.json)
Auto-generated, committed to version control. Pins:
- Resolved model hashes (from registry queries)
- SDK + components versions
- Sub-dependency tree
{
"models": {
"whisper-large-v3-q4": {
"sha256": "abc123...",
"size_bytes": 1234567890,
"url": "https://cdn.locara.app/models/whisper-large-v3-q4-abc123.gguf"
}
},
"sdk_version": "0.1.4",
"components_version": "0.1.2"
}
The lockfile makes builds deterministic. CI uses it; hand-editing is discouraged but allowed.
Versioning
- Patch (0.1.0 → 0.1.1): bug fixes, no capability changes. Auto-published.
- Minor (0.1.0 → 0.2.0): new features, no capability expansion. Reviewed if anything new.
- Major (0.1.0 → 1.0.0): breaking changes. Always reviewed.
Capability changes are independent of version semantics. Any capability expansion (gaining net: true, or adding a new model with sensitive capability) triggers a 7-day cool-down + user re-consent on update — regardless of version bump. See 14-trust-safety.md.
Schema versioning
The schema field lets us evolve the manifest format:
- v1 apps continue to work. Forever.
- Future versions (
locara/v2, etc.) introduce new fields and patterns. - The runtime supports all schema versions (long-term support, SQLite-style commitment).
A v1 manifest written today must still parse and run in 5 years. This is a hard commitment; design accordingly.
Open questions
- (open) Should
categorybe enumerated (closed list) or free-form? Probably enumerated to keep catalog filtering tractable. - (open) How granular should
tagsbe moderated? Spam prevention for SEO-style tag stuffing. - (open) Should the manifest reference minimum SDK version? Probably yes —
"requires_sdk": ">=0.2.0". - (open) Multi-locale display fields (i18n)? Not v1; punt.
Cross-references
- Capability model: 03-capabilities.md
- Modalities + tooling (the developer-facing primary declarations): 04-modalities.md
- CLI commands operating on manifest: 06-cli.md
- Storage schema details: 08-storage.md
- Models and content addressing: 09-models.md
- Trust mechanics around capability cool-down: 14-trust-safety.md