
brewpage-publish
Publish content to brewpage.app — text, markdown, JSON, file, or multi-file site. Asks namespace and password, returns public URL. Triggers: publish, share link, upload to brewpage, host page, brewpage, publish site, upload site, upload directory, deploy site, сделай публичную ссылку, опубликуй.
- Installs
- 597
- Last 24h
- —
- Trending rank
- —
- Security
- Not audited
Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/kochetkov-ma/claude-brewcode --skill brewpage-publish- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads brewpage-publish automatically when relevant.
- 03
Review the result
The agent follows the SKILL.md steps, scripts and references bundled with the skill.
SKILL.md
The instructions your agent reads when the skill is triggered.
brewpage-publish
Publish content to brewpage.app — free instant hosting for HTML pages, JSON documents, files, and multi-file sites. No sign-up required.
Workflow
Step 1: Parse Arguments
Extract from $ARGUMENTS:
--ttl N→ TTL in days (default:15)--entry <filename>→ entry file for SITE uploads (default: auto-detect)--delivery-mode path|subdomain→ optional creation header; omitted means server defaults. Reject other values before upload.- Remaining text →
content_arg
Step 2: Detect Content Type
| Input | Type | API |
|---|---|---|
content_arg is a directory (test -d) | SITE | POST /api/sites (dir auto-zipped — primary path) |
content_arg ends with .zip AND file exists (test -f) | SITE | POST /api/sites (pre-built archive upload) |
content_arg is a file path AND file exists (test -f) | FILE | POST /api/files (multipart) |
content_arg starts with { or [ | JSON | POST /api/json |
| Anything else | HTML | POST /api/html (format=markdown) |
Mode rule: directory/ZIP → SITE. Single file → FILE. POST /api/sites accepts ONLY a multipart archive=@file.zip — there is no raw-folder upload, so a directory is auto-zipped on the fly (the robust default; archive sealing keeps relative paths intact). Stats per type — SITE (dir): HTML count, total size, entry file. SITE (ZIP): file size, entry override. FILE: size + MIME via file --mime-type -b. TEXT/JSON: char count.
Step 3: Show Pre-Publish Stats
For HTML/JSON/FILE:
Content: <type description> · <size> · <api endpoint>
TTL: <N> days
For SITE: detect entry file using priority: 1) --entry flag, 2) index.html exists, 3) first .html file alphabetically.
Built-static guard (run BEFORE zipping). Publish BUILT output, never project sources:
- If the directory contains no
.htmlfile at all → FAIL with an explicit error: "No.htmlfound — build the site first, then point at the build output directory." Do not guess an entry. - If the directory looks like un-built sources (has
package.json+src/but no top-level.html) → warn and ask the user to point at the build output instead (dist/,build/,out/,_site/, orpublic/). Do not zip the source tree.
Content: site · <N> files · <total_size> · POST /api/sites
Entry: <entry_file>
TTL: <N> days
Step 4: Ask Namespace
Use AskUserQuestion:
Namespace controls discovery and appears in publication addresses on brewpage.app.
By default publishing is PRIVATE (unlisted): not in the public gallery and not indexed by search engines. The link is not secret, though — anyone who has it can open it (use a password to restrict access).
Choose `public` for eligible gallery discovery. Eligible Promotion publications may be indexed; Dedicated subdomain hosts use noindex.
Options:
1) public — eligible gallery discovery; eligible Promotion publications may be indexed
2) {auto-suggested 6-8 char slug} — private, link-only (default)
3) Enter custom namespace
4) Skip → use suggested slug (private)
Reply with a number or your custom namespace (1-32 lowercase letters, digits or hyphens).
Auto-suggest: generate a meaningful short slug (3-16 chars, lowercase alphanumeric + hyphens) from content context:
- File → topic/purpose of the file (e.g.
api-docs,login-page,report-q2) - Text/HTML → main subject or title (e.g.
pricing,team-intro,changelog) - JSON → data type or schema name (e.g.
user-config,metrics) - Fallback → project name or directory name if content is ambiguous Never use random strings or truncated filenames — the slug should be human-readable and describe what's being published.
Resolution:
2,4, or empty → suggested slug1→public3or any other string → use as-is
Step 5: Ask Password
Use AskUserQuestion:
Password protection (if set, page is hidden from gallery):
Options:
1) No password (default)
2) Random: {generated 6-char password, e.g. "kx7p2m"}
3) Enter custom password (min 4 chars)
4) Skip → no password
Reply with a number or your custom password.
Generate random password EXECUTE using Bash tool:
LC_ALL=C tr -dc 'a-z0-9' < /dev/urandom | head -c6 2>/dev/null
Resolution:
1,4, or empty → no password2→ use generated random password3or custom text → use as-is
Step 6: Publish and Save Token (secure)
NEW sites and non-public namespaces require Dedicated subdomain (subdomain); explicit path is rejected.
NEW public non-sites default to Promotion (path) and may select subdomain, including password-protected uploads.
Set DELIVERY_MODE to the validated flag value or empty when omitted; send only X-Delivery-Mode, never authored-body fields.
Deduplication may return an OLD or NEW winner: retain its identity, cohort, mode and exact server link, even when the requested mode differs.
Missing/null OLD routing metadata means Existing link; never infer mode from its URL.
SECURITY: The ownerToken MUST NEVER appear in conversation output. The bash blocks below handle curl + token parsing + history save atomically; the LLM sees only the URL. Each block sets
PASS_Hfirst (empty array when no password) and uses"${PASS_H[@]}"quoted — passwords are never string-interpolated into the command. The site-dir zip excludes (.git/,.env*, etc.) are also a secret-leak safeguard — they keep credentials and VCS data out of the published archive.
6a. Init history file (run once, before the publish block) — EXECUTE using Bash tool:
HISTORY_FILE=".claude/brewpage-history.md"
if [ ! -f "$HISTORY_FILE" ]; then
mkdir -p "$(dirname "$HISTORY_FILE")"
cat > "$HISTORY_FILE" <<'HEADER'
# brewpage.app — Published Pages
> PRIVATE FILE — keep this out of version control and never share it.
> Owner tokens allow delete and in-place republish (html/json/kv/sites all support PUT).
> Delete html/json/kv: `curl -s -X DELETE "https://brewpage.app/api/{ns}/{id}" -H "X-Owner-Token: TOKEN"`
> Delete site: `curl -s -X DELETE "https://brewpage.app/api/sites/{ns}/{id}" -H "X-Owner-Token: TOKEN"`
> Update site (keep same URL): `PUT /api/sites/{ns}/{id}` with `X-Owner-Token: TOKEN` + the new bundle — the uploaded bundle fully replaces the file set (adds new files, removes absent ones, overwrites matching). The link never changes.
| Date | URL | Owner Token | TTL | Type | Owner API | Identity |
|------|-----|-------------|-----|------|-----------|----------|
HEADER
fi
Then run ONE of the following publish blocks based on detected type. Each assumes HISTORY_FILE already exists from 6a.
HTML/Markdown text — EXECUTE using Bash tool:
HISTORY_FILE=".claude/brewpage-history.md"
CONTENT=$(cat <<'BREWPAGE_EOF'
{content}
BREWPAGE_EOF
)
PAYLOAD=$(jq -n --arg c "$CONTENT" '{content: $c}')
DELIVERY_H=()
case "${DELIVERY_MODE:-}" in
'') : ;;
path|subdomain) DELIVERY_H=(-H "X-Delivery-Mode: $DELIVERY_MODE") ;;
*) echo "FAILED: delivery mode must be path or subdomain"; exit 1 ;;
esac
PASS_H=()
[ -n "$PASSWORD" ] && PASS_H=(-H "X-Password: $PASSWORD")
RESPONSE=$(curl -s -X POST "https://brewpage.app/api/html?ns={ns}&ttl={days}&format=markdown" \
-H "Content-Type: application/json" \
"${PASS_H[@]}" "${DELIVERY_H[@]}" \
-d "$PAYLOAD")
URL=$(echo "$RESPONSE" | jq -r '.link // empty')
TOKEN=$(echo "$RESPONSE" | jq -r '.ownerToken // empty')
OWNER_API=$(echo "$RESPONSE" | jq -r '.ownerLink // empty')
IDENTITY=$(echo "$RESPONSE" | jq -c '{id, namespace, type, routingCohort, deliveryMode, modeLocked, hostingVersion, managementLink}')
if [ -n "$URL" ]; then
[ -n "$TOKEN" ] && echo "| $(date '+%Y-%m-%d %H:%M') | [$URL]($URL) | \`$TOKEN\` | {ttl}d | html | $OWNER_API | \`$IDENTITY\` |" >> "$HISTORY_FILE"
echo "OK $URL"
else
echo "FAILED: publish rejected (no .link in response)"
fi
JSON — EXECUTE using Bash tool:
HISTORY_FILE=".claude/brewpage-history.md"
DELIVERY_H=()
case "${DELIVERY_MODE:-}" in
'') : ;;
path|subdomain) DELIVERY_H=(-H "X-Delivery-Mode: $DELIVERY_MODE") ;;
*) echo "FAILED: delivery mode must be path or subdomain"; exit 1 ;;
esac
PASS_H=()
[ -n "$PASSWORD" ] && PASS_H=(-H "X-Password: $PASSWORD")
RESPONSE=$(curl -s -X POST "https://brewpage.app/api/json?ns={ns}&ttl={days}" \
-H "Content-Type: application/json" \
"${PASS_H[@]}" "${DELIVERY_H[@]}" \
-d '{original_json}')
URL=$(echo "$RESPONSE" | jq -r '.link // empty')
TOKEN=$(echo "$RESPONSE" | jq -r '.ownerToken // empty')
OWNER_API=$(echo "$RESPONSE" | jq -r '.ownerLink // empty')
IDENTITY=$(echo "$RESPONSE" | jq -c '{id, namespace, type, routingCohort, deliveryMode, modeLocked, hostingVersion, managementLink}')
if [ -n "$URL" ]; then
[ -n "$TOKEN" ] && echo "| $(date '+%Y-%m-%d %H:%M') | [$URL]($URL) | \`$TOKEN\` | {ttl}d | json | $OWNER_API | \`$IDENTITY\` |" >> "$HISTORY_FILE"
echo "OK $URL"
else
echo "FAILED: publish rejected (no .link in response)"
fi
File — EXECUTE using Bash tool:
HISTORY_FILE=".claude/brewpage-history.md"
DELIVERY_H=()
case "${DELIVERY_MODE:-}" in
'') : ;;
path|subdomain) DELIVERY_H=(-H "X-Delivery-Mode: $DELIVERY_MODE") ;;
*) echo "FAILED: delivery mode must be path or subdomain"; exit 1 ;;
esac
PASS_H=()
[ -n "$PASSWORD" ] && PASS_H=(-H "X-Password: $PASSWORD")
RESPONSE=$(curl -s -X POST "https://brewpage.app/api/files?ns={ns}&ttl={days}" \
"${PASS_H[@]}" "${DELIVERY_H[@]}" \
-F "file=@/absolute/path/to/file")
URL=$(echo "$RESPONSE" | jq -r '.link // empty')
TOKEN=$(echo "$RESPONSE" | jq -r '.ownerToken // empty')
OWNER_API=$(echo "$RESPONSE" | jq -r '.ownerLink // empty')
IDENTITY=$(echo "$RESPONSE" | jq -c '{id, namespace, type, routingCohort, deliveryMode, modeLocked, hostingVersion, managementLink}')
if [ -n "$URL" ]; then
[ -n "$TOKEN" ] && echo "| $(date '+%Y-%m-%d %H:%M') | [$URL]($URL) | \`$TOKEN\` | {ttl}d | file | $OWNER_API | \`$IDENTITY\` |" >> "$HISTORY_FILE"
echo "OK $URL"
else
echo "FAILED: publish rejected (no .link in response)"
fi
Site (directory) — EXECUTE using Bash tool:
HISTORY_FILE=".claude/brewpage-history.md"
DELIVERY_H=()
case "${DELIVERY_MODE:-}" in
'') : ;;
path|subdomain) DELIVERY_H=(-H "X-Delivery-Mode: $DELIVERY_MODE") ;;
*) echo "FAILED: delivery mode must be path or subdomain"; exit 1 ;;
esac
PASS_H=()
[ -n "$PASSWORD" ] && PASS_H=(-H "X-Password: $PASSWORD")
TMPZIP=$(mktemp /tmp/brewpage-site-XXXXXX.zip) || { echo "FAILED: cannot allocate site archive"; exit 1; }
rm -f "$TMPZIP" || { echo "FAILED: cannot prepare site archive"; exit 1; }
# Exclude VCS, secrets, deps, editor + OS junk and sourcemaps — publish only built static assets.
if ! (cd "{directory_path}" && zip -r "$TMPZIP" . -x '.git/*' '*/.git/*' '.env' '.env.*' '*/.env' '*/.env.*' 'node_modules/*' '*/node_modules/*' '.DS_Store' '*/.DS_Store' 'Thumbs.db' '.idea/*' '*/.idea/*' '.vscode/*' '*/.vscode/*' '.cache/*' '*/.cache/*' '*.map' '*.log') ||
[ ! -s "$TMPZIP" ] || ! unzip -tq "$TMPZIP" >/dev/null; then
rm -f "$TMPZIP"
echo "FAILED: site archive creation or verification failed"
exit 1
fi
RESPONSE=$(curl -s -X POST "https://brewpage.app/api/sites?ns={ns}&ttl={days}&entry={entry}" \
-H "User-Agent: ClaudeCode/1.0" \
"${PASS_H[@]}" "${DELIVERY_H[@]}" \
-F "archive=@$TMPZIP")
rm -f "$TMPZIP"
URL=$(echo "$RESPONSE" | jq -r '.link // empty')
TOKEN=$(echo "$RESPONSE" | jq -r '.ownerToken // empty')
OWNER_API=$(echo "$RESPONSE" | jq -r '.ownerLink // empty')
IDENTITY=$(echo "$RESPONSE" | jq -c '{id, namespace, type, routingCohort, deliveryMode, modeLocked, hostingVersion, managementLink}')
FCOUNT=$(echo "$RESPONSE" | jq -r '.fileCount // "?"')
if [ -n "$URL" ]; then
[ -n "$TOKEN" ] && echo "| $(date '+%Y-%m-%d %H:%M') | [$URL]($URL) | \`$TOKEN\` | {ttl}d | site ($FCOUNT files) | $OWNER_API | \`$IDENTITY\` |" >> "$HISTORY_FILE"
echo "OK $URL | Files: $FCOUNT"
else
echo "FAILED: publish rejected (no .link in response)"
fi
Site (ZIP file) — EXECUTE using Bash tool:
HISTORY_FILE=".claude/brewpage-history.md"
DELIVERY_H=()
case "${DELIVERY_MODE:-}" in
'') : ;;
path|subdomain) DELIVERY_H=(-H "X-Delivery-Mode: $DELIVERY_MODE") ;;
*) echo "FAILED: delivery mode must be path or subdomain"; exit 1 ;;
esac
PASS_H=()
[ -n "$PASSWORD" ] && PASS_H=(-H "X-Password: $PASSWORD")
RESPONSE=$(curl -s -X POST "https://brewpage.app/api/sites?ns={ns}&ttl={days}&entry={entry}" \
-H "User-Agent: ClaudeCode/1.0" \
"${PASS_H[@]}" "${DELIVERY_H[@]}" \
-F "archive=@{zip_file_path}")
URL=$(echo "$RESPONSE" | jq -r '.link // empty')
TOKEN=$(echo "$RESPONSE" | jq -r '.ownerToken // empty')
OWNER_API=$(echo "$RESPONSE" | jq -r '.ownerLink // empty')
IDENTITY=$(echo "$RESPONSE" | jq -c '{id, namespace, type, routingCohort, deliveryMode, modeLocked, hostingVersion, managementLink}')
FCOUNT=$(echo "$RESPONSE" | jq -r '.fileCount // "?"')
if [ -n "$URL" ]; then
[ -n "$TOKEN" ] && echo "| $(date '+%Y-%m-%d %H:%M') | [$URL]($URL) | \`$TOKEN\` | {ttl}d | site ($FCOUNT files) | $OWNER_API | \`$IDENTITY\` |" >> "$HISTORY_FILE"
echo "OK $URL | Files: $FCOUNT"
else
echo "FAILED: publish rejected (no .link in response)"
fi
Step 7: Output Result
Success (bash printed OK {url}):
Published: {url from bash output}
Owner token saved to .claude/brewpage-history.md
Success for SITE (bash printed OK {url} | Files: {count}):
Published site: {url from bash output}
Entry: {entry_file} | Files: {count}
Owner token saved to .claude/brewpage-history.md
Share the server URL exactly as printed, including any trailing slash.
For a private (non-public) namespace, append one short line after the link (skip if the reply must stay ultra-brief): Unlisted link — anyone who has it can open it, but it's not in the gallery or search. Want it discoverable? Publish to public.
NEVER print the ownerToken in conversation. The token lives only in the history file.
Error (bash printed FAILED: ...):
Publish failed.
Notes
- Always use absolute file paths with curl
-F "file=@...". - Use
jq -n --arg c "$CONTENT" '{content: $c}'to safely encode text content.formatis a query param, not a body field —/api/htmlignores anyformatkey inside the JSON body and reads only?format=from the URL. Wrong location = server applies defaulthtmland stores your markdown as raw text. - TTL default is
15days. Namespace must match^[a-z0-9-]{1,32}$, default: suggested (private) namespace. - To delete a published page, find the owner token in
.claude/brewpage-history.mdand use the delete command shown in that file's header. - Use returned
ownerLinkand stored identity metadata for owner API operations; never parse NEW root hosts for namespace/ID. OLD history without metadata retains its existing API identifiers. - To update a published site,
PUTthe replacement bundle to its apex owner API withX-Owner-Token; retain the host and omitX-Delivery-Modeon ordinary PUT/update. - Only NEW public non-sites allow owner-only
PATCH /api/{type}/{ns}/{id}/hostingwith{"deliveryMode":"subdomain","expectedVersion":1}from current identity metadata. OLD, sites and non-public identities have no mode choice. Use the returned URL/version afterward. - NEW password-protected links stay clean: never generate or append
?p=. API requests still useX-Password; OLD password behavior remains unchanged. - Sites: directory is the primary input — it is auto-zipped (the only thing
POST /api/sitesaccepts), which seals relative paths. A pre-built.zipis the alternative input, uploaded as-is. Always publish BUILT output (dist/,build/,out/,_site/,public/), never project sources. - The auto-zip excludes
.git/,.env/.env.*,node_modules/, editor/OS junk, sourcemaps and logs — a deliberate secret-leak safeguard so credentials and VCS history never reach the public archive. - Entry file detection:
--entryoverride >index.html> first.htmlalphabetically. - Preserve
.linkexactly: NEW subdomain roots retain/; OLD links retain their existing form. Never reconstruct a host from IDs. - Verify NEW native sites at the exact returned URL and asset paths; a browser proves rendering. OLD sites may still use the landing-page redirect; verify those in a browser or fetch their explicit entry asset.
Powered by
| brewpage.app | Free instant hosting — HTML, JSON, files, sites, KV. No sign-up. |
| brewcode | Claude Code plugin suite — infinite tasks, code review, skills, hooks. |
FAQ
What does the brewpage-publish skill do?
Publish content to brewpage.app — text, markdown, JSON, file, or multi-file site. Asks namespace and password, returns public URL. Triggers: publish, share link, upload to brewpage, host page, brewpage, publish site, upload site, upload directory, deploy site, сделай публичную ссылку, опубликуй.
How do I install brewpage-publish?
Run npx skills add https://github.com/kochetkov-ma/claude-brewcode --skill brewpage-publish in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/brewpage-publish/ (personal) or .claude/skills/brewpage-publish/ (project).
Which AI agents can use brewpage-publish?
Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.
Is brewpage-publish safe to install?
No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.
Who maintains brewpage-publish?
It is published by kochetkov-ma in kochetkov-ma/claude-brewcode. It has 597 recorded installs.
More from kochetkov-ma/claude-brewcode
text-optimizer
kochetkov-ma/claude-brewcode
Optimizes text, prompts, and documentation for LLM token efficiency. Applies 52 research-backed rules across 8 categories: Claude behavior, token efficiency, structure, deduplication, reference integrity, perception, LLM comprehension, and aggressive lossy (deep only). Use when optimizing prompts, reducing tokens, compressing verbose docs, or improving LLM instruction quality.
memory-optimize
kochetkov-ma/claude-brewcode
Optimizes Claude Code memory files in 4 interactive steps: removes duplicates, migrates rules to CLAUDE.md/rules files, compresses remaining entries, validates with cleanup. Typical reduction: 30-50% on token count.
Popular devops & cloud skills
microsoft-foundry
microsoft/azure-skills
Build, deploy, evaluate, optimize, fine-tune, and manage Microsoft Foundry agents, models, and resources end to end. USE FOR: foundry, azd ai agent, azd provision/deploy, hosted agent scaffold/develop/run/deploy/troubleshoot, prompt agent create, managed harness agent create, GitHub Copilot harness agent, create agent, update agent, add tool to agent, invoke agent, agent insights, evaluate agent, batch eval, continuous eval, continuous monitoring, agent CI/CD, optimize prompt, improve prompt, optimize agent instructions, Agent Optimizer scaffold, dataset curation from traces, deploy model, model fine-tuning (SFT/DPO/RFT), Foundry project, RBAC, role assignment, permissions, quota, capacity, region, deployment failure, AI Services, create Foundry resource, knowledge index, customize deployment, onboard, availability, training-data, grader, distillation, large file upload. DO NOT USE FOR: Azure Functions, App Service, general Azure deploy (use azure-deploy), general Azure prep (use azure
azure-diagnostics
microsoft/azure-skills
Debug Azure production issues on Azure using AppLens, Azure Monitor, resource health, and safe triage. WHEN: debug production issues, troubleshoot app service, app service high CPU, app service deployment failure, troubleshoot container apps, container app 503 or target port mismatch, troubleshoot functions, function telemetry missing or stopped after a config/connection-string change, troubleshoot AKS, VM RDP, Linux SSH, VM black screen, can't connect to VM, reset VM password, NSG or firewall blocking, kubectl cannot connect, kube-system/CoreDNS failures, pod pending, crashloop, node not ready, upgrade failures, analyze logs, KQL, insights, image pull failures, cold start issues, health probe failures, resource health, root cause of errors, troubleshoot event hubs, troubleshoot service bus, messaging SDK error, AMQP connection failure, message lock lost, lock renewal during long-running processing, service bus dead letter.
azure-prepare
microsoft/azure-skills
Prepare azd-based Azure projects for deployment: generates azure.yaml, infrastructure (Bicep/Terraform), and Dockerfiles for the Azure Developer CLI (azd) workflow. USE ONLY when the user explicitly wants to use azd as the deployment tool, or the project already has an azure.yaml file. DO NOT USE FOR: non-azd deployments, Python App Service code-only deploys (use python-appservice-deploy), or cross-cloud migration (use azure-cloud-migrate). WHEN: prepare app for azd, create azure.yaml, set up azd infrastructure, modernize app for Azure with azd, deploy with azd, function app, timer trigger, service bus trigger, event-driven function, managed identity, generate Bicep, generate Terraform, create and deploy to Azure.
azure-ai
microsoft/azure-skills
Use for Azure AI: Search, Speech, OpenAI, Document Intelligence. Helps with search, vector/hybrid search, speech-to-text, text-to-speech, transcription, OCR. WHEN: AI Search, query search, vector search, hybrid search, semantic search, speech-to-text, text-to-speech, transcribe, OCR, convert text to speech.
azure-deploy
microsoft/azure-skills
Execute Azure deployments for ALREADY-PREPARED applications that have existing .azure/deployment-plan.md and infrastructure files. DO NOT use this skill when the user asks to CREATE a new application — use azure-prepare instead. This skill runs azd up, azd deploy, terraform apply, and az deployment commands with built-in error recovery. Requires .azure/deployment-plan.md from azure-prepare and validated status from azure-validate. WHEN: "run azd up", "run azd deploy", "execute deployment", "push to production", "push to cloud", "go live", "ship it", "bicep deploy", "terraform apply", "publish to Azure", "launch on Azure". DO NOT USE WHEN: "create and deploy", "build and deploy", "create a new app", "set up infrastructure", "create and deploy to Azure using Terraform" — use azure-prepare for these.
azure-validate
microsoft/azure-skills
Pre-deployment validation for Azure readiness. Run deep checks on configuration, infrastructure (Bicep or Terraform), RBAC role assignments, managed identity permissions, and prerequisites before deploying. WHEN: validate my app, check deployment readiness, run preflight checks, verify configuration, check if ready to deploy, validate azure.yaml, validate Bicep, test before deploying, troubleshoot deployment errors, validate Azure Functions, validate function app, validate serverless deployment, verify RBAC roles, check role assignments, review managed identity permissions, what-if analysis, validate Container Apps deployment.