Skip to content

Skills gaps causing repeated failures in Motoko blog app generation (follow-up to #35) #37

@marc0olo

Description

@marc0olo

Context

This is a follow-up to #35. That issue documented 15 errors building a Rust + React ICP blog app where Claude Code had skills installed locally but ignored them. This issue documents a new session building a Motoko + Vanilla JS blog app where skills were not installed locally but were fetched via WebFetch from skills.internetcomputer.org — and we still hit 8 errors across 8 deploy attempts.

The skills were fetched proactively from the start (before writing any code), which eliminated several error classes from #35 (wrong package versions, wrong import paths). But new gaps emerged, particularly around Motoko APIs and environment-specific pitfalls.

Session Stats

  • Errors: 8
  • User prompts to fix: 5 error-fix rounds after initial generation
  • Deploy attempts: 8 before working app
  • Skills fetched: 4 (icp-cli, internet-identity, asset-canister, stable-memory) + index.json
  • Estimated tokens: ~300-400k

Errors Encountered

# Error Skill Gap
1 YAML && HTML-encoded by icp-cli in build commands icp-cli skill doesn't warn about this — agent used cd src/frontend && npm install which icp-cli encoded as &&
2 Missing [toolchain] section in mops.toml No skill covers mops toolchain setup
3 moc 0.13.6 too old for core@2.0.0 (requires >= 1.0.0) stable-memory skill pins core = "2.0.0" but doesn't specify compatible moc version
4 mo:core 2.0.0 API hallucinations — List.pushBack, Map.set, Array.thaw/freeze don't exist No Motoko skill exists. Agent hallucinated from older base library training data. Actual API: List.add, Map.add (for upsert), Map.take, Array.toVarArray
5 fetch Illegal Invocation in production bundle internet-identity skill shows HttpAgent.create() without fetch: window.fetch.bind(window)
6 Wrong II canister ID fallback (be2us-64aaa-aaaaa-qaabq-cai) internet-identity skill hardcodes this fallback, but local II is actually at rdmx6-jaaaa-aaaaa-aaadq-cai
7 shouldFetchRootKey cross-origin issue (initial misdiagnosis of #5) Skills don't explain the relationship between ic_env cookie root key and shouldFetchRootKey
8 No admin init flow in UI (CLI identity ≠ browser II identity) Not a skill gap per se, but a common pattern that could be documented

Errors Shared with Issue #35

Two errors appeared in both sessions despite different tech stacks:

  1. fetch Illegal Invocation (Building an ICP Blog App with Claude Code: A Case Study in What Goes Wrong Without Skills #35 error docs: HTTPS outcalls concept page #12, this session error docs: getting-started quickstart page #5) — This is the most impactful recurring issue. The internet-identity skill's HttpAgent.create() example needs fetch: window.fetch.bind(window) added.

  2. Wrong II canister ID (Building an ICP Blog App with Claude Code: A Case Study in What Goes Wrong Without Skills #35 error feat: agent-friendly documentation (llms.txt + markdown endpoints) #14, this session error docs: getting-started project structure page #6) — The hardcoded fallback in the skill is wrong for local development.

Errors Eliminated vs Issue #35

Because skills were fetched upfront, these #35 errors did not occur:

  • Wrong package versions (@icp-sdk/auth@^0.1.0) — skill had correct versions
  • Wrong import paths (@icp-sdk/auth vs @icp-sdk/auth/client) — skill had correct paths
  • Wrong project structure (canister.yaml vs icp.yaml) — skill had correct format
  • Missing workspace Cargo.toml — N/A (Motoko, not Rust)
  • tsc before bindings — N/A (vanilla JS, no TypeScript)

This confirms that skills do prevent errors when used — the remaining errors are gaps in the skills themselves.

Recommended Skill Improvements

1. internet-identity skill — Fix recurring errors

  const agent = await HttpAgent.create({
    identity,
    host: isLocal ? "http://localhost:8000" : "https://icp-api.io",
+   fetch: window.fetch.bind(window),
    ...(isLocal && { shouldFetchRootKey: true, verifyQuerySignatures: false }),
  });
- const iiCanisterId = canisterEnv?.["PUBLIC_CANISTER_ID:internet_identity"]
-   ?? "be2us-64aaa-aaaaa-qaabq-cai";
+ const iiCanisterId = canisterEnv?.["PUBLIC_CANISTER_ID:internet_identity"]
+   ?? "rdmx6-jaaaa-aaaaa-aaadq-cai";

Add a "Common Pitfalls" section:

  • fetch: window.fetch.bind(window) is required in production Vite/webpack bundles
  • CLI identity and browser II identity are different principals — provide UI for admin init
  • Explain ic_env cookie root key vs shouldFetchRootKey (prefer cookie when available)

2. New: motoko skill (or expand stable-memory)

The biggest error source (error #4) was hallucinated Motoko APIs. A Motoko skill should cover:

  • mo:core 2.0.0 API quick reference (at minimum List, Map, Array method names)
  • mops.toml configuration including [toolchain] section with compatible moc version
  • persistent actor pattern (currently in stable-memory but incomplete)
  • Common type patterns ({#less; #equal; #greater} for comparators)

3. icp-cli skill — Build command escaping

Add a warning about special characters in YAML build commands:

# DON'T: && may be HTML-encoded by some tools
build:
  - cd src/frontend && npm install && npm run build

# DO: use a shell script or separate commands
build:
  - sh src/frontend/build.sh

4. stable-memory skill — Pin compatible toolchain

  [package]
  name = "my-project"
  version = "0.1.0"

+ [toolchain]
+ moc = "1.3.0"
+
  [dependencies]
  core = "2.0.0"

Comparison Summary

Metric #35 (Rust, skills installed but ignored) This session (Motoko, skills fetched via WebFetch)
Errors 15 8
Deploy attempts ~8 8
Shared errors fetch binding, II canister ID Same two
Unique errors Wrong versions, imports, structure mo:core API hallucinations, mops toolchain
Root cause Agent didn't use available skills Skills lack Motoko coverage + have wrong defaults

Takeaway

Proactively fetching skills via WebFetch cut errors nearly in half (15 → 8). The remaining errors fall into two categories:

  1. Bugs in existing skills (fetch binding, wrong II canister ID) — easily fixable, high impact since they affect every session
  2. Missing skill coverage (Motoko APIs, mops toolchain) — requires a new motoko skill

The llms.txtindex.json → on-demand skill fetch pattern discussed in #35 comments works. The skills themselves just need these gaps filled.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions