name: olares-market version: 4.2.0 description: "Olares Market via olares-cli market — install, upgrade, uninstall, clone, stop, resume apps; catalog, status, chart upload, --watch. Use for Olares app store, my apps, 我的应用, install app, upload chart." compatibility: Requires olares-cli on PATH and active Olares profile metadata: openclaw: requires: bins: - olares-cli
market (App-store v2)
CRITICAL — before doing anything, load the olares-shared skill first (profile selection, login, token refresh, auth-error recovery). Flag reference: olares-cli market --help.
Source of truth for flags is always
olares-cli market <verb> --help. This file only carries what--helpcannot give: source resolution, the lifecycle state machine, OpType-vs-State race safety, the verb index, the-s/-amatrix, and the "what apps do I have" routing.
Platform model: app namespaces (
<app>-<owner>vs the admin-only<app>-shared) and which system-middleware apps an admin installs are defined once in../olares-shared/references/olares-platform.md.
When to use
- Olares Market, olares-cli market, Olares app store, install / upgrade / uninstall / clone / stop / resume / cancel an app
my Olares apps,我的应用,market list --mine,is <app> installed yet, chart upload / delete,--watchuntil terminal state- Catalog:
list,get,categories; runtime:status
Anything outside this scope -> see the Skill suite map in
../olares-shared/SKILL.md(already loaded as the suite prerequisite).
Mental model:
marketis lifecycle and inventory at the app-store level (install / upgrade / chart push). For runtime K8s objects, settings, or metrics, route to a sibling.
Verb families
| Family | Verbs | Mutating? |
|---|---|---|
| catalog | list, get, categories |
no |
| runtime | status |
no |
| lifecycle | install, upgrade, uninstall, clone, stop, resume, cancel |
yes |
| charts | upload, delete |
yes |
For verb-specific behavior, always start with olares-cli market <verb> --help. Then drill into a reference if listed:
| Family | Reference |
|---|---|
| catalog + runtime | references/olares-market-list.md (list / --mine / categories / get / status) |
| lifecycle | references/olares-market-lifecycle.md (install / upgrade / uninstall / clone / stop / resume / cancel) |
| charts | references/olares-market-charts.md (upload / delete) |
Source resolution (cross-cutting)
The market backend serves multiple "sources" of charts. The CLI resolves which one to talk to from -s / --source, falling back to a default that depends on the verb:
| Source id | What it is | Used by |
|---|---|---|
market.olares |
Public catalog (read-only browse) | default for list, get, categories, install, upgrade, clone, status |
upload |
SPA "Local Sources → Upload" bucket | hard-coded for upload / delete — -s is intentionally NOT exposed on those two verbs |
cli |
Legacy CLI-upload bucket | read-only (list, status) |
studio |
Devbox / Studio bucket | read-only (list, status) |
- When
-sis omitted, every verb that accepts it printsUsing source: <id>to stderr so the agent can confirm which backend was hit. -a / --all-sourcesbypasses single-source resolution and spans every source the user has — read-only verbs only.- Unknown source ids silently produce an empty result with a
no apps in source 'X'stderr hint. Runmarket list -ato enumerate the configured sources.
-s / -a matrix
| Flag | Read-only browse | Lifecycle (mutating) | Chart management |
|---|---|---|---|
-s / --source |
list, categories, status, get |
install, upgrade, clone |
— (hard-coded upload) |
-a / --all-sources |
list, categories, status |
— | — |
-sis NOT onuninstall/stop/resume/cancel: they act on whichever per-user state row matches the app name, regardless of source.
App lifecycle / state machine
The backend tracks two orthogonal axes per app: State (where the row currently is) and OpType (which mutation is in flight). The CLI groups the full enum into four buckets:
| Bucket | Examples | Meaning |
|---|---|---|
| Progressing | pending, installing, upgrading, uninstalling, stopping, resuming, *Canceling |
Backend is actively working — keep polling |
| Terminal success | running, stopped, uninstalled |
Mutation finished cleanly |
| Terminal failure | installFailed, upgradeFailed, uninstallFailed, stopFailed, resumeFailed |
Mutation finished with a hard error |
| Canceled / cancel-failed | *Canceled, *CancelFailed |
A cancel request landed (or itself failed) |
Each lifecycle verb maps to its own subset of terminal-success buckets — see the lifecycle reference.
OpType vs State (race-safety)
The same State can mean different things depending on which mutation is in flight. Concrete example: an upgrade issued against an app already in running will return state=running, opType=running for one or two ticks before the backend flips to state=upgrading, opType=upgrade. A naive watcher would declare success at tick zero.
The CLI's mutating-verb watchers refuse to accept any "success" classification until either:
- the row's
OpTypematches the op the CLI just issued, or - the row disappears entirely (only legal for
uninstall/status).
cancel and status deliberately set matchOpType=false because they are op-agnostic by design — cancel declares success on any "row stopped moving" state.
--watch semantics (lifecycle verbs)
- Polling, not streaming. Tick on
--watch-interval(default tuned to the backend's progress cadence). --watch-timeout Dcaps total wall-clock time.- One-shot (no
--watch) returns as soon as the backend ACKs the mutation request — the row may still beprogressingfor minutes. - With
--watch, the CLI blocks until the row reaches a terminal bucket (success OR failure) matching the OpType safety rules above. - Idempotent:
resumeagainst an already-runningrow returns immediately with success;installagainst an already-installed row returns immediately withstate=running. Watcher never hangs on "no-op" mutations. --watch-iterations/--watch-interval/--watch-timeoutare rejected without--watch.
"What apps do I have?" routing
| Question | Right verb | Why |
|---|---|---|
| "Show me my apps" / "我的应用" | market list --mine (alias -m) |
Matches the Market UI's "My Terminus" tab exactly — includes in-flight installs, failed rows, transitional states. Wider than "completed installs only" |
"Runtime status of <app>" / "is it installed yet" |
market status <app> or market status <app> --watch |
Focused view: STATE / OPERATION / PROGRESS / SOURCE. The single-app form does cross-source fallback if -s doesn't find the row |
| "Which apps are running right now" | market status (no app) |
All installed-app rows in the resolved source. Add -a for every source. Cannot --watch — use status <app> --watch instead |
| "Browse the catalog" | market list (no --mine) |
Hits /market/data, not /market/state. Browse-and-discover, not inventory |
list --mineis NOT the same as "completed installs only". It hides only the 6 SPA-hiddenuninstalledAppStates(pendingCanceled,downloadingCanceled,downloadFailed,installFailed,installingCanceled,uninstalled). In-flight installs and post-install failures stay visible because the user clicked something and expects to monitor / retry / cancel them.
Output conventions
-o table(default) or-o json— present on EVERY market verb.-q / --quietsuppresses all stdout / stderr; exit code carries the signal.--no-headers— onlylistandcategories(row-oriented browse). NOT onget(key:value detail, no headers separable) orstatus(runtime probe, always headered). No-op silently on mutating verbs.- Mutating verbs emit a stable
OperationResultJSON shape withfinalState/finalOpTypefor scripted parsing.
Common errors
| Symptom | Cause | Fix |
|---|---|---|
no apps in source 'X' (stderr) |
Unknown source id, or empty result | Run market list -a to enumerate configured sources |
app 'X' is not installed (run 'olares-cli market install X' to install it) |
status <app> could not find the row anywhere |
Install first, or verify the app name spelling |
App is installed under source 'Y' (not 'X') (stderr) |
-s X but the row is actually in source Y |
Drop -s, or pass the correct source. The CLI still renders the row |
missing required env var(s): KEY1, KEY2 ... |
install for an app that declares required envs |
Re-run with --env KEY=VALUE (repeatable) for each missing var |
Lifecycle watcher hangs near *Failed state |
Backend failed but kept the failure row visible | Inspect market status <app> for the failure detail; cancel with market cancel <app> if applicable |
cannot --watch 'status' (no app argument) |
market status without an app + --watch |
Use status <app> --watch |
| 401 / 403 from any verb after refresh | Token rotation / consistent server-side rejection | See ../olares-shared/SKILL.md |
--cascade NOT passed: auto-decided ... (stderr) |
C/S v2 multi-chart app on single-user cluster | Informational — the CLI picked --cascade=true; pass --cascade=false explicitly to override |
For the full auth-error matrix see ../olares-shared/SKILL.md.