Install
$ agentstack add skill-nexu-io-roast-skill-deploy ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
deploy-skill
Deploy a zipped static website bundle to Cloudflare Pages through the remote deploy server.
Default production gateway:
https://deploy.nexu.io
This skill is self-contained:
- it reads its own deploy server config from
~/.nexu/deploy-skill.json - it resolves the Nexu cloud API key using a multi-path fallback (see below)
- it stores submitted jobs in
~/.nexu/deploy-skill-jobs.json - it can either submit an existing zip or render a built-in template into a zip first
- it submits the resulting zip directly to the deploy server
- it emits a follow-up async payload so the final completion message is delivered later
Nexu cloud credential lookup
The skill searches the following config.json locations in order and uses the first one that contains a valid desktop.cloud section with connected: true and a non-empty apiKey:
{NEXU_HOME}/config.json— respects an explicitNEXU_HOMEenv var, otherwise~/.nexu/config.json.~/Library/Application Support/@nexu/desktop/.nexu/config.json— the real location used by the Nexu desktop app on macOS.~/.nexu/config.json— legacy fallback (skipped if already covered by candidate 1).
Resolution rules:
- If a candidate file exists and has a
desktop.cloudsection, that file is authoritative — the skill either uses itsapiKeyor fails with a specific error for that file. It does not fall through to the next candidate in that case. - If a candidate file is missing, or exists but has no
desktop.cloudsection at all, the skill moves on to the next candidate. - If every candidate falls through, the skill fails with a "could not find a Nexu cloud configuration" error that lists every path it checked.
This means a user who has logged into the Nexu desktop app (which writes to candidate 2) will have their API key picked up automatically, even if the older ~/.nexu/config.json is empty or legacy.
Requirements
- Node.js 24+
baseUrlconfigured in~/.nexu/deploy-skill.json- a logged-in Nexu cloud account so
~/.nexu/config.jsoncontainsdesktop.cloud.apiKey
Setup
The production deploy gateway for this skill is:
https://deploy.nexu.io
Configure the deploy server base URL:
node scripts/deploy_skill.js setup --base-url https://deploy.nexu.io
Validate the setup:
node scripts/deploy_skill.js check
Submit a Deploy
node scripts/deploy_skill.js submit \
--zip /absolute/path/to/site.zip \
--bot-id BOT_ID \
--chat-id CHAT_ID \
--chat-type channel \
--channel slack \
[--to DELIVERY_TARGET] \
[--thread-id THREAD_ID] \
[--account-id ACCOUNT_ID] \
[--session-key SESSION_KEY] \
[--user-id USER_ID]
On success, the command returns immediately and emits a sessions_spawn payload so the runtime can continue polling in the background.
Submit a Template Candidate
The first built-in candidate template is distill-campaign.
node scripts/deploy_skill.js submit \
--template-id distill-campaign \
--content-file /absolute/path/to/content.json \
--bot-id BOT_ID \
--chat-id CHAT_ID \
--chat-type channel \
--channel slack \
[--to DELIVERY_TARGET] \
[--thread-id THREAD_ID] \
[--account-id ACCOUNT_ID] \
[--session-key SESSION_KEY] \
[--user-id USER_ID]
The content file must be structured JSON with this exact frame. Each field maps to a specific slot in the rendered page layout — write content with the target slot in mind.
Left sidebar (identity panel):
title: 2-10 characters — user's name / cyber-persona headline, shown in.profile-nameunder the avatar.subtitle: 15-30 characters and must include牛马指数,/100, and—— short signature line rendered as.profile-subdirectly under the name. Example format:牛马指数 92/100 — 龙虾成瘾者.portraitId: must be one ofportrait-1throughportrait-7— chooses the avatar image shown in the sidebar AND on eachbotchat bubble.tags: 1-8 strings, each 2-8 characters — rendered both as the social-tag chips in the sidebar and as the quick-reply prompt buttons in the chat card (first 4). Keep tags punchy, noun-like, suitable for both roles.
Right column (tabbed layout: 核心指标 / 深度扒皮 / 和我对话 / 技能文件):
metrics: 4-6 items total.metrics[0]becomes the hero score card (big number + label) in the 核心指标 tab and also drives the poster overlay score; itsvalueshould be a bare integer (e.g."92", no%).metrics[1..]become the horizontal bar chart rows below the species card, each with an SVG icon and a percentage bar — theirvalueshould be a percentage string (e.g."88%").posterSpeciesEmoji: short emoji (1-4 chars) — shown in the species card next to the name and in the poster text overlay.posterSpeciesName: 3-8 characters — the "物种" name in the species card (e.g.龙虾成瘾者).posterSpeciesSub: 5-8 characters — small subtitle under the species name (e.g.办公室物种鉴定).description: 150-250 characters, no markdown, HTML, or newlines — the main roast paragraph rendered as.roast-textinside the 核心指标 tab, above the bar chart. Write it as one dense paragraph; the template does not support paragraph breaks here.qaCards: 2-3 items, each{ question, answer }— the 深度扒皮 tab. Each card gets a rotating icon (🔥 💪 💀 …).questionis the title (short, label-style),answeris the body (1-3 sentences per card).dialogs: 3-6 items, each{ speaker: "bot" | "user", text }— the 和我对话 tab. The first message should usually be abotintro. The template alternates bubbles and shows the avatar next tobotmessages.ctaText: must equal⭐ 生成我的牛马锐评— shown in the "蒸馏完成度" progress header in the 技能文件 tab.installText: must equal复制链接发给你的 nexu agent:https://github.com/nexu-io/roast-skill— shown inside the copy-to-clipboard code block in the 技能文件 tab.
Poster (share modal):
- The template ships a static
assets/poster.pngartwork as the backdrop. The following fields are overlaid as text on top of the artwork:title,subtitle,metrics[0].value,metrics[0].label, andposterSpeciesEmoji+posterSpeciesName. There is no per-user image composition — the poster artwork is the same PNG for every user; only the text overlay changes.
If any field violates the frame, the skill rejects the payload and does not render. It never truncates, rewrites, or invents missing values.
Portrait rule:
- The agent must choose
portraitIdexplicitly. - The skill does not randomly pick a head portrait anymore.
- Any missing or unknown
portraitIdis rejected before rendering.
To restore unfinished jobs after a restart:
node scripts/deploy_skill.js recover
Final Success Message
When the deploy finishes successfully, the async follow-up must tell the user exactly:
> Your website is ready, the link is {link}
Mandatory Guard Checklist
This skill has a hard anti-hallucination rule. The model must verify each step before it can describe that step as successful.
Submit step checks:
- confirm
~/.nexu/deploy-skill.jsonexists and contains a validbaseUrl - confirm
~/.nexu/config.jsoncontains a connected Nexu cloud account with a non-empty API key - confirm either the upload path exists and ends with
.zip, or the template id is registered and the content file matches the template schema - confirm submit sends
Authorization: Bearerfrom the local Nexu config - confirm the server response contains a real
jobId - confirm
taskTypeis exactlystatic-deploy - confirm
statusis exactlyqueuedorrunning - if a delivery target is available, confirm it is persisted as
toin the local job record so later notification does not need to guess the recipient - confirm the accepted job was persisted locally with the same
jobIdandstatus
Polling step checks:
- confirm the queried job already exists in
~/.nexu/deploy-skill-jobs.json - confirm polling sends the same
Authorization: Bearerfrom the local Nexu config - confirm the server response still references the same
jobId - confirm
statusis one ofqueued,running,succeeded,failed, orcancelled - if
statusissucceeded, confirmresult.urlexists and ends with.nexu.spacebefore generating any success message - if
statusisfailedorcancelled, relay the server error message and hint instead of inventing one - if polling times out, only fall back to a temporary
.pages.devlink when that link already exists in the persisted job record
Output rule:
- If any check fails, stop and return the explicit guard-check error.
- Never claim “deployment started” or “website is ready” until the matching guard checklist has passed.
- Timeout fallback message must be:
Your page has been deployed to the temporary domain {pagesDevLink}. If you cannot access this domain, you can retry deploy again.
Rules
- Never invent a job id, URL, or completion state.
- Never invent the delivery target. Persist the concrete
totarget when it is known. - Never say the site is ready during submit.
- Always reject malformed server responses instead of guessing missing fields.
- Always use the local persisted job record for recovery and polling.
- If the server returns an explicit error message or hint, relay it instead of rewriting it.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: nexu-io
- Source: nexu-io/roast-skill
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.