MCP Server Builder
anthropics/skills
Guides the design and implementation of Model Context Protocol servers in TypeScript or Python, from tool naming and error messages to evaluation.
A skill your agent uses for CLI and shell work through rote: running local commands with rote exec, capturing stdout/stderr/files, following logs and background processes, checking dependency…
$ npx skills add modiqo/skillspec --skill rote-shell -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install modiqo/skillspec rote-shell --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/modiqo/skillspec.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/rote-shell/source .claude/skills/rote-shell && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "rote-shell" agent skill from https://github.com/modiqo/skillspec/tree/main/.claude/skills/rote-shell/source into .claude/skills/rote-shell/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "rote-shell", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/modiqo/skillspec/tree/main/.claude/skills/rote-shell/sourceType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add modiqo/skillspec --skill rote-shell -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install modiqo/skillspec rote-shell --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/modiqo/skillspec.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.claude/skills/rote-shell/source .agents/skills/rote-shell && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "rote-shell" agent skill from https://github.com/modiqo/skillspec/tree/main/.claude/skills/rote-shell/source into .agents/skills/rote-shell/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "rote-shell", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add modiqo/skillspec --skill rote-shell -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install modiqo/skillspec rote-shell --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/modiqo/skillspec.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.claude/skills/rote-shell/source .cursor/skills/rote-shell && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "rote-shell" agent skill from https://github.com/modiqo/skillspec/tree/main/.claude/skills/rote-shell/source into .cursor/skills/rote-shell/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "rote-shell", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/modiqo/skillspec.git --path .claude/skills/rote-shell/source--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add modiqo/skillspec --skill rote-shell -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install modiqo/skillspec rote-shell --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/modiqo/skillspec.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.claude/skills/rote-shell/source .gemini/skills/rote-shell && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "rote-shell" agent skill from https://github.com/modiqo/skillspec/tree/main/.claude/skills/rote-shell/source into .gemini/skills/rote-shell/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "rote-shell", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install modiqo/skillspec rote-shellInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add modiqo/skillspec --skill rote-shell -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/modiqo/skillspec.git skills-src && mkdir -p .github/skills && cp -r skills-src/.claude/skills/rote-shell/source .github/skills/rote-shell && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "rote-shell" agent skill from https://github.com/modiqo/skillspec/tree/main/.claude/skills/rote-shell/source into .github/skills/rote-shell/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "rote-shell", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add modiqo/skillspec --skill rote-shell -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install modiqo/skillspec rote-shell --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/modiqo/skillspec.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.claude/skills/rote-shell/source .opencode/skills/rote-shell && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "rote-shell" agent skill from https://github.com/modiqo/skillspec/tree/main/.claude/skills/rote-shell/source into .opencode/skills/rote-shell/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "rote-shell", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
rote-shellA skill your agent uses for CLI and shell work through rote: running local commands with rote exec, capturing stdout/stderr/files, following logs and background processes, checking dependency…
Rote Shell is an agent skill from modiqo/skillspec. Use for CLI and shell work through rote: running local commands with rote exec, capturing stdout/stderr/files, following logs and background processes, checking dependency manifests, mixing adapters/browser/process steps, and crystallizing CLI work into TypeScript flows. Prefer rote shell primitives over raw shell when the command result should be remembered, queried, replayed, or shared.
Its SKILL.md is about 7.2k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It works with TypeScript. The repository describes itself as: SkillSpec makes agent skills followable, testable, and provable with Doctor risk reports, guided imports, structured contracts, and alignment proof. The licence is Apache-2.0.
6 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit f4d9ab5. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
cargonpmghFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md. Its commands use npm and gh, which can reach the network depending on how they are called.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Rote Shell loads about 7.2k tokens when it runs. Until then it costs about 101 tokens; SKILL.md has 3,129 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from modiqo/skillspec at commit f4d9ab5, republished under its Apache-2.0 licence (© modiqo). 3,129 words, ~7,185 tokens.
.claude/skills/rote-shell/SKILL.md (or your agent's skills folder).Use rote for shell and CLI work when the result should become workspace memory: commands, outputs, files, logs, process lifecycle, dependencies, and flow replay. Raw shell is still fine for tiny inspection commands, but work that matters should pass through rote so it can be queried, audited, and crystallized.
Load the shell guidance when you need the complete command model:
rote guidance shell essentialChoose the narrowest rote primitive that preserves evidence:
rote exec -- <program> [args...]rote exec --stdin-file input.txt -- <program>rote exec --capture-file label:path -- <program>rote stream follow --file logs/server.log --until READYrote exec --background --ready-log READY -- <program>rote stream follow-process proc-1 --stream stdout --until READYrote pty run -- <program> [args...]rote deps check deps.tomlrote deno run --allow-all ~/.rote/flows/<name>/main.tsDo not replace these with ad hoc command > file, tail -f, or ps | grep
when the evidence should be durable. Rote already stores typed responses,
artifacts, hashes, offsets, process leases, and command-log provenance.
If the user says "browse", "open this site", "attach to my browser", "use the
page", "click", "type", "snapshot", "extract from the page", "extract social
profiles", "Gmail in browser", or otherwise asks for live web UI state, stop
shell routing and invoke /rote-browse.
Do not satisfy browser intent with rote exec, raw Playwright, native web
search, WebFetch, open, curl, or a saved non-browser flow unless the user
explicitly switches substrate. Native search may help discover a URL only when
the user asked for search/discovery or the browser route cannot identify a URL;
it is not a substitute for browsing and extracting the page with rote.
Browse intent has precedence over the domain noun. For example, "browse my
calendar", "browse Gmail", "browse HubSpot", or "browse Salesforce" means the
user wants browser-state access even though those domains may also have APIs.
You may still run rote flow search "<intent>" first, but only use an
adapter/flow if it is installed, healthy, and completes the request. If the
adapter/flow is missing, stale, unauthenticated, or fails setup, do not ask the
user to build an adapter before trying the browser route. Hand off to
/rote-browse and use an existing headed browser when the task depends on the
user's logged-in profile.
For public profile extraction, such as "browse each committer's social
profile", use GitHub/CLI/API data to collect candidate URLs and identities,
then use /rote-browse to visit and extract the public pages. Do not replace
that browse step with native web search summaries.
Default browser decision:
For active browser attach, hand off to /rote-browse and use its sequence:
rote browser attach setup --method extension --browser chrome
rote browse <url> --headed --attach-existing --new-tab --no-prompt --no-snapshot
rote browse wait --selector '<ready-selector>' --timeout 30 --quiet-ms 750
rote browse snapshotFor browser plus shell work, keep both in the same workspace. Use
/rote-browse for page leases, snapshots, slices, refs, auth state, and
readiness. Use /rote-shell only after browser state has been materialized as
a saved response, snapshot, slice, or file that a local CLI should process.
Use only shipped commands. Do not invent aliases from the roadmap.
| Need | Shipped command | Notes |
|---|---|---|
| One-shot process capture | rote exec -- <program> [args...] | Direct argv by default. |
| File stdin | rote exec --stdin-file input.txt -- <program> | Records stdin provenance. |
| Declared output file | rote exec --capture-file label:path -- <program> | Captures file metadata and artifact pointer. |
| Saved stdout/stderr files | rote exec --stdout-file out.txt --stderr-file err.txt -- <program> | Use for durable stream files. |
| Dependency preflight | rote deps check deps.toml | No install side effects. |
| Moving file/log stream | rote stream follow --file app.log --until READY | Supports offsets, chunks, hashes, and pattern stop. |
| Background start | rote exec --background --ready-log READY -- <program> | Creates a tracked lease such as proc-1. |
| Background status | rote exec status proc-1 | Query lease state before acting. |
| Background wait | rote exec wait proc-1 --timeout-ms 300000 --poll-ms 500 | Blocks until a tracked finite job exits or times out; records exit plus stdout/stderr observations. |
| Background stdout/stderr follow | rote stream follow-process proc-1 --stream stdout --until READY | Reads from background log artifacts. |
| Background stop and cleanup | rote exec stop proc-1 | On Unix, stops the process group and records cleanup facts. |
| One-shot terminal transcript | rote pty run -- <program> [args...] | Use when the command must see a terminal. |
Deferred or not shipped as commands yet:
rote exec attachrote exec logdetachIf a task needs a deferred feature, say so and use the nearest shipped primitive
instead. For example, use rote exec wait for finite tracked jobs, use
rote stream follow-process ... --until <pattern> for log observation or
readiness, and use rote exec status plus rote exec stop instead of raw
ps/kill when the process is tracked.
For authored TypeScript flows, use first-class SDK wrappers instead of hand-assembling command arrays. The SDK surface mirrors the shipped shell patterns:
| Pattern | SDK call |
|---|---|
| Durable one-shot | await rote.exec({ argv: ["git", "status", "--short"], deps: ["git"] }) |
| Declared stdin/output files | await rote.exec({ argv, stdin: { file }, capture: { stdout: { file }, files: [{ label, path }] } }) |
| Dependency preflight | await rote.depsCheck({ manifest: "deps.toml" }) |
| Tracked background job / detach-like work | await rote.execBackground({ argv, readyLog, readyTimeoutMs, capture }) |
| Long-running job with useful parallel work | await rote.execBackgroundAndJoin(request, async (job) => { ... }, { timeoutMs, pollMs, stopOnWorkError }) |
| Lease status | await rote.execStatus("proc-1") |
| Lease wait | await rote.execWait("proc-1", { timeoutMs: 300_000, pollMs: 500 }) or await job.wait(...) |
| Lease cleanup | await rote.execStop("proc-1") |
| Moving file stream | await rote.followFile("logs/app.log", { until: "READY" }) |
| Background process stream | await rote.followProcess("proc-1", "stdout", { until: "READY" }) |
| One-shot PTY transcript | await rote.ptyRun({ argv, cols: 100, rows: 30 }) |
| Authored ordered fan-out | await rote.execMany(requests, { stopOnError: false }) |
Use rote.shell().<method> when you want the shell namespace explicitly; the
top-level rote.<method> forms are convenience aliases for authored flows.
Do not invent SDK methods for deferred roadmap items. There is no
rote.detach, persistent PTY send, or direct OS-pipe stream handle yet. The
current detach-like pattern is a tracked background lease with stdout/stderr
files, execWait, followProcess, execStatus, and execStop.
rote.execMany preserves workspace response ordering by running process
requests serially. For true parallel shell fan-out, generate declarative
frontmatter steps: with type: process.exec, for_each, and
max_concurrency so the DAG runner owns the scheduling and provenance.
For long-running finite jobs in authored TypeScript, prefer
execBackgroundAndJoin or job.join when there is useful adapter, browser,
process, file, or explicit stream work to do while the lease runs. The callback
creates normal semantic DAG evidence; the final exec wait is the join point.
Do not generate heartbeat or polling loops as DAG work.
rote.execBackground(...) already prints the lease and poll commands to
stderr. Do not duplicate that announcement in crystallized flows. Use
announce: false only for deliberately quiet flows.
When the user asks to turn shell exploration into a reusable flow, choose the flow shape from the work pattern:
| Exploration pattern | Crystallized shape |
|---|---|
| One finite command whose output is the fact | rote.exec({ argv, deps, capture }) |
| Command writes files that downstream work reads | rote.exec({ capture: { files: [...] } }) plus typed file paths |
| Existing file or log is the source of truth | rote.followFile(path, options) |
| Long finite job where other useful work can run | rote.execBackgroundAndJoin(request, async (job) => { ... }, options) |
| Long service or daemon with readiness | rote.execBackground({ readyLog, capture }), then status/follow/stop |
| Need to inspect progress from a tracked lease | job.follow(...) or rote.followProcess(...) |
| Need completion proof from a tracked lease | job.wait(...) or rote.execWait(...) |
| Terminal behavior is the point | rote.ptyRun({ argv, input, cols, rows }) |
| Many independent commands share one shape | declarative steps: with process.exec, for_each, and max_concurrency |
Crystallize causality, not waiting. Do not encode heartbeat loops, repeated status polling, or sleep/retry scaffolding as business DAG nodes. Those are observation mechanics. The reusable flow should expose semantic actions and joins: start work, observe meaningful artifacts or streams, wait for completion, then summarize.
Before authoring a TypeScript shell flow, read:
rote guidance typescript flow-creationThat guide owns frontmatter, deps.toml, FlowOutput, release QA, and the shell
SDK wrapper contract.
Map the user's vague request to the smallest shipped pattern that preserves evidence:
| Signal | Pattern | Use |
|---|---|---|
| Tiny disposable inspection | Raw shell allowed | direct harness shell |
| Result may be queried, compared, summarized, or replayed | Durable one-shot | rote exec -- |
| Command reads a known file | Declared file input | rote exec --stdin-file or a direct argv path |
| Command creates a file that matters | Declared file output | rote exec --capture-file |
| Full stdout/stderr matters | Durable stream files | --stdout-file, --stderr-file |
| Required tools or input files matter | Dependency gate | deps.toml plus rote deps check |
| Existing log is moving | File stream watch | rote stream follow --file |
| Start a server or daemon-like process | Service lease | rote exec --background --ready-log |
| Long finite non-interactive job | Tracked background job | rote exec --background --stdout-file --stderr-file |
| Inspect background output | Process stream observation | rote stream follow-process |
| Need liveness before acting | Lease status | rote exec status |
| Need cleanup | Lease cleanup | rote exec stop |
| Many independent items share a command shape | Fan-out batch | steps: with process.exec, for_each, and max_concurrency |
| API result feeds CLI or CLI result feeds API | Mixed substrate chain | adapter/browser primitive plus rote exec |
| Browser snapshot/file feeds local CLI | Browser-file bridge | browser snapshot/file plus rote exec |
| Release, publish, deploy, or global mutation | Guarded mutation | deps check, tool-native dry-run, approval, then foreground unless background is approved |
| Command checks whether stdout is a terminal | One-shot PTY transcript | rote pty run -- |
| Command may prompt interactively and can be scripted safely | One-shot PTY with bounded input | rote pty run --input or --stdin-file |
| Command needs ongoing human interaction | Foreground or defer | persistent PTY attach is not shipped |
--dry-run, --resume, --force-resume, and --max-concurrency are DAG
runner controls for frontmatter steps: flows. They are not universal
rote exec flags. For a single command, use the tool's own dry-run/check mode
when available.
CLI work must happen inside a rote workspace:
rote init cli-work --seq --force
rote workspace sandbox cli-work off
cd ~/.rote/rote/workspaces/cli-workKeep commands simple and literal. Avoid shell control operators, command
substitution, and long && chains unless the user explicitly needs shell
semantics. Prefer direct argv:
rote exec -- rg TODO docsUse shell parsing only when it is the real subject of the work:
rote exec -- sh -c 'printf "alpha\n" | tr a-z A-Z'Treat every @N as the handle for what just happened. The handle is saved
evidence, not always the raw business payload. Route by type.
After a command finishes, read @@result first:
response_id is the saved evidence handleresponse_kind tells you how to query the evidenceprimary_query, primary_stdout_query, primary_stderr_query, or
artifact_query are exact typed queries for the saved response@@next remains the immediate next-action guideFor one-shot process output, prefer the typed query fields from @@result:
rote query @1 '.stdout.text' -r
rote query @1 '.stderr.text' -r
rote query @1 '.status.exit' -r
rote query @1 '.files' -r
rote query @2 '.cleanup' -rUse @proc addresses when inspecting process responses:
rote query @proc.last.stdout '.text' -r
rote query @proc.1.exit '.' -r
rote query @proc.last.transcript '.text' -rWhen @@result gives an exact query such as
rote query @proc.4.transcript '.text' -r, prefer it over @proc.last if any
other command may run before you query. Use rote @N . for full provenance
inspection, not as a shortcut for stdout or PTY transcript text.
Do not summarize from terminal scrollback when a structured query exists.
Declare file inputs and outputs instead of relying on memory:
rote exec \
--stdin-file input.txt \
--capture-file summary:out/summary.txt \
-- python3 scripts/summarize.pyThis records stdin provenance, file change state, media type, hashes when
available, and artifact paths under .rote/artifacts/processes/@N/.
Start servers as leases, not mystery PIDs:
rote exec --background --ready-log "Listening" --ready-timeout-ms 10000 -- npm run dev
rote exec status proc-1
rote stream follow-process proc-1 --stream stdout --until "GET /health"
rote exec stop proc-1
rote query @3 '.cleanup' -rOn Unix, rote starts background commands in a process group and stops the group
with TERM followed by KILL if needed. Inspect .cleanup before claiming a
process stopped.
For long-running but finite commands, use a tracked background lease instead of
an untracked detach. rote exec detach is not shipped yet. The current
detached-like primitive is:
rote exec \
--background \
--stdout-file logs/job.stdout.log \
--stderr-file logs/job.stderr.log \
-- cargo test --all-targets --all-features
rote exec status proc-1
rote exec wait proc-1 --timeout-ms 600000 --poll-ms 1000
rote stream follow-process proc-1 --stream stdout --from-start --max-bytes 65536
rote stream follow-process proc-1 --stream stderr --from-start --max-bytes 65536Use this when the command is non-interactive, can safely continue while the
agent does other work, and its stdout/stderr are enough to monitor progress.
Use exec wait to establish completion and exit status. Use
follow-process to inspect output, not as the primary completion detector.
Keep the lease id (proc-1) in the task notes and query status before making
claims about completion if wait has not finished.
In authored TypeScript, prefer the semantic join helper:
const joined = await rote.execBackgroundAndJoin(
{ argv: ["cargo", "test"], deps: ["cargo"] },
async (job) => {
const checks = await rote.exec({ argv: ["gh", "pr", "checks"], deps: ["gh"] });
const stderr = await job.follow("stderr", { fromStart: true, maxBytes: 65536 });
return { checks, stderr };
},
{ timeoutMs: 600_000, pollMs: 1_000, stopOnWorkError: true },
);The callback's work becomes semantic DAG evidence. The wait remains the completion join. Poll/heartbeat internals do not become graph nodes.
Do not background a command when it may prompt for credentials, OTP, passphrase,
license acceptance, or confirmation. rote pty run can capture a bounded
one-shot terminal transcript, but it does not provide persistent attach. Ongoing
interactive jobs should run foreground or be postponed until the user can drive
the prompt.
Use PTY only when terminal behavior is the point: commands that check
isatty, render progress differently on terminals, or can be driven with
bounded scripted input.
rote pty run --cols 100 --rows 30 -- script-that-checks-tty
rote pty run --input "yes\n" -- interactive-but-scriptable-command
rote query @proc.last.transcript '.text' -rDo not pass secrets through --input; terminal echo may record them in the
transcript. Do not use PTY for persistent REPLs or long human-driven sessions
until start/send/snapshot/stop support exists.
Treat release and publish commands as high risk. For examples like
cargo release, npm publish, gh release create, or deploy commands:
draft until completion evidence is
captured.Decision rule:
rote execrote exec --backgroundrote exec --background --ready-log ...When a task depends on local tools, create or update
~/.rote/flows/<name>/deps.toml before replay. This is not optional for
crystallized shell flows: if the flow calls rote.exec({ argv }) for git,
gh, cargo, python, node, jq, rg, or any other local executable, the
flow directory must include a matching dependency manifest before the flow is
marked released.
schema_version = 1
[[tools]]
id = "github-cli"
command = "gh"
required = true
version_command = ["gh", "--version"]
[files]
required = ["input.txt"]Then run:
cd ~/.rote/flows/<name>
rote deps check deps.tomlDo not auto-install tools into global locations unless the user approved that specific provisioning policy. A crystallized flow should declare dependencies so the target environment can check or provision them before work begins.
If rote deps check deps.toml reports missing required tools, stop and elicit
an install decision from the user before continuing. Show the missing tool,
why the flow needs it, and the lowest-risk install scope available. Prefer
project-local or rote-managed installs over global package manager installs.
Only install globally when the user explicitly approves that scope.
Use this shape:
The flow needs these missing tools before replay:
- gh: required for GitHub PR and Actions checks
I can install/provision them using one of these scopes:
- rote-managed/project-local: preferred when available; keeps replay isolated
- user/global package manager: broader machine mutation; requires explicit approval
Do you want me to install/provision the missing tools, or should I leave the
flow in draft until you install them?After any approved install or user-managed install, rerun:
cd ~/.rote/flows/<name>
rote deps check deps.tomlNever mark the flow released while required dependencies are still missing.
For API plus CLI work, use the adapter for typed API calls and rote exec for
local CLI facts. Example shape:
rote POST /github '{"method":"GET","path":"/repos/$owner/$repo"}' -t -s
rote exec -- gh repo view "$owner/$repo" --json name,visibility
rote query @1 '.' -r
rote query @2 '.stdout.text' -rFor browser plus CLI work, use rote-browse for page state and rote-shell
for local processing of snapshots/artifacts. Do not drop into raw Playwright or
raw shell when a rote primitive can preserve the evidence.
Current mixed replay support is intentionally asymmetric:
process.exec actions are first-class steps: DAG actionsFor browser-involved crystallization today, capture the browser state with
rote-browse, materialize the snapshot or slice to a file, then consume that
file from process.exec.
After a useful CLI workflow works twice, ask whether to crystallize it. The canonical replay command for TypeScript flows is:
rote deno run --allow-all ~/.rote/flows/<name>/main.tsUse rote flow run only as compatibility syntax. New generated usage should
prefer rote deno run --allow-all.
When the user says yes, do the full release discipline:
Choose the correct scaffold path:
~/.rote/flows/<name>/main.ts manually with
@rote-frontmatter. Do not run rote flow pending save,
rote flow template create, or rote flow frontmatter; those commands
require --adapter in the current implementation and will fail or emit an
adapter-shaped flow.rote flow frontmatter or
rote flow template create so adapter fingerprints and parameters are
captured. Then choose one execution shape:steps: when the replay can be expressed
as adapter calls plus type: process.exec actions.FlowOutput, runPreflight(...),
and SDK calls such as rote.exec({ argv }) when custom branching,
formatting, help text, or richer TypeScript logic is needed.Minimal shell-only frontmatter shape:
/**
* CSV Sales Report
*
* Summarizes a local CSV into JSON and a text report.
*
* @rote-frontmatter
* ---
* name: csv-sales-report
* description: "Summarizes a local CSV into JSON and a text report using rote shell primitives."
* provenance:
* tier: local
* workspace: csv-json-report-demo
* metadata:
* status: draft
* kind: atomic
* flow_type: sequential
* format: typescript
* requires_endpoints: []
* requires_sessions: false
* parameters:
* - name: input
* type: string
* required: true
* description: "Input CSV path"
* - name: out_dir
* type: string
* required: false
* default: "out"
* description: "Output directory"
* tags:
* - shell
* - process
* - typescript
* ---
*/Create ~/.rote/flows/<name>/main.ts.
For declarative DAG flows, put the replay graph in frontmatter steps:.
For authored SDK flows, use TypeScript SDK shell primitives for process
work: rote.exec, rote.execBackground, rote.execStatus,
rote.execStop, rote.followFile, rote.followProcess, rote.ptyRun,
rote.depsCheck, and rote.execMany. Use adapter handles from
runPreflight(...) for adapter work.
Create ~/.rote/flows/<name>/deps.toml for every local tool or required
input file. For shell-only flows, prefer a real deps.toml file over
frontmatter-only dependency prose so replay can run rote deps check.
Keep frontmatter parameters, usage text, and the flag parser in lockstep.
If frontmatter names use underscores, the parser must accept those exact
names or documented aliases; do not ship github_repo metadata with only a
--github-repo parser unless both forms work.
Start with metadata.status: draft. Do not set released until dependency
preflight and replay QA have passed.
Test the draft with at least three distinct inputs:
cd ~/.rote/flows/<name>
rote deps check deps.toml
rote deno run --allow-all ~/.rote/flows/<name>/main.ts <input-a>
rote deno run --allow-all ~/.rote/flows/<name>/main.ts <input-b>
rote deno run --allow-all ~/.rote/flows/<name>/main.ts <input-c>If dependency preflight fails, ask the user whether to provision missing
required tools, with the install scope and side effects stated plainly. Do
not continue release QA until dependency preflight passes or the user says
to keep the flow as draft.
Use the right QA gate for the execution shape.
Declarative steps: DAG flows:
rote flow validate ~/.rote/flows/<name>/main.ts
rote deno run --allow-all ~/.rote/flows/<name>/main.ts --dry-run <params>
rote deno run --allow-all ~/.rote/flows/<name>/main.ts <params>
rote deno run --allow-all ~/.rote/flows/<name>/main.ts --resume latest <params>rote flow lint checks the authored FlowOutput contract and is not a
release gate for pure steps: DAG flows whose TypeScript body is bypassed by
the DAG runner.
Authored SDK flows:
rote flow lint <name>
rote deno run --allow-all ~/.rote/flows/<name>/main.ts --help
rote deno run --allow-all ~/.rote/flows/<name>/main.ts <known-good-input>In both shapes, loop until hardcoded paths, missing dependency declarations, mismatched parameters, raw shell leaks, and output-format issues are fixed.
Mark the flow released only after QA passes. Current practice is to edit the
frontmatter status from draft to released, then rebuild and verify the
index:
rote flow index --rebuild
rote flow search "<name or relevant keywords>"If a pending workspace stub was used, discard it after release:
rote flow pending discard <workspace>Do not claim a shell-derived flow is released from memory. The release claim
must point back to rote deps check deps.toml, command output, saved responses,
and successful rote deno run --allow-all executions.
In steps: flows, @step{.path} resolves against the step response body, not
the persisted @N envelope on disk. For an MCP adapter call, the response body
is the JSON-RPC body, so a GitHub adapter text payload usually needs a scalar
query such as:
@repo_adapter{.result.content[0].text | fromjson | .full_name}For process steps, the response body is process.exec, so downstream steps can
reference fields such as .stdout.text or captured file metadata. Keep
process.exec argv, stdin paths, and capture paths scalar after resolution.
Do not pass large adapter/browser payloads through argv when a file bridge or a
small scalar projection is clearer.
© modiqo, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in .claude/skills/rote-shell/source of modiqo/skillspec.
Open the folder on GitHubat commit f4d9ab5
Rote Shell next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Rote Shell this skillmodiqo/skillspec | 706 | — | ~7.2k | Automated safety check: Pass | Apache-2.0 | |
| MCP Server Builderanthropics/skills | 180k | 64 repos | ~2.3k | Automated safety check: Pass | Apache-2.0 | |
| Web Artifacts Builderanthropics/skills | 180k | 41 repos | ~769 | Automated safety check: Pass | Apache-2.0 | |
| Typescript Advanced Typesrolling-scopes/rsschool-app | 10k | 25 repos | ~4.2k | Automated safety check: Pass | MPL-2.0 | |
| Code Review ChecklistshareAI-lab/learn-claude-code | 78k | 5 repos | ~1.1k | Automated safety check: Pass | MIT | |
| MCP Server BuildershareAI-lab/learn-claude-code | 78k | 5 repos | ~1.2k | Automated safety check: Pass | MIT |
anthropics/skills
Guides the design and implementation of Model Context Protocol servers in TypeScript or Python, from tool naming and error messages to evaluation.
anthropics/skills
Builds multi-component claude.ai HTML artifacts as a small React, TypeScript and Tailwind project, then bundles it into one shareable HTML file.
rolling-scopes/rsschool-app
Master TypeScript's advanced type system including generics, conditional types, mapped types, template literals, and utility types for building type-safe applications.
shareAI-lab/learn-claude-code
Reviews code against a five-part checklist covering security, correctness, performance, maintainability and testing, and reports findings in a fixed format.
shareAI-lab/learn-claude-code
Walks through building MCP servers in Python or TypeScript that expose tools, resources and prompts to Claude, with templates, registration and testing.
nrwl/nx
Import, merge, or combine repositories into an Nx workspace using nx import.
modiqo/skillspec
Multi-agent code review with deep analysis. An agent skill from modiqo/skillspec.
modiqo/skillspec
Document and explain the codebase as-is using parallel sub-agents.
modiqo/skillspec
A skill your agent uses when the task needs to browse a website with rote, browse Gmail or an email web app with rote, attach to an active browser, inspect logged-in web app state, snapshot or slice…
modiqo/skillspec
A skill your agent uses when the task needs to run a local command and remember the result, inspect CLI output with provenance, follow a log or process stream, start or observe a background job…
modiqo/skillspec
A skill your agent uses when writing commit messages, creating PR titles, pushing commits, or creating PRs — ensures conventional commit format and that formatting/linting pass before any push
modiqo/skillspec
Review code changes by collecting the review target, researching context, checking risks, and reporting findings before summary.
Works with
A skill your agent uses for CLI and shell work through rote: running local commands with rote exec, capturing stdout/stderr/files, following logs and background processes, checking dependency…. Rote Shell is an agent skill from modiqo/skillspec. Use for CLI and shell work through rote: running local commands with rote exec, capturing stdout/stderr/files, following logs and background processes, checking dependency manifests, mixing adapters/browser/process steps, and crystallizing CLI work into TypeScript flows.
Rote Shell fits situations like: CLI and shell work through rote: running local commands with rote exec; capturing stdout/stderr/files; following logs and background processes; checking dependency manifests.
Run `npx skills add modiqo/skillspec --skill rote-shell -a claude-code`. Or copy the skill folder (.claude/skills/rote-shell/source in modiqo/skillspec) into .claude/skills/rote-shell in your project. Claude Code loads it when a task matches its description.
Run `npx skills add modiqo/skillspec --skill rote-shell -a codex`. Or copy the skill folder (.claude/skills/rote-shell/source in modiqo/skillspec) into .agents/skills/rote-shell in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add modiqo/skillspec --skill rote-shell -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/rote-shell, .gemini/skills/rote-shell, .github/skills/rote-shell and .opencode/skills/rote-shell in your project.
Going by SKILL.md and its folder, Rote Shell needs the command-line tools its instructions call (cargo, npm and gh).
SKILL.md contains no URLs. Its commands use npm and gh, which can reach the network depending on how they are called. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Rote Shell is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 7.2k tokens (SKILL.md is roughly 29k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Rote Shell: MCP Server Builder (anthropics/skills, 180k stars), Web Artifacts Builder (anthropics/skills, 180k stars), Typescript Advanced Types (rolling-scopes/rsschool-app, 10k stars) and Code Review Checklist (shareAI-lab/learn-claude-code, 78k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
modiqo (a GitHub organization) maintains it in modiqo/skillspec, which has 706 GitHub stars. The repository holds 9 skills in this directory. The repository was last updated on August 9, 2026.
Source: modiqo/skillspec on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.