Publish one local .html file through Frevana's custom-domain upload flow.
The script first checks custom_domain from GET /subscriptions/user. When no custom domain is configured, it stops before requesting an upload URL and directs the user to:
https://www.frevana.com/dashboard/domain
What This Skill Needs
- one user-specified local
.htmlfile path - the previous
file_keysupplied by the caller when the user wants to update existing content FREVANA_TOKENin the environment, or a one-time--tokenoverridecurlbashpython3- network access to
https://api.frevana.com
Do not guess the file path. If the user has not identified a file, ask for it.
Fixed Publishing Contract
The bundled script owns these request values:
category:agent_app_resultscene_type:content_htmlpublish_type:custom_domainagent_id: use the available Agent ID; fall back tofrevana-space-cmsteam_id: use the available team ID; otherwise use the current session/task ID; omit only when neither is availablefile_extension: fixed tohtmlcontent_type: fixed totext/htmlfile_title: use--titlewhen provided; otherwise extract it from the HTML and fall back to the filename stem- source file: pass the user-specified path directly to the upload command
file_key: omit for a new publication; for an update, pass the exact value from the previous publication
Do not override or reproduce this payload with ad hoc API calls. Do not modify the specified file as part of the publishing workflow.
Execution Order
- Confirm the requested path exists, is a regular file, and ends in
.html(case-insensitive). Before any network request, reject every other file type, tell the user that Frevana Space CMS only supports.html, and ask for an.htmlfile. - Determine whether the user wants a new publication or an update. For an update, require the previous
file_keyfrom the caller; do not guess it or silently create new content. - Prefer the bundled script over manual HTTP calls.
- Let the script read
FREVANA_TOKEN. - For a new publication, run:
bash <skill-path>/scripts/publish_file.sh \
--file /absolute/path/to/result.html
- For an update, run:
bash <skill-path>/scripts/publish_file.sh \
--file /absolute/path/to/result.html \
--file-key "previous/file_key.html"
- If the script reports that
custom_domainis not configured, give the user the exact configuration link it prints and stop. Do not request a pre-upload URL or upload the file. - If the custom domain is configured, let the script call
POST /s3/custom-upload-url. For an update, the request includes the previousfile_key; for a new publication, it omitsfile_key. - Upload the specified file directly to the returned pre-signed destination.
- After the upload succeeds, let the script call
PUT /s3/content/{content_id}/publish?op_type=publish. - After both upload and publish succeed, return a JSON object containing
url,file_key, andcontent_idto the caller. - Explicitly tell the caller that a later update must send the returned
file_keyvalue unchanged as thefile_keyrequest parameter, which the script accepts through--file-key. - Let the caller associate and persist that result with its own Agent App ID. The skill must not save publication state locally.
- Do not expose the pre-signed upload URL, its query parameters, the bearer token, or raw credential files.
Options
--token <token> One-time Frevana bearer token override
--file <path> Local .html file to publish
--file-key <key> Previous file_key; include only when updating existing content
--title <title> Optional title override
--agent-id <id> Optional Frevana Agent ID
--team-id <id> Optional team ID
--session-id <id> Session/task ID fallback when team ID is unavailable
FREVANA_API_BASE_URL can override the API host for local testing.
ID Resolution
- Resolve
agent_idin this order:--agent-id,FREVANA_AGENT_ID,CODEX_AGENT_ID, then fixed fallbackfrevana-space-cms. - Resolve
team_idin this order:--team-id,FREVANA_TEAM_ID,CODEX_TEAM_ID, then the session fallback. - Resolve the session fallback in this order:
--session-id,FREVANA_SESSION_ID,CODEX_THREAD_ID,CODEX_SESSION_ID. - If neither a team ID nor session ID is available, omit optional
team_id.
HTML and Title Resolution
- Use
--titlewhen the user explicitly provides a title. - Otherwise use the first non-empty
<h1>, then<title>, thenog:titleortwitter:title. - If the HTML does not contain a usable title, use the filename without its
.htmlextension. - Reject
.htm, Markdown, JSON, images, PDFs, documents, and every other non-.htmlinput before checking the custom domain or calling Frevana.
Upload Behavior
- For a new publication, the custom upload URL request omits
file_key. - For an update, the custom upload URL request includes the exact previous
file_keyso Frevana updates the existing content instead of creating a new item. - The script uploads the file with PUT to the returned
presigned_url. - It passes the original path directly to
curl --upload-file; it does not create or upload a transformed copy. - Title extraction and fixed HTML metadata construction never write to the source file.
- It sends
Content-Type: text/htmlduring the upload. - It never forwards the Frevana authorization header to the object-storage upload URL.
- It reads
content_idfrom the custom upload URL response. - After a successful object upload, it sends
title, fixedpublish_type=custom_domain, and fixedcategory=agent_app_resulttoPUT /s3/content/{content_id}/publish?op_type=publish. - It treats the operation as successful only when both upload and publish return 2xx.
- It uses the public URL returned by the API. If the API returns only a file key, it builds the URL from the configured custom domain and that key.
- It prints one JSON object containing only
url,file_key, andcontent_id.
Caller-Owned State
- The skill is stateless and must not create a history file, sidecar file, or app-state directory.
- The caller owns the mapping between its Agent App ID and the returned
url,file_key, andcontent_id. - Treat the returned
file_keyas the update handle. For a later update, pass that exact value as thefile_keyfield toPOST /s3/custom-upload-url, or equivalently through--file-keywhen using the bundled script. - If an update response omits
key/file_key, the result retains the previousfile_keysupplied by the caller.
Example:
bash <skill-path>/scripts/publish_file.sh \
--file /absolute/path/to/updated.html \
--file-key "<file_key returned by the previous publish>"
Error Handling
- Missing or unreadable file: ask the user for a valid local file path.
- Non-
.htmlinput: reject it before any network request, tell the user that Frevana Space CMS only supports.html, and ask for a local.htmlfile. - Update requested without a caller-supplied previous
file_key: ask the caller for it and stop before any API request. - Missing token in a non-interactive run: tell the user to set
FREVANA_TOKENor use--token. - Missing custom domain: direct the user to
https://www.frevana.com/dashboard/domain. - Unexpected API response: report the error without printing credentials or a pre-signed URL.
- Upload failure: do not claim the file was published.
- Publish failure after upload: report that the file was uploaded but publishing failed, and do not return the public URL as a successful result.