From math-coach
Drives iris-cli to search, browse, ask AI questions about, and export Iris architecture repositories modeling systems as graphs of collections→sets→packages→elements→diagrams. Activates on Iris/systems mentions or artefact references.
npx claudepluginhub cgbarlow/skills --plugin math-coachThis skill uses the workspace's default tool permissions.
This skill drives [`iris-cli`](https://github.com/cgbarlow/iris/tree/main/cli),
Interactively co-builds C4 model architecture diagrams (Context, Container, Component, Code) via dialogue. Supports greenfield design, retro-documenting code/prose, review, and updates. Outputs Mermaid C4 + Markdown by default.
Evaluates software architectures, suggests patterns, and generates diagrams for system design. Useful for refactoring, scalability planning, or new project blueprints.
Generates code intelligence layers: Skeleton Index (<4s zero-dep), AST knowledge graph (CodeGraph), Mermaid architecture diagrams, smart context builder for AI agents to query codebases instantly.
Share bugs, ideas, or general feedback.
This skill drives iris-cli,
the Python command-line client for an Iris architecture-knowledge
repository. Iris models systems as a graph of collections → sets →
packages → elements → diagrams. The CLI exposes read-only browse,
search, AI Q&A, and export operations against any Iris backend over
HTTP.
When the user mentions iris in this context, prefer the CLI over inventing your own HTTP calls — the CLI handles auth, rate-limit buckets, output formatting, and the SQLite-vs-Supabase deployment- mode split for you.
If mcp__*__Iris__* tools are loaded in the current session, ALWAYS
use those — never the CLI. The MCP tools are typed, validated, run
server-side, work in every Claude surface (Cowork, Desktop chat,
claude.ai web), and don't need a shell. The CLI exists for environments
where there's a real local shell and no MCP is configured — namely
Claude Code in a terminal or in Desktop "Code" mode.
| Environment | Best path |
|---|---|
| Claude Code CLI / Desktop "Code" tab | iris-cli (this skill, full body below) |
| Cowork — Desktop or web | mcp__claude_ai_Iris__* tools (don't read further; pick the right MCP tool for the user's intent) |
| Standard Claude Desktop chat / claude.ai web | mcp__claude_ai_Iris__* tools |
The iris-cli sandbox in Cowork is ephemeral, slow to boot, sometimes fails outright, and doesn't have iris-cli pre-installed. The MCP sidesteps every one of those failure modes.
If MCP isn't available, this skill is the right answer when the user:
iris … command verbatim — even when MCP is loaded the
user has explicitly asked for the CLI; respect that.iris-cli is a Python tool installed via uv. The user might already
have it (which iris); if not:
uv tool install --from "git+https://github.com/cgbarlow/iris#subdirectory=cli" iris-cli
If the user doesn't have uv itself, suggest the official installer
(curl -LsSf https://astral.sh/uv/install.sh | sh) — but check
uv --version first to avoid re-installing.
On the first uv tool install ever performed on a machine, uv warns
that ~/.local/bin isn't on PATH. Run this once so every
future uv-installed tool resolves automatically:
uv tool update-shell
exec $SHELL -l # reload shell so the new PATH takes effect
iris login --url <URL> requires the iris-api backend service —
the host that serves /api/*. It is not:
https://iris-uat.chrisbarlow.nz),
which serves the SPA shell at every path and would 404 every API
call from the CLI.https://iris-mcp.onrender.com), which
speaks MCP, not REST.Known backends:
https://iris-api-gtb3.onrender.comhttp://localhost:8000 (the default)iris-api Render / Docker /
uvicorn service is on.If unsure, ask the user, or check the frontend's VITE_API_BASE_URL
env var — that's the backend host the SPA points at.
The right path depends on which mode the backend runs in. If you don't know, try (a) first; on a 404 with "Supabase deployment mode" in the detail, switch to (b).
(a) SQLite-mode backend (local dev, single-tenant self-host) —
interactive username + password, mints a PAT, saves to
~/.config/iris/config.toml:
iris login --url https://iris-api.example.com
# Prompts for username + password.
# Result: { url, token = "iris_pat_…" } stored at
# $XDG_CONFIG_HOME/iris/config.toml (mode 0600).
(b) Supabase-mode backend (UAT, multi-tenant prod) — the
backend's /api/auth/login is intentionally disabled (auth flows
through Supabase Auth, not the iris backend). Mint a PAT externally
and hand it to the CLI with --token:
# 1. Sign in via the frontend (e.g. https://iris-uat.chrisbarlow.nz).
# In browser DevTools → Application → Local Storage, find the
# sb-<project-ref>-auth-token entry and copy the access_token field.
SUPABASE_JWT='eyJhbGciOi…'
# 2. Mint a PAT with that JWT:
PAT=$(curl -sX POST https://iris-api-gtb3.onrender.com/api/users/me/tokens \
-H "Authorization: Bearer $SUPABASE_JWT" \
-H "Content-Type: application/json" \
-d '{"name":"iris-cli"}' \
| python3 -c 'import json,sys; print(json.load(sys.stdin)["token"])')
# 3. Persist it via iris login (no API call — just writes the config):
iris login --url https://iris-api-gtb3.onrender.com --token "$PAT"
The PAT is shown exactly once at mint time. If the user loses it, mint a new one — they're cheap to revoke and recreate.
Login is optional. With no PAT configured, the CLI runs against the
backend's anonymous rate-limit buckets (anon / anon_ai) and can
do read-only browse, search, AI ask, and export — same scope an
unauthenticated browser visitor has. Useful for quick exploration; for
sustained work, log in so the user gets the more generous pat
bucket and any role-gated content.
Every command resolves --url and --token in this order:
--url, --token).IRIS_URL, IRIS_TOKEN).$XDG_CONFIG_HOME/iris/config.toml (defaults to ~/.config/...).http://localhost:8000, no token).So once the user has run iris login once, every subsequent command
just works without flags.
Use this table to pick the command. Append --json to anything in
the Read group when you need to chain output through jq or feed
it into another tool.
| Intent | Command |
|---|---|
| Search across the whole repository | iris search "query" |
| Search inside a specific set | iris search "q" --set <set-id> |
| List diagrams (paginated) | iris diagrams list [--set <id>] [--limit N] |
| Inspect one diagram | iris diagrams get <diagram-id> |
| Diagram revision history | iris diagrams versions <diagram-id> |
| List elements / get one | iris elements list [--set <id>] / iris elements get <id> |
| List packages / get one | iris packages list [--set <id>] / iris packages get <id> |
| List sets / get one | iris sets list [--collection <id>] / iris sets get <id> |
| List collections / get one | iris collections list / iris collections get <id> |
| Export an artefact | iris export {diagram|element|package|set|collection} <id> --format {json|markdown} [-o PATH] |
| Ask iris's AI a question | iris ask "question" --set <id> [--stream] [--mode discuss|creation] |
| Show conversation history | iris conversations list --set <id> |
| Show the authenticated user | iris whoami |
Notes:
--stream on iris ask prints SSE chunks as they arrive — best
for the user watching live; turn it off with --no-stream for
scripting.iris ask --set can be passed multiple times to ground the
question in several sets at once (multi-set Q&A).iris export … -o - writes to stdout instead of a file.iris export set <id> --format markdown -o docs/platform.md.Example 1: find what owns customer PII
iris ask "Which services in the default set own customer PII?" \
--set default --stream
Streams the answer as it's generated. Drop --stream to wait for
the complete answer.
Example 2: pipe search hits into jq
iris search payment --json | jq '.results[].name'
Lists the names of every search match. The --json flag is the
right reach whenever Claude needs to act on iris output
programmatically (vs. show it to the user).
Example 3: snapshot a set into a wiki
iris export set 7d4f8c9b-2e1a-4f3b-9a8c-1234567890ab \
--format markdown -o docs/platform-architecture.md
Produces a deterministic Markdown bundle of every package, diagram, and element in the set. Commit it to a wiki repo and re-run the command on each iris-side change.
Example 4: who am I?
iris whoami
Returns the user the current PAT belongs to. Useful for verifying a freshly-pasted token before running a longer pipeline.
Every command returns one of:
| Code | Meaning | What to do |
|---|---|---|
0 | Success | Continue. |
1 | Backend HTTP 4xx / 5xx (not auth) | Read the printed detail; surface to the user. Often "not found" or a malformed argument. |
2 | Network / connection error | Backend probably down or unreachable. Check the URL; if on Render's free tier, suspect cold start (60-s spin-up after idle) and retry once. |
3 | 401 / 403 — auth | Token missing, invalid, expired, or the user lacks permission. The CLI prints a hint to re-run iris login. |
When chaining commands, check $? after each step rather than
assuming success.
The single thing most likely to trip up a first-time iris-cli user
on a UAT / production deployment is hitting iris login --url ...
without --token and seeing:
Error: This backend runs in Supabase deployment mode — /api/auth/login
is disabled. Mint a PAT externally (via the frontend or curl
+ a Supabase JWT) and re-run:
iris login --url <URL> --token iris_pat_…
This is the error that means: jump to §2 → Login (b). The
/api/auth/login username+password endpoint is intentionally absent
in Supabase mode because Supabase Auth handles credentials. Mint the
PAT via the curl recipe and re-run with --token.
The CLI covers the read-only + AI surface area. If the user wants to
write to iris (create a diagram, modify an element, etc.), the
CLI doesn't expose those operations — they run through the iris HTTP
API directly with the same PAT in Authorization: Bearer …. Pull up
docs/api.md
and the OpenAPI schema at <backend>/api/docs for the full surface.