
Canhelp
- 120 installs
- 28 repo stars
- Updated August 4, 2026
- dfinity/icskills
Fetch and summarize a mainnet IC canister's Candid interface from its canister ID or human-readable name.
About
Given a mainnet canister ID or name, fetches its Candid interface and prints a human-readable summary of its query methods, update methods, and types. A developer uses it to inspect what a mainnet IC canister exposes, like --help for canisters.
- Resolves a mainnet canister ID or name and fetches its Candid interface
- Prints a grouped, readable summary of query/update methods and types
Canhelp by the numbers
- 120 all-time installs (skills.sh)
- Ranked #157 of 479 Web3 & Blockchain skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/dfinity/icskills --skill canhelpAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 120 |
|---|---|
| repo stars | ★ 28 |
| Last updated | August 4, 2026 |
| Repository | dfinity/icskills ↗ |
What it does
Fetch and summarize a mainnet IC canister's Candid interface from its canister ID or human-readable name.
Files
Given a canister ID or name in $ARGUMENTS, fetch and summarize its Candid interface.
Steps
1. Resolve the canister ID by running the resolve script from the skill's base directory:
./scripts/resolve-canister-id.sh "$ARGUMENTS"If $ARGUMENTS is already a valid principal, the script echoes it back. Otherwise, it queries the IC Dashboard API and outputs matches as <canister-id> <name> (one per line).
- If there is a single result, clearly display the resolved canister ID and use it directly.
- If there are multiple results, present the list to the user and ask them to pick one before continuing.
2. Fetch the Candid interface using the resolved canister ID:
./scripts/fetch-candid.sh <resolved-canister-id>The script outputs the path to the downloaded .did file.
3. Read the file using the Read tool.
4. Present the output as a readable summary with the following structure:
Canister `<canister-id>`
Query methods:
method_name(arg1: type1, arg2: type2) → return_type— one-line description if inferable from the name
Update methods:
method_name(arg1: type1) → return_type
Types:
- List any custom record/variant types defined in the interface, with their fields
Guidelines
- Group methods by query vs update
- Sort methods alphabetically within each group
- For complex nested types, show the top-level structure and note nesting
- If the candid is very large (>100 methods), show a summary count and list only the most important-looking methods, offering to show the full list on request
- If the fetch succeeds, but the Candid interface is empty,explain that the canister is not exposing its Candid interface in the wasm metadata
- If the fetch fails, suggest the user verify the canister ID and that
icpis installed
#!/bin/bash
set -euo pipefail
if ! command -v icp &>/dev/null; then
echo "Error: 'icp' CLI not found. Install it from https://dfinity.github.io/icp-cli" >&2
exit 1
fi
CANISTER_ID="${1:?Usage: fetch-candid.sh <canister-id>}"
OUT="/tmp/candid_${CANISTER_ID}.did"
icp canister metadata "$CANISTER_ID" candid:service --network ic > "$OUT"
echo "$OUT"
#!/bin/bash
set -euo pipefail
INPUT="${1:?Usage: resolve-canister-id.sh <canister-id-or-name>}"
# Principal: Base32(CRC32 · blob) grouped into 5-char chunks separated by dashes.
# Each group is exactly 5 lowercase alphanumeric chars, except the last which is 1-5.
# Max 63 chars (29-byte blob → 53 base32 chars + 10 dashes). Must have at least 2 groups.
if [[ "$INPUT" =~ ^[a-z2-7]{5}(-[a-z2-7]{5})*(-[a-z2-7]{1,5})$ ]]; then
echo "$INPUT"
exit 0
fi
# Otherwise, query IC Dashboard API for name-based lookup
QUERY=$(python3 -c "import urllib.parse, sys; print(urllib.parse.quote(sys.argv[1]))" "$INPUT")
RESPONSE=$(curl -sf "https://ic-api.internetcomputer.org/api/v4/canisters?format=json&has_name=true&query=${QUERY}&limit=50")
python3 -c "
import sys, json
data = json.load(sys.stdin)
entries = data.get('data', [])
if not entries:
print('Error: no canister found matching \"$INPUT\"', file=sys.stderr)
sys.exit(1)
for e in entries:
print(f\"{e['canister_id']} {e.get('name', 'N/A')}\")
" <<< "$RESPONSE"