Compiled from a full day of CLI testing. Everything here is blocking or significantly degrading the CLI experience.
π΄ Blocking β Server Bugs
1. template: null routing bug
Abilities deployed via CLI have template: null and are silently ignored by the cloud router β keywords never fire, voice never triggers the ability. The router should dispatch based on trigger_words directly, not require a template ID.
Current workaround: Two-step deploy β create shell ability from template (no zip), then upload code via validate/release-code. Messy and undocumented.
Fix: Make the router dispatch on matching_hotwords/trigger_words regardless of whether template is set.
2. New installs default to agent_capability: false
When an ability is installed on an agent, it defaults to system_capability: true, agent_capability: false. This means keyword routing never fires even if the ability is correctly assigned.
Current workaround: CLI now calls PUT /api/capabilities/edit-installed-capability/{installed_id}/ with agent_capability: true after every assign. But this requires JWT.
Fix: Default agent_capability: true for skill and brain_skill category abilities on install.
3. DELETE /api/capabilities/delete-capability/{id}/ returns 404
Delete endpoint doesn't exist or isn't reachable. We removed openhome delete from the CLI entirely because of this.
Fix: Implement the endpoint, or document the correct delete path.
4. add-capability rejects zip + template together
POST /api/capabilities/add-capability/ returns "Cannot use zip_file and template together!" if both fields are passed. This forces a two-step workaround for any ability that needs a template for routing to work.
Fix: Either accept both (zip overrides template code), or fix bug #1 so template isn't required for routing.
5. matching_capabilities drops all but last field
PUT /api/personalities/edit-personality/ only keeps the last matching_capabilities form field when multiple are sent. Assigning A,B,C wipes to just C.
Current workaround: CLI now sends a single CSV string. Needs to be confirmed as the canonical format and documented.
Fix: Document expected format (CSV string? repeated fields? JSON array?) and handle consistently.
π‘ Missing Endpoints
6. No templates listing endpoint
The dashboard shows available templates (Alarm, Send Email, OpenClaw, Empty Template, etc.) but there's no API endpoint to fetch them. CLI can't offer template selection without hardcoding IDs.
Add: GET /api/capabilities/templates/ returning [{id, name, category}]
7. No direct ability update/overwrite endpoint
There's no PUT /api/capabilities/update-capability/{id}/ to upload new code to an existing ability. The CLI uses POST /api/capabilities/validate/release-code/{release_id}/ as a workaround (discovered in issue #14).
Add: A documented update endpoint. Also clarify committed=true vs committed=false behavior β currently undocumented.
8. get-installed-capabilities requires JWT, not API key
Most CLI operations work with X-API-KEY. But GET /api/capabilities/get-installed-capabilities/ requires JWT (Authorization: Bearer), making it inaccessible to scripts and non-browser clients that only have an API key.
Fix: Accept X-API-KEY for this endpoint, or add an SDK-accessible equivalent.
9. edit-installed-capability uses installed ID, not capability ID
PUT /api/capabilities/edit-installed-capability/{id}/ expects the installed ID (from get-installed-capabilities), not the capability ID (from get-all-capabilities). There's no way to look up the installed ID without JWT.
Fix: Accept capability ID as an alternative, or add GET /api/capabilities/get-installed-capability/by-capability/{capability_id}/ as a stable, API-key-accessible endpoint.
π Missing Documentation
10. WebSocket logs endpoint undiscovered
wss://app.openhome.com/websocket/logs?api_key=...&tail=100 exists and works but isn't in the docs. Found by a community contributor through experimentation.
Add to docs: Log streaming WebSocket endpoint with params.
11. agent_capability vs system_capability not documented
The installed capability object has agent_capability and system_capability boolean fields that control keyword routing. These are not mentioned anywhere in the API reference or ability docs.
Add to docs: What these fields mean, default values, how to set them.
12. local_client.py only on Google Drive
The local connect client is hosted on a personal Google Drive link. This is fragile (link can expire, can't be scripted, not versioned).
Fix: Host local_client.py in the abilities repo at templates/Local/local_client.py so it can be downloaded programmatically and versioned alongside the template.
13. validate/release-code committed field undocumented
POST /api/capabilities/validate/release-code/{release_id}/ accepts a committed boolean field. committed=false saves but doesn't activate. committed=true activates immediately. Neither behavior is documented.
Add to docs: This endpoint, its fields, and what committed controls.
π’ Nice to Have
14. add-capability should return release_id
The response from POST /api/capabilities/add-capability/ returns capability_id but not release_id. Getting the release ID requires a separate call to get-all-capabilities and digging through capability_versions. Return it directly.
15. Ability names with spaces
Dashboard allows names with spaces. CLI was incorrectly rejecting them (now fixed client-side). Just confirm this is supported server-side so we can document it.
All client-side workarounds for the above are in PR #16. The workarounds work but are fragile β these server fixes would let us remove the hacks.
Compiled from a full day of CLI testing. Everything here is blocking or significantly degrading the CLI experience.
π΄ Blocking β Server Bugs
1.
template: nullrouting bugAbilities deployed via CLI have
template: nulland are silently ignored by the cloud router β keywords never fire, voice never triggers the ability. The router should dispatch based ontrigger_wordsdirectly, not require a template ID.Current workaround: Two-step deploy β create shell ability from template (no zip), then upload code via
validate/release-code. Messy and undocumented.Fix: Make the router dispatch on
matching_hotwords/trigger_wordsregardless of whethertemplateis set.2. New installs default to
agent_capability: falseWhen an ability is installed on an agent, it defaults to
system_capability: true, agent_capability: false. This means keyword routing never fires even if the ability is correctly assigned.Current workaround: CLI now calls
PUT /api/capabilities/edit-installed-capability/{installed_id}/withagent_capability: trueafter every assign. But this requires JWT.Fix: Default
agent_capability: trueforskillandbrain_skillcategory abilities on install.3.
DELETE /api/capabilities/delete-capability/{id}/returns 404Delete endpoint doesn't exist or isn't reachable. We removed
openhome deletefrom the CLI entirely because of this.Fix: Implement the endpoint, or document the correct delete path.
4.
add-capabilityrejects zip + template togetherPOST /api/capabilities/add-capability/returns"Cannot use zip_file and template together!"if both fields are passed. This forces a two-step workaround for any ability that needs a template for routing to work.Fix: Either accept both (zip overrides template code), or fix bug #1 so template isn't required for routing.
5.
matching_capabilitiesdrops all but last fieldPUT /api/personalities/edit-personality/only keeps the lastmatching_capabilitiesform field when multiple are sent. AssigningA,B,Cwipes to justC.Current workaround: CLI now sends a single CSV string. Needs to be confirmed as the canonical format and documented.
Fix: Document expected format (CSV string? repeated fields? JSON array?) and handle consistently.
π‘ Missing Endpoints
6. No templates listing endpoint
The dashboard shows available templates (Alarm, Send Email, OpenClaw, Empty Template, etc.) but there's no API endpoint to fetch them. CLI can't offer template selection without hardcoding IDs.
Add:
GET /api/capabilities/templates/returning[{id, name, category}]7. No direct ability update/overwrite endpoint
There's no
PUT /api/capabilities/update-capability/{id}/to upload new code to an existing ability. The CLI usesPOST /api/capabilities/validate/release-code/{release_id}/as a workaround (discovered in issue #14).Add: A documented
updateendpoint. Also clarifycommitted=truevscommitted=falsebehavior β currently undocumented.8.
get-installed-capabilitiesrequires JWT, not API keyMost CLI operations work with
X-API-KEY. ButGET /api/capabilities/get-installed-capabilities/requires JWT (Authorization: Bearer), making it inaccessible to scripts and non-browser clients that only have an API key.Fix: Accept
X-API-KEYfor this endpoint, or add an SDK-accessible equivalent.9.
edit-installed-capabilityuses installed ID, not capability IDPUT /api/capabilities/edit-installed-capability/{id}/expects the installed ID (fromget-installed-capabilities), not the capability ID (fromget-all-capabilities). There's no way to look up the installed ID without JWT.Fix: Accept capability ID as an alternative, or add
GET /api/capabilities/get-installed-capability/by-capability/{capability_id}/as a stable, API-key-accessible endpoint.π Missing Documentation
10. WebSocket logs endpoint undiscovered
wss://app.openhome.com/websocket/logs?api_key=...&tail=100exists and works but isn't in the docs. Found by a community contributor through experimentation.Add to docs: Log streaming WebSocket endpoint with params.
11.
agent_capabilityvssystem_capabilitynot documentedThe installed capability object has
agent_capabilityandsystem_capabilityboolean fields that control keyword routing. These are not mentioned anywhere in the API reference or ability docs.Add to docs: What these fields mean, default values, how to set them.
12.
local_client.pyonly on Google DriveThe local connect client is hosted on a personal Google Drive link. This is fragile (link can expire, can't be scripted, not versioned).
Fix: Host
local_client.pyin the abilities repo attemplates/Local/local_client.pyso it can be downloaded programmatically and versioned alongside the template.13.
validate/release-codecommittedfield undocumentedPOST /api/capabilities/validate/release-code/{release_id}/accepts acommittedboolean field.committed=falsesaves but doesn't activate.committed=trueactivates immediately. Neither behavior is documented.Add to docs: This endpoint, its fields, and what
committedcontrols.π’ Nice to Have
14.
add-capabilityshould returnrelease_idThe response from
POST /api/capabilities/add-capability/returnscapability_idbut notrelease_id. Getting the release ID requires a separate call toget-all-capabilitiesand digging throughcapability_versions. Return it directly.15. Ability names with spaces
Dashboard allows names with spaces. CLI was incorrectly rejecting them (now fixed client-side). Just confirm this is supported server-side so we can document it.
All client-side workarounds for the above are in PR #16. The workarounds work but are fragile β these server fixes would let us remove the hacks.