feat: add deploy-to-cloud-engine skill#212
Conversation
New Infrastructure skill that deploys an already-built ICP project to a user's own cloud engine: verify the icp CLI, link the user's console identity with `icp identity link web --auth <console-origin>`, obtain the console origin and subnet id (asking when unknown), and run `icp deploy -e ic --subnet <subnet-id>`. Includes evaluations/deploy-to-cloud-engine.json (output + trigger evals). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Skill Validation ReportValidating skill: /home/runner/work/icskills/icskills/skills/deploy-to-cloud-engineStructure
Frontmatter
Markdown
Tokens
Content Analysis
Contamination Analysis
Result: passed Project Checks |
- Console origin now defaults to https://opencloud.org (the main OpenCloud console): the agent states the default and offers an override instead of asking open-endedly. Subnet id stays a hard ask — it cannot be guessed. - Pitfall 2 gains a recovery path for an unauthorized deploy after linking against the default origin. - Fix `icp default` -> `icp identity default` (the former does not exist in icp 0.3.0), in both the skill and the evals. - Evals: case 1 expects default-with-override behavior; new override case for a non-default console origin. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…acts - Step 1 starts with `icp identity list`: the CLI cannot reveal which console an identity was linked against, so route by what exists — no web-linked identity -> link; recognizable identity -> set active; unsure -> relink under a new name (cheap and safe). Verify with `icp identity default` / `icp identity principal`. - Warn never to omit --auth: its built-in default is https://id.ai, not the console (verified against icp 0.3.0 --help). - Document the 'Press Enter to log in' prompt that stalls the link command in non-interactive shells (hit in a real agent deploy). - Step 3 names the frontend URL form https://<id>.icp0.io and the console's 'Open in browser' link. - compatibility: icp-cli >= 0.3.0 (commands verified on 0.3.0). - Evals: stalled-link case, deploy-as-anonymous case (pitfall 5 had no coverage), marketplace .icp packaging near-miss in should_not_trigger. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add a step explaining how to tag canisters with __META_PROJECT / __META_NAME / __META_MAIN_CANISTER via settings.environment_variables so the cloud engine console groups them into one named application with labelled canisters and an "Open" button, instead of bare principal rows. icp-cli merges these with the auto-injected PUBLIC_CANISTER_ID:* vars (verified against 0.3.0). Renumber deploy/verify steps, add two pitfalls, and surface naming in the skill description. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add two output evals (naming a deployed app via __META_PROJECT / __META_NAME / __META_MAIN_CANISTER in settings.environment_variables, and an adversarial "no Open button" case checking the literal "true" value), two should_trigger queries for console-naming requests, and mention the metadata in the eval-file description. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
marc0olo
left a comment
There was a problem hiding this comment.
Skill and evals review — deploy-to-cloud-engine
Good skill. Covers genuinely new territory (nothing in icp-cli handles the --auth identity link, subnet targeting, or __META_* console metadata), end-to-end verified, and the without-skill baseline confirms the delta is real — baseline invents dfx deploy --network ic for every flow question. Validation passes; triggers are perfect 9/9 / 8/8.
I ran the full suite. Three failures in the WITH-skill results, analysed below.
Eval results — node scripts/evaluate-skills.js deploy-to-cloud-engine
| Eval | WITH skill | WITHOUT skill |
|---|---|---|
| Deploy a built project to a cloud engine | 6/6 ✅ | 0/6 |
| Just the link command | 3/4 |
1/4 |
| Adversarial: wrong --auth origin | 4/4 ✅ | 1/4 |
| Override: non-default console origin | 4/4 ✅ | 1/4 |
| Adversarial: guessing the subnet id | 3/3 ✅ | 1/3 |
| Agent pitfall: link command stalls non-interactively | 4/4 ✅ | 0/4 |
| Adversarial: deploying as anonymous | 4/4 ✅ | 2/4 |
| Adversarial: dfx to the engine | 3/4 |
0/4 |
| Name the app in the engine console | 6/6 ✅ | 0/6 |
| Adversarial: named app but no Open button | 3/4 |
1/4 |
| Trigger evals | 9/9 should-trigger | 8/8 should-not-trigger |
Total: 40/43 WITH | 8/43 WITHOUT
Required before merge
1. printf '\n' | — the "Press Enter" wording will cause silent failures
Step 1 says "supply the Enter keypress (pipe an empty line)". On icp-cli 0.3.2 (verified in PR #217 agent-web-identity), redirecting stdin from /dev/null produces a bare EOF that does not satisfy the prompt — the command sits on Press Enter to log in indefinitely, no browser opens, and the flow wastes the first sign-in attempt. Piping an actual newline is the only reliable fix:
printf '\n' | icp identity link web <your-identity-name> --auth <console-origin>Update both the Step 1 prose and Pitfall 1 to use this form, and add an explicit note: do NOT redirect from /dev/null.
2. Eval 2 — prompt/expected_behavior mismatch (false failure)
Prompt: "Give me only the command … No deploy steps."
Expected behavior: "Mentions a browser tab opens and the user completes the Internet Identity sign-in there."
These contradict. Asking for only the command and then checking for surrounding context is a design bug — the failure here is in the eval, not the skill. Two options: (a) remove that expected_behavior, or (b) drop the "No deploy steps" scope restriction and reword to "Give me the link command and what to expect when I run it."
3. Pitfall 6 too thin — causing real eval 8 failure (3/4)
The failure in "Adversarial: dfx to the engine": when correcting dfx misuse, the agent produced icp identity link web without <name> and --auth <console-origin>. Pitfall 6 currently reads only "This ecosystem uses icp, never dfx." — not enough to anchor the full command signature under adversarial conditions. Strengthen it to show the complete correction:
6. **Using `dfx`.** This ecosystem uses `icp`, never `dfx`. The correct sequence is:
`icp identity link web <name> --auth <console-origin>` (Step 1), then
`icp deploy -e ic --subnet <subnet-id>` (Step 3).
Suggested improvements (not blocking)
Missing inline icp.yaml example in Step 2. The text says "For a single inline icp.yaml, put the same block under each canister entry instead" but shows no YAML. Since agents use code blocks directly, prose-only guidance is a gap for the common case of single-file projects. Add a snippet:
# icp.yaml
canisters:
frontend:
recipe: ...
settings:
environment_variables:
__META_PROJECT: "My App"
__META_NAME: "Frontend"
__META_MAIN_CANISTER: "true"
backend:
recipe: ...
settings:
environment_variables:
__META_PROJECT: "My App"
__META_NAME: "Backend"Eval 10 — name the command explicitly. The failure was the agent said "redeploy" without naming icp deploy. Change the expected_behavior to check that the agent says icp deploy specifically — it matters that the right command is named.
Pitfall 4 — weak, not a failure mode. "Assuming a fixed identity name" is a clarification about a placeholder value, not a failure path. The identity name is already explained in Step 1. Either drop this pitfall or fold the note into the Step 1 inline explanation.
Prerequisites — strip the install detail. The npm install -g @icp-sdk/icp-cli @icp-sdk/ic-wasm, Node.js >= 22, and demo-icp fallback instructions duplicate what lives in icp-cli. This skill already defers there for everything else — trim to: "icp on $PATH — see the icp-cli skill to install."
Future cross-reference. PR #217 agent-web-identity covers icp identity link web --app <domain> for acting as a user's app-specific principal (oisy.com, NNS, etc.) — a distinct use case from --auth here. Once that lands, add it to ## Related Skills.
|
Skill and evals review — Good skill. Covers genuinely new territory (nothing in I ran the full suite. Three failures in the WITH-skill results, analysed below. Eval results —
|
| Eval | WITH skill | WITHOUT skill |
|---|---|---|
| Deploy a built project to a cloud engine | 6/6 ✅ | 0/6 |
| Just the link command | 3/4 |
1/4 |
| Adversarial: wrong --auth origin | 4/4 ✅ | 1/4 |
| Override: non-default console origin | 4/4 ✅ | 1/4 |
| Adversarial: guessing the subnet id | 3/3 ✅ | 1/3 |
| Agent pitfall: link command stalls non-interactively | 4/4 ✅ | 0/4 |
| Adversarial: deploying as anonymous | 4/4 ✅ | 2/4 |
| Adversarial: dfx to the engine | 3/4 |
0/4 |
| Name the app in the engine console | 6/6 ✅ | 0/6 |
| Adversarial: named app but no Open button | 3/4 |
1/4 |
| Trigger evals | 9/9 should-trigger | 8/8 should-not-trigger |
Total: 40/43 WITH | 8/43 WITHOUT
Required before merge
1. printf '\n' | — the "Press Enter" wording will cause silent failures
Step 1 says "supply the Enter keypress (pipe an empty line)". On icp-cli 0.3.2 (verified in PR #217 agent-web-identity), redirecting stdin from /dev/null produces a bare EOF that does not satisfy the prompt — the command sits on Press Enter to log in indefinitely, no browser opens, and the flow wastes the first sign-in attempt. Piping an actual newline is the only reliable fix:
printf '\n' | icp identity link web <your-identity-name> --auth <console-origin>Update both the Step 1 prose and Pitfall 1 to use this form, and add an explicit note: do NOT redirect from /dev/null.
2. Eval 2 — prompt/expected_behavior mismatch (false failure)
Prompt: "Give me only the command … No deploy steps."
Expected behavior: "Mentions a browser tab opens and the user completes the Internet Identity sign-in there."
These contradict. Asking for only the command and then checking for surrounding context is a design bug — the failure here is in the eval, not the skill. Two options: (a) remove that expected_behavior, or (b) drop the "No deploy steps" scope restriction and reword to "Give me the link command and what to expect when I run it."
3. Pitfall 6 too thin — causing real eval 8 failure (3/4)
The failure in "Adversarial: dfx to the engine": when correcting dfx misuse, the agent produced icp identity link web without <name> and --auth <console-origin>. Pitfall 6 currently reads only "This ecosystem uses icp, never dfx." — not enough to anchor the full command signature under adversarial conditions. Strengthen it to show the complete correction:
6. **Using `dfx`.** This ecosystem uses `icp`, never `dfx`. The correct sequence is:
`icp identity link web <name> --auth <console-origin>` (Step 1), then
`icp deploy -e ic --subnet <subnet-id>` (Step 3).
Suggested improvements (not blocking)
Missing inline icp.yaml example in Step 2. The text says "For a single inline icp.yaml, put the same block under each canister entry instead" but shows no YAML. Since agents use code blocks directly, prose-only guidance is a gap for the common case of single-file projects. Add a snippet:
# icp.yaml
canisters:
frontend:
recipe: ...
settings:
environment_variables:
__META_PROJECT: "My App"
__META_NAME: "Frontend"
__META_MAIN_CANISTER: "true"
backend:
recipe: ...
settings:
environment_variables:
__META_PROJECT: "My App"
__META_NAME: "Backend"Eval 10 — name the command explicitly. The failure was the agent said "redeploy" without naming icp deploy. Change the expected_behavior to check that the agent says icp deploy specifically — it matters that the right command is named.
Pitfall 4 — weak, not a failure mode. "Assuming a fixed identity name" is a clarification about a placeholder value, not a failure path. The identity name is already explained in Step 1. Either drop this pitfall or fold the note into the Step 1 inline explanation.
Prerequisites — strip the install detail. The npm install -g @icp-sdk/icp-cli @icp-sdk/ic-wasm, Node.js >= 22, and demo-icp fallback instructions duplicate what lives in icp-cli. This skill already defers there for everything else — trim to: "icp on $PATH — see the icp-cli skill to install."
Future cross-reference. PR #217 agent-web-identity covers icp identity link web --app <domain> for acting as a user's app-specific principal (oisy.com, NNS, etc.) — a distinct use case from --auth here. Once that lands, add it to ## Related Skills.
…dfx pitfall
Required items from the review:
- Step 1, Pitfall 1, and the stall eval now prescribe
`printf '\n' | icp identity link web ...` and explicitly forbid
`< /dev/null` (bare EOF never satisfies the 'Press Enter' prompt).
- Eval 2: prompt reworded to 'the link command and what to expect' so
the browser-tab expected_behavior no longer contradicts the prompt.
- dfx pitfall now anchors the full correct sequence (link with
--auth, then icp deploy -e ic --subnet).
Suggested items:
- Step 2 gains the inline icp.yaml example. Corrected from the review
snippet: per the v0.3.0 schema, `canisters` is an ARRAY of
{name, recipe, settings} items, not a map keyed by canister name.
- Eval 10 requires naming `icp deploy` explicitly, not 'redeploy'.
- 'Assuming a fixed identity name' pitfall folded into Step 1 prose.
- Prerequisites defer installation to the icp-cli skill.
- PR #217 cross-reference deferred until it lands.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Thanks for the thorough review and for running the suite — all items addressed in 73d87d4. Required
Suggestions
The three WITH-skill failures from your run map to required items 2–3 plus the eval-10 wording, so the suite should be re-run on the new state — checklist updated accordingly. |
marc0olo
left a comment
There was a problem hiding this comment.
All three required fixes and all suggested improvements addressed. Re-ran the four affected evals — every previous failure is now resolved:
| Eval | Before | After |
|---|---|---|
| 2 — Link command and what to expect | 3/4 |
4/4 ✅ |
| 6 — Link command stalls non-interactively | 4/4 (old criterion) | 4/4 ✅ (stricter /dev/null criterion) |
| 8 — Adversarial: dfx to the engine | 3/4 |
4/4 ✅ |
| 10 — Adversarial: named app but no Open button | 3/4 |
4/4 ✅ |
Effective score is now 43/43 across the output suite. Good to merge.
What
Adds
deploy-to-cloud-engine(category Infrastructure): a skill that deploys an already-built ICP project to a user's own cloud engine (an OpenCloud / control-panel engine, administered from a web console). It:icpCLI is installed,icp identity list) and, when no engine identity exists, links the user's console identity withicp identity link web <name> --auth <console-origin>(the user completes the Internet Identity sign-in in the browser),https://opencloud.org(stated to the user and overridable when they sign in to a different console) and obtains the engine's subnet id, asking the user rather than guessing,icp deploy -e ic --subnet <subnet-id>,__META_PROJECT/__META_NAME/__META_MAIN_CANISTERenvironment variables (viasettings.environment_variables) so the engine console shows a single named app with labelled backend/frontend canisters and an "Open" button, instead of bare principal rows, and verifies the canisters on the console.Includes
evaluations/deploy-to-cloud-engine.json(output + trigger evals) covering the documented pitfalls: wrong or omitted--authorigin, the non-interactive "Press Enter" stall, deploying as anonymous, guessing the subnet id, dfx misuse, the console-naming metadata flow (naming an app + the "no Open button" case), and a marketplace-packaging near-miss that must not trigger this skill.Why
The
icp-cliskill covers general builds and mainnet deploys, but nothing covers the cloud-engine-specific path: linking the CLI to the engine's console identity, targeting the engine's own subnet, and tagging the canisters so the engine console shows them as one named app. This is the skill a coding agent links to so it can ship straight to a user's cloud engine — the flow the cloud-engine console currently spells out by hand.Updates since opening
icp default→icp identity default(the former does not exist in icp 0.3.0), and documentation of the "Press Enter to log in" prompt that stallsicp identity link webin non-interactive shells.https://opencloud.org) with an invited override, instead of an open-ended ask; the subnet id remains a hard ask.icp identity list(the CLI cannot reveal which console an identity was linked against), a warning that omitting--authsilently links against its built-in defaulthttps://id.ai, the frontend URL formhttps://<canister-id>.icp0.io, and a compatibility pin toicp-cli >= 0.3.0.__META_PROJECT/__META_NAME/__META_MAIN_CANISTERenvironment variables that group CLI-deployed canisters into one named app (same__META_PROJECTacross canisters), label each one, and mark the entry point (__META_MAIN_CANISTER: "true") for the "Open" button. Verified on the opencloud.org engine: icp-cli merges these with the auto-injectedPUBLIC_CANISTER_ID:*variables, so the asset canister keeps serving. Added matching output evals (naming an app, "no Open button" adversarial) and twoshould_triggerqueries.printf '\n' | icp identity link web …with an explicit do-not-use-/dev/nullnote (Step 1, Pitfall 1, and the stall eval); eval 2's prompt/behavior contradiction fixed ("the link command and what to expect"); the dfx pitfall anchors the full correct sequence; inlineicp.yamlexample added to Step 2 (array form per the v0.3.0 schema —canistersis a list of{name, recipe, settings}); the identity-name pitfall folded into Step 1; prerequisites defer installation toicp-cli.npm run validate—skill-validatorwas not available in my environment (no Go/Homebrew install).node scripts/check-project.js deploy-to-cloud-enginepasses (metadatatitle/categorypresent, eval file found, 0 warnings).node scripts/evaluate-skills.js deploy-to-cloud-engine) after the review fixes and paste results below. (Reviewer's run on the pre-fix state: 40/43 WITH skill vs 8/43 WITHOUT; triggers 17/17.)icp identity link web …andicp deploy -e ic --subnet …against a real engine — done 2026-06-10, see "Updates since opening".__META_*console-naming metadata against a real engine — done 2026-06-11 (canisters merged the vars and rendered as a named app).Evaluation results
Not yet generated.
evaluations/deploy-to-cloud-engine.jsonis included (10 output evals + trigger evals, covering the deploy flow, the documented pitfalls, and the console-naming metadata); results need to be produced withnode scripts/evaluate-skills.js deploy-to-cloud-enginebefore merge.Per CONTRIBUTING, all PRs require repo-admin approval before merge.