Best for
- Activation Triggers
- When NOT to Use
- User mentions "aside", "aside browser", "AI browser" automation explicitly
MichelKerkmeester/opencode--skilled-agent-loops-with-spec-kit-memory/.opencode/skills/mcp-tooling/mcp-aside-devtools/SKILL.md
Aside AI-browser orchestrator: routes between the aside CLI (agent tasks + deterministic REPL) and Aside MCP via Code Mode.
Decision brief
AI-browser automation through the Aside CLI: natural-language agent tasks and a deterministic Playwright-compatible JavaScript REPL, with the Aside MCP server via Code Mode as the composition fallback.
Compatibility matrix
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/MichelKerkmeester/opencode--skilled-agent-loops-with-spec-kit-memory --skill ".opencode/skills/mcp-tooling/mcp-aside-devtools"Inspect the Agent Skill "mcp-aside-devtools" from https://github.com/MichelKerkmeester/opencode--skilled-agent-loops-with-spec-kit-memory/blob/3d386ee21366523774d89c0aff3ebbbc8fa7ff10/.opencode/skills/mcp-tooling/mcp-aside-devtools/SKILL.md at commit 3d386ee21366523774d89c0aff3ebbbc8fa7ff10. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
Use Bash for aside, Read for references, Grep for logs/output, and Glob for screenshots/artifacts. The aside manual is registered in .utcpconfig.json; use mcpcodemodecalltoolchain only after its callables are discovery-confirmed (searchtools()/toolinfo()) in a Code Mode session…
Use when: - User mentions "aside", "aside browser", "AI browser" automation explicitly - User wants a goal-driven, multi-step browser task delegated to a browser agent ("book, fill, compare, sign in and download") - User needs deterministic, evidence-friendly browser steps (open…
Use when: - User mentions "aside", "aside browser", "AI browser" automation explicitly - User wants a goal-driven, multi-step browser task delegated to a browser agent ("book, fill, compare, sign in and download") - User needs deterministic, evidence-friendly browser steps (open…
Do not use for: - Chrome/Chromium/Edge debugging with raw CDP primitives, HAR export, or bdg (use mcp-chrome-devtools — Aside has no CDP-domain parity and no dedicated console/network tools) - Extracting a measured Style Reference (design tokens) from a live website's real CSS (…
The authoritative routing logic for scoped loading, weighted intent scoring, and ambiguity handling.
Permission review
The documentation includes network, browsing, or remote request actions.
"INSTALL": {"weight": 4, "keywords": ["install", "setup", "set up", "not installed", "curl", "sign in", "sign-in", "getting started", "not found", "first time", "command -v aside"]},The documentation asks the agent to run terminal commands or scripts.
Run the CLI preflight (`command -v aside` → `--version` → `--help` fixture) before any Aside operation.Evidence record
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 95/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 34 | Source | Repository attention, not individual Skill quality |
| Compatibility | 0 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
AI-browser automation through the Aside CLI: natural-language agent tasks and a deterministic Playwright-compatible JavaScript REPL, with the Aside MCP server via Code Mode as the composition fallback.
Use when:
aside replrepl surfaceAutomatic Triggers:
Do not use for:
bdg (use mcp-chrome-devtools — Aside has no CDP-domain parity and no dedicated console/network tools)sk-design-md-generator)sk-code)| Level | When to Load | Resources |
|---|---|---|
| CONDITIONAL | If intent signals match | REPL/MCP/session/troubleshooting |
| ON_DEMAND | Only on explicit request | Full diagnostics set |
| FALLBACK | Zero-score routes only | Core CLI reference suggested (never auto-loaded) |
The authoritative routing logic for scoped loading, weighted intent scoring, and ambiguity handling.
discover_markdown_resources() recursively scans skill-local references/ and assets/ when those folders exist.load_if_available() uses _guard_in_skill(), the discovered inventory, and a seen set.references/*.md resources plus the flat assets/utcp-aside-manual.md snapshot. This skill has no keyed references/<key>/ or assets/<key>/ resource subdirectories.UNKNOWN_FALLBACK requests CLI/REPL/MCP disambiguation and SUGGESTS the default CLI reference without loading it (DEFAULT_RESOURCE_SEMANTICS = "fallback-only"): a scored route loads exactly its intents' mapped resources, and a zero-score route loads nothing beyond the disambiguation checklist.from pathlib import Path
SKILL_ROOT = Path(__file__).resolve().parent
RESOURCE_BASES = (SKILL_ROOT / "references", SKILL_ROOT / "assets")
DEFAULT_RESOURCE = "references/aside-cli-reference.md"
# Fallback-only: DEFAULT_RESOURCE is a defer-time suggestion, never unioned
# into a route's loaded set. Scored routes load exactly RESOURCE_MAP[intent];
# zero-score routes load nothing and ask for disambiguation instead.
DEFAULT_RESOURCE_SEMANTICS = "fallback-only"
UNKNOWN_FALLBACK_CHECKLIST = [
"Confirm agent-task CLI vs deterministic REPL vs Code Mode MCP path",
"Confirm the signed-in Aside account and target profile",
"Provide one task goal, URL, or error message",
]
INTENT_SIGNALS = {
"TASK": {"weight": 4, "keywords": ["aside", "agent task", "browser agent", "natural language", "ai browser", "aside exec", "autonomous", "multi-step", "sign in and", "book", "fill the form"]},
"REPL": {"weight": 4, "keywords": ["repl", "deterministic", "playwright", "snapshot", "screenshot", "opentab", "open tab", "javascript", "evidence", "page.pdf", "annotated"]},
"MCP": {"weight": 4, "keywords": ["mcp", "code mode", "tool chain", "stdio", "tools/list", "call_tool_chain", "manual", "model context protocol", "chained with other tools"]},
"INSTALL": {"weight": 4, "keywords": ["install", "setup", "set up", "not installed", "curl", "sign in", "sign-in", "getting started", "not found", "first time", "command -v aside"]},
"TROUBLESHOOT": {"weight": 4, "keywords": ["error", "failed", "troubleshoot", "unbound", "not bound", "daemon", "signed out", "timeout", "hangs", "hanging", "stuck", "crash", "broken", "not working", "won't connect", "root cause"]},
}
RESOURCE_MAP = {
"TASK": ["references/aside-cli-reference.md", "references/session-management.md"],
"REPL": ["references/aside-cli-reference.md", "references/session-management.md"],
"MCP": ["references/mcp-wiring.md", "references/session-management.md", "assets/utcp-aside-manual.md"],
"INSTALL": ["references/troubleshooting.md"],
"TROUBLESHOOT": ["references/troubleshooting.md", "references/session-management.md"],
}
LOADING_LEVELS = {
"ON_DEMAND_KEYWORDS": ["full troubleshooting", "full session guide", "all patterns", "permission model", "daemon health", "everything about aside"],
"ON_DEMAND": ["references/troubleshooting.md", "references/session-management.md", "references/mcp-wiring.md"],
}
def _task_text(task) -> str:
parts = [
str(getattr(task, "text", "")),
str(getattr(task, "query", "")),
" ".join(getattr(task, "keywords", []) or []),
]
return " ".join(parts).lower()
def _guard_in_skill(relative_path: str) -> str:
resolved = (SKILL_ROOT / relative_path).resolve()
resolved.relative_to(SKILL_ROOT)
if resolved.suffix.lower() != ".md":
raise ValueError(f"Only markdown resources are routable: {relative_path}")
return resolved.relative_to(SKILL_ROOT).as_posix()
def discover_markdown_resources() -> set[str]:
docs = []
for base in RESOURCE_BASES:
if base.exists():
docs.extend(p for p in base.rglob("*.md") if p.is_file())
return {doc.relative_to(SKILL_ROOT).as_posix() for doc in docs}
def score_intents(task) -> dict[str, float]:
"""Weighted intent scoring from request text and routing signals."""
text = _task_text(task)
scores = {intent: 0.0 for intent in INTENT_SIGNALS}
for intent, cfg in INTENT_SIGNALS.items():
for keyword in cfg["keywords"]:
if keyword in text:
scores[intent] += cfg["weight"]
if getattr(task, "cli_available", False):
scores["TASK"] += 4
if getattr(task, "code_mode_configured", False):
scores["MCP"] += 4
if getattr(task, "has_error", False):
scores["TROUBLESHOOT"] += 4
return scores
def select_intents(scores: dict[str, float], ambiguity_delta: float = 1.0, max_intents: int = 2) -> list[str]:
ranked = sorted(scores.items(), key=lambda item: item[1], reverse=True)
if not ranked or ranked[0][1] <= 0:
return ["UNKNOWN"]
selected = [ranked[0][0]]
if len(ranked) > 1 and ranked[1][1] > 0 and (ranked[0][1] - ranked[1][1]) <= ambiguity_delta:
selected.append(ranked[1][0])
return selected[:max_intents]
def route_aside_devtools_resources(task):
inventory = discover_markdown_resources()
scores = score_intents(task)
intents = select_intents(scores, ambiguity_delta=1.0)
loaded = []
seen = set()
def load_if_available(relative_path: str) -> None:
guarded = _guard_in_skill(relative_path)
if guarded in inventory and guarded not in seen:
load(guarded)
loaded.append(guarded)
seen.add(guarded)
if max(scores.values() or [0]) < 0.5:
# Fallback-only: nothing is loaded on a zero-score route; the default
# reference is offered as a suggestion beside the disambiguation ask.
return {
"routing_key": "aside-devtools",
"intents": intents,
"intent_scores": scores,
"load_level": "UNKNOWN_FALLBACK",
"needs_disambiguation": True,
"disambiguation_checklist": UNKNOWN_FALLBACK_CHECKLIST,
"suggested_fallback": DEFAULT_RESOURCE,
"resources": loaded,
}
matched_intents = []
for intent in intents:
before_count = len(loaded)
for relative_path in RESOURCE_MAP.get(intent, []):
load_if_available(relative_path)
if len(loaded) > before_count:
matched_intents.append(intent)
text = _task_text(task)
if any(keyword in text for keyword in LOADING_LEVELS["ON_DEMAND_KEYWORDS"]):
for relative_path in LOADING_LEVELS["ON_DEMAND"]:
load_if_available(relative_path)
result = {"routing_key": "aside-devtools", "intents": intents, "intent_scores": scores, "resources": loaded}
if not matched_intents:
result["notice"] = f"No knowledge base found for intent(s): {', '.join(intents)}"
result["suggested_fallback"] = DEFAULT_RESOURCE
return result
Prefer the CLI. It has two lanes: aside "<prompt>" / aside exec for outcome-oriented agent tasks, and aside repl "<JavaScript>" for deterministic, evidence-friendly steps. Use the Aside MCP server via Code Mode only when browser work must be composed with other MCP tools or when a capability exists only on the discovered MCP surface.
REQUEST
|
+- Outcome-oriented, multi-step, approval-gated -> aside "<prompt>" / aside exec
+- Deterministic proof (tab, snapshot, screenshot) -> aside repl "<JavaScript>"
+- Composition with other Code Mode tools -> Aside MCP repl via call_tool_chain()
command -v aside # binary present?
aside --version 2>&1 # capture the installed version as a fixture
aside --help 2>&1 # capture the installed command surface as a fixture
The command surface is version-pinned evidence. Re-capture --help before relying on any flag; never freeze flag spellings from memory. If the binary is absent, report the official install command (curl -fsSL https://releases.aside.com/install.sh | bash, macOS-only) and let the operator decide — never install implicitly.
| Command | Purpose |
|---|---|
aside "<task>" | Start a natural-language browser-agent task |
aside --session <id> "<task>" | Continue a prior agent task/session |
aside --account <id> "<task>" | Run a direct task under a selected account |
aside exec ... | Explicit task execution with provider/model controls |
aside account list / status [id] / use <id> | Enumerate / inspect / select accounts |
aside repl "<JavaScript>" | Deterministic browser automation (e.g. openTab(...)) |
aside mcp | Start the local MCP server over stdio |
Boundary rules: --account is documented for direct tasks and exec only — never invent aside mcp --account or aside repl --account. --session is agent-task continuation, not an MCP browser selector. There are no typed aside navigate/dom/screenshot/console/network subcommands.
UNKNOWN — model-flag spelling: docs show -m provider/model while the installed help shows separate --model and --provider options. Unresolved; capture the installed version's help before using either spelling.
aside mcp is a client-spawned local stdio process with no URL, port, token, or credential field; it inherits the logged-in CLI account/provider context. The Code Mode manual is named aside and is registered in .utcp_config.json (registered 2026-07-16; snapshot in assets/utcp-aside-manual.md). Live discovery ran 2026-07-16 (direct stdio MCP probe of CodeMode-MCP; fixture references/discovery-fixture-2026-07-16.json): the registry/discovery name is aside.aside.repl (dot-separated — NOT the previously predicted aside.aside_repl registry form), and the TypeScript callable inside call_tool_chain is aside.aside_repl(args) (fixture Access as: line, matching mcp-code-mode's {manual_name}.{manual_name}_{tool_name} convention). Rediscovery before invocation remains mandatory (tools.listChanged: true).
Version-pinned tool inventory: against version 1.26.626.1517 (protocol 2024-11-05, tools.listChanged: true), tools/list returned exactly one tool, repl (required inputs title + code; persistent sandboxed ES2023+/Playwright REPL; 120-second call timeout; no import/require). The one-repl-tool inventory was re-confirmed live through Code Mode discovery on 2026-07-16 (references/discovery-fixture-2026-07-16.json). This is evidence, not a contract: always rediscover at runtime (initialize → tools/list, then Code Mode search_tools()/list_tools()/tool_info()) before invocation. There are no first-class navigate, dom, screenshot, console, or network MCP tools.
Browser-profile binding: a fresh aside mcp process is transport-healthy but browser-unbound — listBrowserTabs() fails with "This task is not bound to a browser profile." This is a binding failure, not an auth failure. The supported binding procedure is UNKNOWN (undocumented); report it distinctly and stop.
Three layers, each with its own lifecycle:
--session <id> continues account-scoped task state; tasks can pause for input/approval and resume.Permission modes are Read only / Guard (default) / Full access, layered with Allow/Ask/Deny rules; Deny wins; saved password values are never exposed to the agent. Which mode aside mcp inherits is UNKNOWN — apply caller-owned read/action/sensitive policy. "Unattended" is best-effort: MFA, CAPTCHA, identity checks, vault unlock, and approvals pause tasks and require a human.
No public isolation guarantee exists for concurrent mutating clients on one profile (Aside has no --isolated=true equivalent). Default posture: one UTCP manual and a single-writer rule per account/profile; the dual-manual alternative is an unresolved open question. Cleanup: close the MCP stdio process; there is no public daemon/status/stop command. Wrap Code Mode browser operations in try/finally.
command -v aside → --version → --help fixture) before any Aside operation.repl-tool result as version-pinned evidence.2>&1.aside navigate/dom/screenshot/console/network) or MCP tools beyond the discovered inventory.aside.aside.repl, TS callable aside.aside_repl(args) — fixture references/discovery-fixture-2026-07-16.json; still re-verify per session).aside --update implicitly; installation is operator-invoked only.--account to aside mcp or aside repl; it is documented for direct tasks and exec only.aside manual without a controlled multi-client isolation test — the strategy is unresolved.page.on(...) events in the repl (fixture-confirmed API), but it is caller-assembled, not a dedicated tool: document the pattern, keep the honest gaps, and treat any live capture as needing a bound session + independent verification (see the DevTools-parity feature family).aside account use <id> or re-sign-in — needs the operator).-m vs --model/--provider conflict.Workflow is complete when the lane (task CLI / REPL / MCP) is selected and justified, preflight fixtures are captured, the operation ran with exit codes checked, artifacts are independently verified (PNG magic, parseable JSON), MCP processes are closed, and any UNKNOWN or probe-required capability touched is reported as such rather than claimed.
Quality targets are a passing preflight before first use, runtime tool discovery before every MCP invocation, and zero capability claims beyond the research-verified surface.
This skill operates within the behavioral framework defined in AGENTS.md.
Key integrations:
skill_advisor.pyUse Bash for aside, Read for references, Grep for logs/output, and Glob for screenshots/artifacts. The aside manual is registered in .utcp_config.json; use mcp__code_mode__call_tool_chain only after its callables are discovery-confirmed (search_tools()/tool_info()) in a Code Mode session that loaded the manual.
mcp-chrome-devtools owns imperative CDP debugging (bdg), dedicated console/network capture, and HAR export — route those requests there. This packet copies its routing discipline, not its command names.
page API)Aside mirrors the Chrome DevTools capability surface through one lane — the Playwright page API inside aside repl (fixture-confirmed). Full patterns and playbook scenarios live in the DevTools-parity feature family (feature-catalog/devtools-parity/, scenarios ASD-016..021). Confidence: confirmed = fixture + online research; skip-valid = documented pattern, live run needs a bound authorized session; gap = no Aside equivalent.
| DevTools capability | Aside repl pattern | Status |
|---|---|---|
| DOM query / eval | page.$eval / page.evaluate / snapshot(page) | confirmed / skip-valid |
| Screenshot + PDF | page.screenshot({ fullPage }) / page.pdf | confirmed |
| Console capture | page.on('console', ...) | skip-valid |
| Network capture | page.on('request'|'response', ...) | skip-valid |
| HAR export | assemble from events | gap — no native HAR |
| Cookies + storage | page.context().cookies() / page.evaluate(localStorage) | confirmed / skip-valid |
| Performance timing | page.evaluate(performance.getEntriesByType(...)) | confirmed / skip-valid |
| Lighthouse audit | — external tooling required | gap — no Lighthouse |
| Navigate + multi-tab | openTab / attachActiveBrowserTab / page.goto / tabs | confirmed / skip-valid |
| Parallel isolated instances | — single manual, single writer | gap — no isolation |
| Raw CDP passthrough | — Playwright API only | gap — no CDP |
Use aside "<task>", aside --session <id> "<task>", aside exec, aside account list, aside account status, aside account use <id>, aside repl "<JavaScript>" (e.g. openTab(url)), and aside mcp. Global options observed on 1.26.626.1517: --version, --session <id>, --account <id>, --model <model>, --provider <provider>, --speed <default|fast>, --effort <off|minimal|low|medium|high|xhigh|ultrabrowse>, --update (never invoke implicitly). Re-capture aside --help per installed version before relying on any of these.
The router discovers markdown resources dynamically from references/ and assets/ when those directories exist. This skill routes over the flat reference set: references/aside-cli-reference.md, references/mcp-wiring.md, references/session-management.md, and references/troubleshooting.md. The dated online-research refresh references/aside-online-research-2026-07-17.md (CLI/MCP/REPL corroboration, the verbatim mcp.json wiring, and the permission model) is discovered dynamically but is not mapped to a specific intent — read it directly when verifying the current developer surface.
Assets: assets/utcp-aside-manual.md — the registered aside UTCP manual snapshot (registered 2026-07-16; verify with jq, do not re-add), loaded for MCP intent.
Feature catalog: feature-catalog/feature-catalog.md — the capability inventory across the five intent domains. It lives outside the references//assets/ discovery roots, so it is linked here rather than auto-loaded by the router.
Scripts: scripts/install.sh, scripts/doctor.sh.
Examples: examples/README.md — workflow example scripts. It lives outside the references//assets/ discovery roots, so it is linked here rather than auto-loaded by the router.
Server packages: mcp-servers/aside-cli/README.md and mcp-servers/aside-mcp/README.md — install pointers for the CLI and the MCP registration (the aside UTCP manual is registered; see assets/utcp-aside-manual.md).
Related skills: mcp-code-mode for the MCP transport, mcp-chrome-devtools for CDP-level browser debugging, and sk-code for the application code being verified.
Install guide: INSTALL-GUIDE.md.
Frequently asked questions
AI-browser automation through the Aside CLI: natural-language agent tasks and a deterministic Playwright-compatible JavaScript REPL, with the Aside MCP server via Code Mode as the composition fallback.
The source record exposes this install command: npx skills add https://github.com/MichelKerkmeester/opencode--skilled-agent-loops-with-spec-kit-memory --skill ".opencode/skills/mcp-tooling/mcp-aside-devtools". Inspect the command and pinned source before running it.
Static rules flagged network, exec-script in the source; the page lists the matching lines and excerpts.
Alternatives
garrytan/gbrain
End-to-end discipline for turning any large data source (audio libraries, email takeouts, document corpora, chat exports, API dumps) into brain pages at scale. The lifecycle spine: SCHEMA → ACCESS → TRIAL → EVALUATE → IMPROVE → CODIFY → TEST → SKILLIFY → BULK → MONITOR. State is tracked in a durable JSON manifest (see MANIFEST-PATTERN.md) so any crash, session boundary, or subagent fan-out resumes from ground truth instead of memory.
alirezarezvani/claude-skills
App Store Optimization (ASO) toolkit for researching keywords, analyzing competitor rankings, generating metadata suggestions, and improving app visibility on Apple App Store and Google Play Store. Use when the user asks about ASO, app store rankings, app metadata, app titles and descriptions, app store listings, app visibility, or mobile app marketing on iOS or Android. Supports keyword research and scoring, competitor keyword analysis, metadata optimization, A/B test planning, launch checklist
dotnet/skills
Migrates .NET test projects from VSTest to Microsoft.Testing.Platform (MTP). Use when user asks to "migrate to MTP", "switch from VSTest", "enable Microsoft.Testing.Platform", "use MTP runner", set OutputType=Exe only for test projects in Directory.Build.props, or mentions EnableMSTestRunner, EnableNUnitRunner, or UseMicrosoftTestingPlatformRunner. USE FOR: MTP behavioral differences vs VSTest (exit code 8, zero tests discovered, --ignore-exit-code, TESTINGPLATFORM_EXITCODE_IGNORE); centralizing
vipshop/cache-dit
High-level guide for integrating a new DiT model into cache-dit: Cache (BlockAdapter/ForwardPattern), Context Parallelism, Tensor Parallelism, Text Encoder Parallelism (TE-P), VAE Parallelism (VAE-P), generate CLI, installation, testing workflow, and detailed references. Use when adding support for a new diffusion transformer model in cache-dit.