| name | octo-html |
| version | 0.2.0 |
| description | HTML docs domain (octo-doc) — create and govern self-contained interactive HTML documents, immutable versions, drafts, sharing, media, comments, and agent element edits. This is a DIFFERENT backend from the `octo-docs` (CRDT/Yjs) domain. Load after octo-shared. |
| metadata | {"requires":{"bins":["octo-cli"],"skills":["octo-shared"]}} |
octo-html — interactive HTML documents
This is NOT the octo-docs body-editing domain. octo-cli html … talks
to octo-doc, where a document is a self-contained HTML page published as
immutable versions. octo-cli docs … talks to the separate CRDT/Yjs backend.
All commands call $OCTO_API_BASE_URL/docs-html/v1/* and return the standard
{ok, identity, data, ...} success envelope.
Document-reference contract
- Canonical create has no document reference. Omit
slug and provide
html. The CLI generates idempotency_key; an explicit key is optional. A display name belongs in meta.title;
it is metadata, not identity.
- Save
data.slug from the response. New documents always return
data.doc_id and data.slug, with data.slug == data.doc_id, whether mounted
or unmounted. Use data.slug for every later operation.
- Legacy documents keep their old reference. For an old document, use its
legacy slug wherever this skill says
<doc-ref>.
- No alias identity and no same-name republish. Creating again with the same
meta.title creates a different document. To publish another version, supply
the saved data.slug in the server's legacy-named slug field.
- Do not infer a mode from
mount_type, registered, status, or whether
data.doc_id is non-empty. registered and status report operational state,
not identity.
Query and JSON-body fields remain named slug for wire compatibility. Put the
saved document reference in them. Path help displays <doc-ref>, and old legacy
slugs are accepted. The CLI does not persist the reference.
Minimum rollout dependency: this contract requires the canonical-create
server changes in octo-docs-backend#166 and octo-docs-html#33 to be merged and
deployed before this CLI is released.
Auth & space
- Authenticate with a stored bot profile (
--profile / --bot-id) or
OCTO_BOT_TOKEN; confirm the selected identity with octo-cli config show.
- Do not pass
--space. octo-doc resolves identity and space server-side.
- Write operations require author/write capability. Reads need at least reader
capability; backend failures are normalized into the CLI's
{ok:false,error:{type,code,message,hint,detail}} envelope.
1. Create and publish
Documents are declarative: no JavaScript. The backend rejects any publish or
draft whose HTML carries script, with 400 and the stable code
html_contains_javascript. This is not advisory — there is no flag to opt out.
When generating a document, never emit:
<script> elements (including inside <svg>),
on* event-handler attributes (onclick, onload, onerror, …),
javascript: / vbscript: / scriptable data: URLs in href, src,
xlink:href, action, formaction, object[data], or a non-empty srcdoc.
Express interaction with CSS instead — :hover, :target, :checked +
sibling selectors, <details>/<summary>, transitions and animations all work
and cover most of what a document needs. Do not assume script is merely inert:
the host application embeds documents in a sandboxed iframe, but the document's
own version URL serves the stored HTML as a top-level page, so script that got
stored would execute for every reader who opens that link. CSS, inline style,
<iframe>, <noscript> and <meta http-equiv=refresh> are all still allowed.
On rejection the error details.violations lists every offending construct with
its kind, tag, attr and 1-based line. Fix all of them in one pass — the
list is complete (capped at 50, with details.truncated set when it overflows).
Do not retry the same document unchanged, and do not try to work around the gate
by encoding or splitting the script.
octo-cli html publish --data '{"html":"<html><body><h1>Runbook</h1></body></html>","meta":{"title":"Runbook"},"mount_type":"group","group_no":"<group_no>"}'
octo-cli html publish --data '{"html":"<html><body><h1>Private draft</h1></body></html>","meta":{"title":"Private draft"}}'
octo-cli html publish --data '{"slug":"<doc-ref>","html":"<html><body><h1>Runbook v2</h1></body></html>","meta":{"title":"Runbook"}}'
octo-cli html list
octo-cli html get <doc-ref>
octo-cli html versions <doc-ref>
octo-cli html <doc-ref>
html list returns the backend's offset envelope as data plus _pagination
(total, page, page_size). It has no cursor flags or --page-all support.
Mounts (group, space, or thread) control placement/registration only. For
group, pass group_no; for thread, pass thread_id. They do not choose the
document-reference format.
WITHOUT mount_type the backend skips docs-backend registration, so the HTML
never shows up in the sidebar file list — this is the #1 "my doc didn't appear"
gotcha. An unmounted document still receives a canonical doc_id; registration
and identity are separate concerns.
2. Author drafts
A draft is an author-only working slot and does not mint an immutable version
until promoted.
octo-cli html draft create --html '<html><body><h1>WIP</h1></body></html>'
octo-cli html draft save <doc-ref> --data '{"html":"<html><body><h1>WIP</h1></body></html>"}'
octo-cli html draft promote <doc-ref>
3. Sharing and grants
octo-cli html share <doc-ref>
octo-cli html unshare <doc-ref>
octo-cli html grant add <doc-ref> --uid <uid> --role reader
octo-cli html grant list <doc-ref>
octo-cli html grant rm <doc-ref> <uid>
4. Media assets
octo-cli html asset ls <doc-ref>
octo-cli html asset add <doc-ref> --file ./chart.png
octo-cli html asset rm <doc-ref> <sha256>
5. Comments
The wire parameter remains slug; pass the saved document reference.
octo-cli html comment list --slug <doc-ref> [--version all]
octo-cli html comment add --data '{"slug":"<doc-ref>","text":"Please clarify this","anchor":{"kind":"element","aid":"<content-hash>"}}'
html comment list likewise preserves offset metadata in _pagination; it has
no cursor flags or --page-all support.
6. Agent element edit and reply
octo-cli html element get --data '{"slug":"<doc-ref>","aid":"<content-hash>"}'
octo-cli html element replace --data '{"slug":"<doc-ref>","aid":"<content-hash>","new_html":"<section>updated body</section>"}'
octo-cli html reply --data '{"slug":"<doc-ref>","parent_id":"<comment-root-id>","text":"Done.","status":"applied"}'
To preserve comment anchors, prefer narrow element replacements; avoid changing
an element's tag or nearby heading unless necessary.
Errors
401 / 403 — missing or insufficient capability.
404 — document reference (canonical doc_id or legacy slug), comment, or aid
not found.
400 html_contains_javascript — the published or draft HTML carries
JavaScript (see the no-JavaScript rule in §1). details.violations names every
offending construct with its kind / tag / attr / line; regenerate the
document without script rather than retrying it unchanged.
- Element replacement rejects multiple top-level elements, scripts/styles,
inline event handlers, and
javascript: URLs.
Schema lookup
octo-cli schema --list html
octo-cli schema html.publish
octo-cli schema html.element.replace
octo-cli schema html.reply