skills/yoetz/SKILL.md
Fast CLI-first LLM council, bundler, and multimodal gateway. Use ONLY when user explicitly mentions "yoetz", "yoetz ask", "yoetz council", "yoetz review", "yoetz generate", "yoetz bundle", "yoetz browser". NOT triggered by generic "second opinion" or "ask another model" requests.
npx skillsauth add avivsinai/yoetz yoetzInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Fast, agent-friendly LLM council tool for multi-model consensus, code review, and bundling.
Explicit triggers only:
NOT triggered by:
Before running any yoetz command, ensure the CLI is installed.
If command -v yoetz fails, install via one of the following:
| Platform | Command |
|----------|---------|
| macOS (Homebrew) | brew install avivsinai/tap/yoetz |
| Linux (Homebrew if available) | brew install avivsinai/tap/yoetz |
| From source (Rust 1.88+) | cargo install --git https://github.com/avivsinai/yoetz --locked |
| Windows (Scoop) | scoop bucket add avivsinai https://github.com/avivsinai/scoop-bucket && scoop install yoetz |
| Pre-built binary | Download from GitHub Releases and place in PATH |
Prefer Homebrew when available — pre-built binaries, fastest install.
Install the Yoetz agent skill itself when the user asks for Yoetz support inside Claude Code, Codex CLI, or another compatible skill-aware agent runtime:
/plugin marketplace add avivsinai/skills-marketplace
/plugin install yoetz@avivsinai-marketplace
npx skills add avivsinai/yoetz
npx skild install @avivsinai/yoetz
The CLI and the agent skill are separate deliverables: installing yoetz puts
the binary on PATH; installing the skill teaches the agent how to call it
safely.
--format json for parsingYOETZ_AGENT=1 environment variableyoetz bundle first to inspect sizeNEVER type a model ID from memory. Agent training data contains stale model names. Always query the live registry.
To find the current frontier model per provider:
yoetz models frontier --format json
To find a specific model:
yoetz models resolve "grok" --format json
Use the returned ID verbatim in your commands. Do not modify, shorten, or guess model IDs.
If the registry is stale or empty, sync first:
yoetz models sync
Search for models by keyword:
yoetz models list -s claude --format json
| Task | Command |
|------|---------|
| Find frontier model per provider | yoetz models frontier --format json |
| Find frontier model for a provider | yoetz models frontier --family openai --format json |
| Resolve a model ID | yoetz models resolve "grok" --format json |
| Search models | yoetz models list -s claude --format json |
| Ask single model | yoetz ask -p "question" -f "src/*.rs" --provider openrouter --model MODEL_ID --format json |
| Council vote | yoetz council -p "question" --models MODEL_ID,MODEL_ID,MODEL_ID --format json |
| Review staged diff | yoetz review diff --staged --format json |
| Review file | yoetz review file --path src/main.rs --format json |
| Bundle files | yoetz bundle -p "context" -f "src/**/*.rs" --format json |
| Generate image | yoetz generate image -p "description" --provider openai --model MODEL_ID --format json |
| Estimate cost | yoetz pricing estimate --model MODEL_ID --input-tokens 1000 --output-tokens 500 |
| Browser check (CDP/default) | yoetz browser check --format json |
| Extension check | yoetz browser check --transport chrome-extension-native --format json |
| Browser attach | yoetz browser attach --format json |
| Browser login | yoetz browser login |
Replace MODEL_ID with IDs from yoetz models frontier or yoetz models resolve.
Examples that use --provider openrouter require OPENROUTER_API_KEY. If the
user only has a direct provider key, use the matching provider instead, such as
--provider openai with an OpenAI-family ID.
Get opinions from multiple LLMs in parallel. --models is required.
OPENAI_MODEL=$(yoetz models frontier --family openai --format json | jq -r '.[0].model.id')
ANTHROPIC_MODEL=$(yoetz models frontier --family anthropic --format json | jq -r '.[0].model.id')
XAI_MODEL=$(yoetz models frontier --family xai --format json | jq -r '.[0].model.id')
yoetz council \
-p "Should we use async traits or callbacks for this API?" \
-f src/lib.rs -f "src/api/*.rs" \
--models "$OPENAI_MODEL,$ANTHROPIC_MODEL,$XAI_MODEL" \
--format json
Use the returned model IDs verbatim. Do not add provider prefixes, nested
OpenRouter wrappers, or old example names around IDs returned by frontier or
resolve.
Quick question with file context:
MODEL_ID=$(yoetz models frontier --family openai --format json | jq -r '.[0].model.id')
yoetz ask \
-p "What's the bug in this error handling?" \
-f src/error.rs \
--provider openrouter --model "$MODEL_ID" \
--format json
For Anthropic/XAI models, use OpenRouter (no extra config needed):
MODEL_ID=$(yoetz models frontier --family anthropic --format json | jq -r '.[0].model.id')
yoetz ask -p "Review this" -f "src/*.rs" \
--provider openrouter --model "$MODEL_ID" \
--format json
yoetz review diff --staged --format json
yoetz review file --path src/main.rs --format json
MODEL_ID=$(yoetz models frontier --family openai --format json | jq -r '.[0].model.id')
yoetz review diff --staged --provider openrouter --model "$MODEL_ID" --format json
Bundle creates a session with files at ~/.yoetz/sessions/<id>/bundle.md.
# Get bundle path from JSON output
yoetz bundle -p "Explain this" -f "src/**/*.rs" --format json
# Output includes: {"artifacts":{"bundle_md":"/Users/.../.yoetz/sessions/.../bundle.md",...},...}
# Extract bundle_md path directly
BUNDLE=$(yoetz bundle -p "Review" -f "src/*.rs" --format json | jq -r .artifacts.bundle_md)
cat "$BUNDLE"
For browser workflows, pass the bundle.md path:
BUNDLE=$(yoetz bundle -p "Review" -f "src/*.rs" --format json | jq -r .artifacts.bundle_md)
yoetz browser recipe --recipe chatgpt --bundle "$BUNDLE" --format json
For web-only models like ChatGPT Pro that lack API access. Connects to your running Chrome via CDP (Chrome DevTools Protocol) to submit bundles through the web UI.
If the user is doing repeated ChatGPT Pro/Enterprise recipe work, or mentions
Chrome remote-debugging approval friction, recommend the opt-in
chrome-extension-native transport as the robust path. Use the native setup
flow, load/update the extension in Chrome, run doctor, then target the stable
extension_instance_id when multiple profiles are open.
The recipe supports both ChatGPT Enterprise and personal ChatGPT account UIs;
their model pickers differ, but Yoetz still targets only Pro with Extended
enabled and fails closed if that selection cannot be proven.
Do not silently switch transports after upload/send/wait side effects. If the extension reports a terminal ChatGPT phase, preserve the manual-recovery tab and warn before any rerun that could duplicate a submission.
ChatGPT Pro code reviews can legitimately spend 15-20 minutes in file analysis.
This is normal. The native-extension transport prints low-noise lifecycle and
waiting_response progress to stderr, including in --format json mode so
stdout remains parseable. For unattended review loops, keep waiting on the
original process until it returns, write the result with --output-final, and do
not launch a second run just because progress is sparse. The current recipe
default is 90 minutes; set --var wait_timeout_ms=<milliseconds> only when a
run needs a deliberate override. If the extension returns a terminal
upload/send/wait error, use
yoetz browser extension inspect --chatgpt --run-id <run-id> before deciding
whether an intentional rerun is safe.
If progress says waiting for final assistant controls, ChatGPT has exposed
post-send assistant text but not a final scoped action affordance yet. Do not
treat the visible text as complete and do not start a duplicate run; use the
reported inspect command to check the preserved tab if you need live state.
# Optional fallback browser transports:
npm install -g dev-browser
# Secondary fallback transport:
npm install -g agent-browser
yoetz connects to your already logged-in Chrome session via auto-connect (CDP). No cookie extraction or separate browser needed.
Transport priority: chrome-devtools-mcp > dev-browser > agent-browser > manual browser upload.
Connection priority: explicit --cdp > auto-connect > cookie state > profile fallback.
Use --cdp http://127.0.0.1:9222 when you need to target a specific Chrome instance/profile.
Step 1: Enable remote debugging in Chrome
chrome://inspect/#remote-debuggingIf Chrome lands on chrome://inspect/#devices instead, that's fine. Keep "Discover network targets" enabled there.
Step 2: Run a recipe
BUNDLE=$(yoetz bundle -p "Review" -f "src/*.rs" --format json | jq -r .artifacts.bundle_md)
yoetz browser recipe --recipe chatgpt --bundle "$BUNDLE" --format json
Step 3: Approve remote debugging (Chrome 146+) Chrome 146+ may show an "Allow remote debugging?" dialog on the first live attach. Click Allow once for that browser instance.
Step 4: Verify connection
yoetz browser attach --format json
Chrome 146 introduced a security dialog for external CDP connections. Yoetz is extension-free by design, so the only way to get "approve once, then run silently" behavior is to keep the daemon/CDP session alive and avoid tearing it down between invocations.
Current policy:
chrome-devtools-mcp first, dev-browser second, agent-browser third.yoetz browser reset explicitly.yoetz browser extension status --chatgpt reports connected, the built-in ChatGPT recipe selects chrome-extension-native as its only default transport and fails closed. Use --transport <other> to opt out intentionally.If you see "Allow remote debugging?" in Chrome, click Allow and retry.
Explicit --cdp is already supported on yoetz browser attach, check, recipe, and login, but it only bypasses auto-discovery. It does not bypass Chrome's approval gate when targeting the same live browser instance started from chrome://inspect.
If the approval dialog is frozen or unclickable, use the manual CDP path instead:
chrome --remote-debugging-port=9222 --user-data-dir=/tmp/chrome-debug
yoetz browser attach --cdp http://127.0.0.1:9222 --format json
Chrome for Testing is also a good fallback for this manual path.
Use this when ChatGPT Pro recipe robustness needs install-once native messaging instead of CDP approval prompts:
yoetz browser extension setup --chatgpt --open-chrome
yoetz browser extension doctor --chatgpt
yoetz browser extension status --chatgpt --format json
yoetz browser check --transport chrome-extension-native --format json
yoetz browser recipe \
--recipe chatgpt \
--transport chrome-extension-native \
--bundle "$BUNDLE" \
--format json \
--output-final /tmp/yoetz-chatgpt-native.json
Maintenance commands:
yoetz browser extension install-host --chatgpt
yoetz browser extension reconnect --chatgpt
yoetz browser extension reload --chatgpt
yoetz browser extension update --chatgpt
yoetz browser extension inspect --chatgpt --run-id <run-id>
yoetz browser extension grant-identity --chatgpt
The extension transport is ChatGPT-only, native-host backed, and currently
macOS/Linux-only. Do not use it as a general browser interpreter, and do not
silently fall back to CDP after browser-side side effects have started.
For extension-native workflows, do not run plain yoetz browser check; that
checks the default CDP/browser stack and may trigger Chrome's remote-debugging
approval. Use yoetz browser check --transport chrome-extension-native --format json
or yoetz browser extension doctor --chatgpt instead.
Do not run a live canary as a routine readiness step before ChatGPT Pro recipe
runs; reserve it for explicit diagnostics.
If doctor or inspect points to a live ChatGPT-side problem and the user
explicitly wants a diagnostic probe, run
yoetz browser extension canary --chatgpt --live.
For autonomous ChatGPT Pro work, treat the caller-provided bundle as
authoritative and expect long waits: 15-20 minutes is normal for large file
analysis, and the default wait_timeout_ms is 90 minutes. Use JSON output and a
durable result file; progress is emitted to stderr so stdout remains valid JSON.
Example:
YOETZ_AGENT=1 yoetz browser recipe \
--recipe chatgpt \
--transport chrome-extension-native \
--bundle "$BUNDLE" \
--format json \
--output-final /tmp/yoetz-chatgpt-review.json \
--var extension_instance_id=ext_...
When --bundle points at a Yoetz session bundle.md, the ChatGPT composer
prompt defaults to the user prompt stored in the adjacent bundle.json; use
--var prompt=... only when intentionally overriding that prompt for a test or
manual run.
Keep the process attached until it returns. Parse the JSON response as the
model's answer to the prompt; Yoetz does not attach pass/fail/review semantics
to the text. Hand the response back according to the user's current task. If
that task explicitly calls for iteration, apply the requested follow-up work,
build a fresh bundle, and run a new native-extension recipe with a new
run_id and --output-final. If the answer is obviously truncated or
nonsensical, report that the model response was unusable; rerun only when the
current user task calls for another attempt.
If a run fails after upload/send/wait, inspect the marked tab with the run id
from the error instead of rerunning blindly; reruns after browser side effects
can duplicate the submission.
For response_extraction_failed, compare the tab and diagnostics: if the owned
tab itself only shows a tiny/truncated assistant fragment, report that ChatGPT
returned an unusable answer; if the tab visibly contains the full answer,
preserve the tab and report the extraction miss.
Manual Chrome-side install is still part of this path, but updates are managed
by Yoetz. setup --chatgpt copies packaged extension source into the stable
$YOETZ_DIR/chatgpt-native-extension directory; load that directory once from
chrome://extensions with Developer mode enabled. After Yoetz upgrades, run
yoetz browser extension update --chatgpt to refresh the managed copy, reload
Chrome, and verify the loaded version. If an older install has Chrome loading
$YOETZ_DIR/chrome-extension-native/unpacked, update refreshes that loaded
directory too.
For agent-driven setup, prefer yoetz browser extension setup --chatgpt --open-chrome; it installs the host, opens Chrome's extension page, and prints
the exact folder to select. Chrome still requires the Load unpacked UI
confirmation for local extensions.
When multiple Chrome profiles have the extension loaded, pass
--var profile_email=<email> if Chrome exposes one, or the stable
--var extension_instance_id=<id> shown by status --chatgpt.
If auto-connect isn't available, cookie sync is still supported:
# Log into ChatGPT in real Chrome, close Chrome, then:
yoetz browser sync-cookies
yoetz browser check --format json
Requires Node >= 24.4. If macOS shows a Keychain prompt for Chrome Safe Storage, click Always Allow.
The built-in ChatGPT recipe always targets Pro with Extended enabled. Do not pass
model or extended overrides; the CLI rejects them. This applies to both
ChatGPT Enterprise and personal ChatGPT accounts. Different picker layouts are
handled by the transport, but an unproven Pro Extended selection is a hard
failure before upload/send.
# Create bundle and get bundle.md path
BUNDLE=$(yoetz bundle -p "Review this code" -f "src/*.rs" --format json | jq -r .artifacts.bundle_md)
# Send to ChatGPT
yoetz browser recipe --recipe chatgpt --bundle "$BUNDLE" --format json
# By default, every request opens a fresh, yoetz-owned ChatGPT tab marked with
# ?_yoetz=<run-id> so your own ChatGPT tabs are not touched. `--var thread=reuse`
# is rejected. To resume, pass `--var conversation=<id|url>`; yoetz still opens a
# new owned tab for that conversation.
The wait loop reports completion_reason in its JSON output:
copy_button — the strong signal: a copy control rendered on the new
assistant message (response is fully streamed).stable_idle_unscoped_copy_button — guarded recovery for long responses when
scoped assistant text is stable, generation is idle, and a new copy control is
visible but cannot be scoped to the latest assistant turn.There is no generic "stable text" completion fallback for the extension transport. If ChatGPT text is visible but final controls have not appeared yet, Yoetz keeps waiting and prints the inspect command unless the long-response copy-control recovery above is satisfied.
# Get fast API results first
OPENAI_MODEL=$(yoetz models frontier --family openai --format json | jq -r '.[0].model.id')
GEMINI_MODEL=$(yoetz models frontier --family gemini --format json | jq -r '.[0].model.id')
yoetz council -p "Review" -f "src/*.rs" \
--models "$OPENAI_MODEL,$GEMINI_MODEL" --format json > api.json
# Then get ChatGPT Pro opinion
BUNDLE=$(yoetz bundle -p "Review" -f "src/*.rs" --format json | jq -r .artifacts.bundle_md)
yoetz browser recipe --recipe chatgpt --bundle "$BUNDLE" --format json
Recipes can be specified by name (resolved from installed locations) or by path:
# By name (searches Homebrew share, XDG, etc.)
yoetz browser recipe --recipe chatgpt --bundle "$BUNDLE" --format json
# By explicit path
yoetz browser recipe --recipe ./my-recipes/custom.yaml --bundle "$BUNDLE" --format json
Built-in recipes: chatgpt, claude, gemini.
| Symptom | Fix |
|---------|-----|
| Allow remote debugging? dialog | Click Allow in Chrome, then retry. If the dialog is frozen, launch Chrome with --remote-debugging-port=9222 --user-data-dir=/tmp/chrome-debug and use yoetz browser attach --cdp http://127.0.0.1:9222 --format json instead. |
| auto-connect probe timed out | Chrome dialog is probably showing. Click Allow. If Chrome will not accept the dialog, switch to the explicit --cdp flow above. Install dev-browser first; agent-browser remains a fallback. |
| chatgpt login required | Chrome was reached but the wrong profile/tab was used. Open ChatGPT in the target Chrome profile first, or connect that profile explicitly with --cdp, then retry. |
| daemon already running | Run yoetz browser attach --format json to check connection. If the daemon is stale, use yoetz browser reset, not agent-browser close directly. |
| agent-browser failed | Ensure npx agent-browser --version works, or npm install -g agent-browser |
| dev-browser failed | Ensure dev-browser --help works, verify Chrome remote debugging is enabled, and retry with --cdp if you need a specific Chrome profile. |
| chrome-extension-native not connected | Run yoetz browser extension setup --chatgpt --open-chrome, load the printed managed extension directory in chrome://extensions, then run yoetz browser extension doctor --chatgpt. |
| Multiple extension profiles | Run yoetz browser extension status --chatgpt --format json; pass --var extension_instance_id=ext_... for deterministic routing. profile_email is only a Chrome-profile guard when Chrome exposes it. |
| Extension terminal phase after upload/send/wait | Do not rerun automatically. Continue in the Yoetz-owned ChatGPT tab or intentionally rerun knowing it may duplicate a submission. |
| Recipe not found | Use --recipe chatgpt (name) or full path. Check brew --prefix/share/yoetz/recipes/ |
| cookie extraction failed | Legacy path: ensure Node >= 24.4, log into ChatGPT in Chrome, close Chrome, yoetz browser sync-cookies |
When yoetz browser recipe needs manual browser automation, use dev-browser directly against the authenticated Chrome session:
BUNDLE=$(yoetz bundle -p "Review" -f "src/**/*.ts" --format json | jq -r .artifacts.bundle_md)dev-browser --connect <<'EOF'
const page = await browser.getPage("chatgpt");
await page.goto("https://chatgpt.com/");
console.log(await page.title());
EOF
browser.getPage(name), page.goto(url), page.click(selector), page.fill(selector, text), page.evaluate(fn), page.title()saveScreenshot(buf, name), writeFile(name, data), readFile(name)yoetz browser recipe --cdp http://127.0.0.1:9222 --format json ...This keeps the default path aligned with the same browser transport users already rely on outside Yoetz.
The browser module connects to your running Chrome via CDP (Chrome DevTools Protocol):
headless_chrome, attaches directly to your logged-in Chrome session--transport <other>
when you intentionally want the CDP/dev-browser stack.yoetz browser resetBuilt-in providers (work with just env var):
openai - OPENAI_API_KEYgemini - GEMINI_API_KEYopenrouter - OPENROUTER_API_KEYVia OpenRouter (recommended for Anthropic/XAI - no extra config):
yoetz models frontier --family anthropic --format jsonyoetz models frontier --family xai --format jsonModel IDs: use the exact id / model.id returned by
yoetz models frontier, yoetz models resolve, or yoetz models list. Do not
rewrite those IDs into provider wrappers or nested OpenRouter paths.
# Estimate before running
yoetz pricing estimate --model MODEL_ID --input-tokens 12000 --output-tokens 800
# Set limits
yoetz ask -p "Review" --max-cost-usd 1.00 --daily-budget-usd 5.00 --format json
--debug to capture raw responses during troubleshooting--max-output-tokens is too low~/.yoetz/sessions/<id>/yoetz ask -p "Describe" --image photo.png --format jsontools
Use when work should span one or more detached tasks but still behave like one job with a single owner context. TaskFlow is the durable flow substrate under authoring layers like Lobster, ACPX, plugins, or plain code. Keep conditional logic in the caller; use TaskFlow for flow identity, child-task linkage, waiting state, revision-checked mutations, and user-facing emergence.
tools
# Lobster Lobster executes multi-step workflows with approval checkpoints. Use it when: - User wants a repeatable automation (triage, monitor, sync) - Actions need human approval before executing (send, post, delete) - Multiple tool calls should run as one deterministic operation ## When to use Lobster | User intent | Use Lobster? | | ------------------------------------------------------ | --------------------------
tools
# Lobster Lobster executes multi-step workflows with approval checkpoints. Use it when: - User wants a repeatable automation (triage, monitor, sync) - Actions need human approval before executing (send, post, delete) - Multiple tool calls should run as one deterministic operation ## When to use Lobster | User intent | Use Lobster? | | ------------------------------------------------------ | --------------------------
tools
A CLI tool for making authenticated requests to the X (Twitter) API. Use this skill when you need to post tweets, reply, quote, search, read posts, manage followers, send DMs, upload media, or interact with any X API v2 endpoint.