Council Execution
hex/claude-council
Executes council queries by running the query pipeline across selected AI providers (Gemini, OpenAI, Grok, Perplexity), displaying formatted responses verbatim, and generating a synthesis of…
Control Chrome browser via CLI for testing, automation, and debugging.
The automated check flagged lines worth reading first. See the safety section below.
$ npx skills add w-winter/dot314 --skill surf -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install w-winter/dot314 surf --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/w-winter/dot314.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/surf .claude/skills/surf && 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 "surf" agent skill from https://github.com/w-winter/dot314/tree/main/skills/surf into .claude/skills/surf/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "surf", 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/w-winter/dot314/tree/main/skills/surfType 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 w-winter/dot314 --skill surf -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install w-winter/dot314 surf --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/w-winter/dot314.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/surf .agents/skills/surf && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "surf" agent skill from https://github.com/w-winter/dot314/tree/main/skills/surf into .agents/skills/surf/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "surf", 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 w-winter/dot314 --skill surf -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install w-winter/dot314 surf --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/w-winter/dot314.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/surf .cursor/skills/surf && 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 "surf" agent skill from https://github.com/w-winter/dot314/tree/main/skills/surf into .cursor/skills/surf/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "surf", 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/w-winter/dot314.git --path skills/surf--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 w-winter/dot314 --skill surf -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install w-winter/dot314 surf --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/w-winter/dot314.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/surf .gemini/skills/surf && 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 "surf" agent skill from https://github.com/w-winter/dot314/tree/main/skills/surf into .gemini/skills/surf/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "surf", 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 w-winter/dot314 surfInstalls 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 w-winter/dot314 --skill surf -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/w-winter/dot314.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/surf .github/skills/surf && 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 "surf" agent skill from https://github.com/w-winter/dot314/tree/main/skills/surf into .github/skills/surf/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "surf", 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 w-winter/dot314 --skill surf -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install w-winter/dot314 surf --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/w-winter/dot314.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/surf .opencode/skills/surf && 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 "surf" agent skill from https://github.com/w-winter/dot314/tree/main/skills/surf into .opencode/skills/surf/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "surf", 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.
surfControl Chrome browser via CLI for testing, automation, and debugging.
Surf is an agent skill from w-winter/dot314. Control Chrome browser via CLI for testing, automation, and debugging. Use when the user needs browser automation, screenshots, form filling, page inspection, network/CPU emulation, DevTools streaming, or AI queries via ChatGPT/Gemini/Perplexity/Grok/AI Studio.
Its SKILL.md is about 7.6k tokens, which your agent loads only when the skill is triggered. The skill folder holds 1 other file.
It sits in Productivity & Automation, covering Browser automation, Web search and Forms and invoices. It works with OpenAI, Perplexity and Linux. The licence is MIT.
4 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit 0c6bbc7. 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.
No scripts in the folder and no shell commands in SKILL.md (its code samples are bash and json).
From the folder's file list and the shell code blocks in SKILL.md.
Hosts in commands or code, which the agent is likely to contact:
youtube.comgoogle.comother.comFrom 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.
Surf loads about 7.6k tokens when it runs. Until then it costs about 67 tokens; SKILL.md has 1,745 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 patterns that need a careful read before installing.
es matching `.env*`, `*.pem`, `*.key`, `id_rsa*`, `id_ed25519*`, `*.p12`, `*.pfx`, `credentials*`, or `secrets*`. Use `-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 w-winter/dot314 at commit 0c6bbc7, republished under its MIT licence (© w-winter). 1,745 words, ~7,554 tokens.
.claude/skills/surf/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.Control Chrome browser via CLI or Unix socket.
For WSL2 with Windows Chrome, run surf install <extension-id> inside WSL2. Surf detects WSL2 and writes the Windows-side native messaging manifest plus a wrapper that launches the WSL host. Use surf install <extension-id> --target linux only for Linux browsers running inside WSLg.
On macOS, Chrome reads the native messaging manifest at ~/Library/Application Support/Google/Chrome/NativeMessagingHosts/surf.browser.host.json. If native messaging fails, confirm that file exists, its allowed_origins extension ID matches chrome://extensions, then rerun surf install <extension-id>, restart Chrome, reload the extension, and inspect the extension service-worker console.
If a command reports Socket connect failed, run surf doctor first, then check the Attempted socket: line. Default sockets are /tmp/surf.sock on macOS/Linux/WSL2 and //./pipe/surf on Windows. If SURF_SOCKET is set, the browser-launched host and the shell running surf must use the same value.
Remote clients require a per-client credential; Tailnet reachability alone is not authorization. On the POSIX browser host, authorize the client before installing the listener:
surf remote authorize agent-macbook --output ~/agent-macbook.surf-credential.json
surf install <extension-id> --listen 100.101.102.103:4321
surf remote listMove the mode-0600 credential to the client through a secure channel. It grants full trusted Surf authority. Use it explicitly or through SURF_REMOTE and SURF_REMOTE_CREDENTIAL:
surf --remote 100.101.102.103:4321 \
--remote-credential ~/.config/surf/agent-macbook.json \
page.read
surf remote revoke agent-macbook # Run on the browser hostRemote paths are client-local by default. local:./file is explicit client-local syntax; only remote:/absolute/path accesses the browser host directly. Remote transfer supports one upload or ChatGPT/Gemini input and one screenshot, network-export, or Gemini image output. Limits are 256 MiB per file, 512 MiB and 32 files per connection, and 256 KiB decoded chunks. record, aistudio.build, smoke screenshot directories, directories, and multi-file inputs are not supported remotely. Successful action screenshots and failure --auto-capture diagnostics are transferred back to client-local paths.
surf --help # Full help
surf <group> # Group help (tab, scroll, page, wait, dialog, emulate, form, perf, ai)
surf --help-full # All commands
surf --find <term> # Search tools
surf --help-topic <topic> # Topic guide (refs, semantic, frames, devices, windows)# 1. Navigate to page
surf navigate "https://example.com"
# 2. Read page to get element refs
surf page.read
# 3. Click by ref or coordinates
surf click --ref "e1"
surf click --x 100 --y 200
# 4. Type text
surf type --text "hello"
# 5. Full-page screenshot
surf screenshot --full-page --output /tmp/shot.png
# Inspect animation/style changes as JSON
surf animate-audit --selector ".thing" --duration 2000 --fps 10Query AI models using your browser's logged-in session. Must be logged into the respective service in Chrome.
surf chatgpt "explain this code"
surf chatgpt "summarize" --with-page # Include current page context
surf chatgpt "review" --model gpt-5.5 # Specify model
surf chatgpt "analyze" --file document.pdf # With file attachmentUse surf chatgpt for quick one-shot questions. Use surf oracle for long-running or Pro coding consults that need a durable job, explicit model and effort selection, file context, recovery, or follow-up turns. Oracle is local-only.
For agent workflows, detach after dispatch and keep the returned .id:
surf oracle ask "Review this change and identify release risks" \
--files "src/**/*.ts" --files "package.json" \
--model gpt-5.5 --effort pro --detach --json
surf oracle status <job-id> --json
surf oracle result <job-id> --json
# Or let Surf keep polling until capture:
surf oracle result <job-id> --wait --jsonstatus reads persisted state without touching Chrome. result attempts to harvest the answer and returns the job object with response once its state is captured. A Ctrl-C during waiting exits with status 130 and prints Recover with: surf oracle result <id>. Once the job is awaiting, the persisted ChatGPT conversation URL is its durable key, so surf oracle result <id> can recover after CLI exit, native-host restart, or Chrome restart by reopening that conversation.
Treat Pro quota as scarce. Oracle never selects Pro implicitly; request it with --model pro or --effort pro. ChatGPT model aliases include instant, thinking, pro, gpt-5.5, and gpt-5.6-sol. Accepted --effort values are light, standard, extended, heavy, and pro. Requested model and effort selections are read back before submission, and an unverifiable selection fails with model_verification_failed instead of silently continuing. Capacity is one non-terminal oracle job. A capacity error includes the in-flight job ID; poll that job or wait for it to finish rather than submitting the same consult again.
When loaded as a Pi extension, Surf also registers a surf-oracle external-job provider when the runtime exposes that bridge. The provider maps start, status, result, reattach, and follow to durable Surf Oracle jobs. It returns the conversation URL, requested and verified model and effort, prompt digest, result text, and failure details. reattach only harvests an existing job by ID; it never submits the prompt again.
Context comes from repeatable --files globs. Surf fails closed when a glob matches nothing or a matched file is unreadable, binary, or invalid UTF-8. It also blocks gitignored files and basenames matching .env*, *.pem, *.key, id_rsa*, id_ed25519*, *.p12, *.pfx, credentials*, or secrets*. Use --allow-sensitive only after intentionally reviewing those files; it overrides the block rather than redacting content. Context up to 60,000 evidence characters is inserted inline, while larger context becomes one private text attachment. The assembly manifest records each path, byte count, SHA-256, inline or bundle disposition, and deny-list outcome.
Continue a captured consult with follow. Use the ID returned by each turn for the next turn:
surf oracle follow <job-id> "Challenge your recommendation. What could invalidate it?" --detach --json
surf oracle result <follow-job-id> --wait --json
surf oracle follow <follow-job-id> "Give the final decision and concrete next steps." --detach --jsonsurf gemini "explain quantum computing"
surf gemini "summarize" --with-page # Include page context
surf gemini "analyze" --file data.csv # Attach file
surf gemini "a robot surfing" --generate-image /tmp/robot.png
surf gemini "add sunglasses" --edit-image photo.jpg --output out.jpg
surf gemini "summarize" --youtube "https://youtube.com/..."
surf gemini "hello" --model gemini-3.5-flash # Models: gemini-3.1-pro (default), gemini-3.5-flash, gemini-3.1-flash-lite
surf gemini "wide banner" --generate-image /tmp/banner.png --aspect-ratio 16:9surf perplexity "what is quantum computing"
surf perplexity "explain this page" --with-page # Include page context
surf perplexity "deep dive" --mode research # Research mode (Pro)
surf perplexity "latest news" --model sonar # Model selection (Pro)surf grok "what are the latest AI trends on X" # Search X posts
surf grok "analyze @username recent activity" # Profile analysis
surf grok "summarize this page" --with-page # Include page context
surf grok "find viral AI posts" --deep-search # DeepSearch mode
surf grok "quick question" --model fast # Models: auto, fast, expert, grok-4.20-betaFor exhaustive, multi-angle X research with categorized findings and full post-URL traceability, use the deep-x-research skill (skills/deep-x-research/) instead of a single Grok query.
Grok Validation & Troubleshooting:
# Validate Grok UI and check available models (no query sent)
surf grok --validate
# If models changed, save discovered models to surf.json config
surf grok --validate --save-modelssurf aistudio "explain quantum computing"
surf aistudio "redteam this" --with-page # Include current page context
surf aistudio "quick answer" --model gemini-3-flash-preview # Model selection
surf aistudio "analyze" --timeout 600 # Custom timeout (default: 300s)Why AI Studio over Gemini? AI Studio gives access to less restricted Gemini models. For Gemini 3 Pro the difference can be significant with certain prompts. Downside: aggressive per-day rate limits on Pro and Flash models.
Model selection is best-effort: Pass any AI Studio model id (e.g. gemini-3.1-pro-preview, gemini-3-flash-preview, gemini-flash-lite-latest). If the model isn't found, AI Studio uses whatever model was last selected in the UI.
surf aistudio.build "build a portfolio site"
surf aistudio.build "todo app" --model gemini-3.1-pro-preview # Model override
surf aistudio.build "crm dashboard" --output ./out # Extract zip to directory
surf aistudio.build "game" --keep-open --timeout 600 # Keep tab open, 10min timeoutAutomates AI Studio's App Builder at aistudio.google.com/apps. Types your prompt, clicks Build, waits for completion, downloads the generated zip, and optionally extracts it.
--output <dir> extracts the zip to a directory--model <id> overrides the model in Advanced Settings--timeout <seconds> build timeout (default: 600s)--keep-open leaves the AI Studio tab open after completionReturns zipPath, extractedPath, model, buildDuration, and tookMs.
When AI queries fail, check these common issues:
surf grok --validate to checkDebugging workflow for agents:
# 1. Check if the service is accessible and UI is valid
surf grok --validate
# 2. If models mismatch, update the local settings
surf grok --validate --save-models
# 3. Retry with explicit model name from validation output
surf grok "query" --model <model-from-validation>
# 4. If still failing, try with longer timeout
surf grok "query" --timeout 600surf tab.list
surf tab.new "https://google.com"
surf tab.switch 12345
surf tab.close 12345
surf tab.move 12345 --to-window 67890
surf tab.reload # Reload current tab
# Named tabs (aliases)
surf tab.name myapp # Name current tab
surf tab.switch myapp # Switch by name
surf tab.named # List named tabs
surf tab.unname myapp # Remove name
# Tab groups
surf tab.group # Create/add to tab group
surf tab.ungroup # Remove from group
surf tab.groups # List all tab groupssurf window.list # List all windows
surf resize 1280 720 # Resize current browser window
surf resize 1280 # Set current window width only
surf window.list --tabs # Include tab details
surf window.new # New window
surf window.new --url "https://example.com" # New window with URL
surf window.new --incognito # New incognito window
surf window.new --unfocused # Don't focus new window
surf window.focus 12345 # Focus window by ID
surf window.close 12345 # Close window
surf window.resize --id 123 --width 1920 --height 1080
surf window.resize --id 123 --state maximized # States: normal, minimized, maximized, fullscreenMulti-agent isolation:
# Create a separate window for one agent and keep using its ID
surf window.new "https://example.com"
surf --window-id 123 tab.list
surf --window-id 123 go "https://other.com"
# Pin work to a specific tab, or name it for easier handoff
surf read --tab-id 456
surf tab.name agent-a --tab-id 456
surf tab.switch agent-aUse window.new, --window-id, --tab-id, and named tabs to keep parallel agents on separate targets. Surf serializes non-streaming browser CLI requests per socket with a file-based lock, so agents sharing one native host wait instead of interleaving commands. Use --no-lock only for intentional bypasses. For hard isolation, run separate browser/profile instances with separate native hosts and SURF_SOCKET values; each socket gets its own lock. Surf does not yet have session.new, session IDs, or independent per-agent CDP sessions.
# CDP method (real events) types at the current focus
surf type --text "hello"
surf click --x 100 --y 200
# Selector/ref targets use frame-aware DOM input
surf type "hello" --into "#input"
surf type "hello" --ref e5
# Keys
surf key Enter
surf key "cmd+a"
surf key.repeat --key Tab --count 5 # Repeat key presses
# Hover and drag
surf hover --ref e5
surf drag --from-x 100 --from-y 100 --to-x 200 --to-y 200surf page.read # Accessibility tree with refs + page text
surf page.read --no-text # Interactive elements only (no text content)
surf animate-audit --selector ".thing" --duration 2000 --fps 10 # JSON animation timeline
surf page.read --ref e5 # Get specific element details
surf page.read --depth 3 # Limit tree depth
surf page.read --compact # Minimal output for LLM efficiency
surf page.read --max-bytes 2000 # Cap visible text at a UTF-8 byte boundary
surf page.text # Plain text content only
surf page.html --strip-scripts # Rendered HTML without scripts
surf page.save --selector "#artifact" --strip-scripts --output page.html # Save one static element
surf page.state # Modals, loading state, scroll infoUse page.html when the user wants a static copy of the current rendered DOM. This works for Claude artifact pages and ordinary web pages.
# Save the active page as HTML.
surf page.save --output page.html
# Save a Claude artifact or other preview page after it loads, without scripts.
surf wait.dom --stable 500
surf page.html --selector "#artifact" --strip-scripts > artifact.htmlUse --selector <css> to export its matching element only. A selector miss fails with an error. --strip-scripts removes scripts from exported markup without changing the page. Without --selector, page.html exports the whole document with its doctype. page.html exports the selected frame when frame.switch is active. Use page.read first when you need refs or visible text.
Find and act on elements by role, text, or label instead of refs:
# Find by ARIA role
surf locate.role button --name "Submit" --action click
surf locate.role textbox --name "Email" --action fill --value "test@example.com"
surf locate.role link --all # Return all matches
# Find by text content
surf locate.text "Sign In" --action click
surf locate.text "Accept" --exact --action click
# Find form field by label
surf locate.label "Username" --action fill --value "john"
surf locate.label "Password" --action fill --value "secret"Actions: click, fill, hover, text (get text content)
surf search "login" # Find text in page
surf search "Error" --case-sensitive # Case-sensitive
surf search "button" --limit 5 # Limit results
surf find "login" # Alias for searchsurf element.styles e5 # Get computed styles by ref
surf element.styles ".card" # Or by CSS selector
# Returns: font, color, background, border, padding, bounding boxsurf scroll down 800 # Scroll down 800px
surf scroll up 400 # Scroll up 400px
surf scroll bottom # Scroll to bottom
surf scroll top # Scroll to top
surf scroll.bottom # Dot command form also works
surf scroll.top
surf scroll.to --ref e5 # Scroll element into view
surf scroll.info # Get scroll positionsurf wait 2 # Wait 2 seconds
surf wait.element ".loaded" # Wait for element
surf wait.network # Wait for network idle
surf wait.url "/success" # Wait for URL pattern
surf wait.dom --stable 100 # Wait for DOM stability
surf wait.load # Wait for page load completesurf dialog.info # Get current dialog type/message
surf dialog.accept # Accept (OK)
surf dialog.accept --text "response" # Accept prompt with text
surf dialog.dismiss # Dismiss (Cancel)# Network throttling
surf emulate.network slow-3g # Presets: slow-3g, fast-3g, 4g, offline
surf emulate.network reset # Disable throttling
# CPU throttling
surf emulate.cpu 4 # 4x slower
surf emulate.cpu 1 # Reset
# Device emulation (19 presets)
surf emulate.device "iPhone 14"
surf emulate.device "Pixel 7"
surf emulate.device --list # List available devices
# Custom viewport
surf emulate.viewport --width 1280 --height 720
surf emulate.touch --enable # Enable touch emulation
# Geolocation
surf emulate.geo --lat 37.7749 --lon -122.4194
surf emulate.geo --clearsurf page.read # Get element refs first
# Fill by ref
surf form.fill --data '[{"ref":"e1","value":"John"},{"ref":"e2","value":"john@example.com"}]'
# Checkboxes: true/false
surf form.fill --data '[{"ref":"e7","value":true}]'
# Dropdown selection
surf select e5 "Option A" # By value (default)
surf select e5 "Option A" "Option B" # Multi-select
surf select e5 --by label "Display Text" # By visible label
surf select e5 --by index 2 # By index (0-based)surf upload --ref e5 --files "/path/to/file.txt"
surf upload --ref e5 --files "/path/file1.txt,/path/file2.txt"surf frame.list # List frames with IDs
surf frame.switch "FRAME_ID" # Switch to iframe context
surf frame.main # Return to main frame
surf frame.js --id "FRAME_ID" --code "return document.title"
# After frame.switch, subsequent commands target that frame:
surf frame.switch "iframe-1"
surf page.read # Reads iframe content
surf click e5 # Clicks in iframe
surf frame.main # Back to main pagesurf network # List captured requests
surf network --stream # Real-time network events
surf network.get --id "req-123" # Full request details
surf network.body --id "req-123" # Get response body
surf network.curl --id "req-123" # Generate curl command
surf network.origins # List origins with stats
surf network.stats # Capture statistics
surf network -vv --body-mode text --per-body-bytes 65536
surf network.export --har --output ./trace.har
surf network.clear # Clear captured requestsResponse-body capture supports none, text, and all modes plus per-body and per-tab-session byte caps. HAR exports carry body completeness metadata. Persistent network state is private under ~/.surf/state/network/ by default; configure SURF_NETWORK_PATH in the native host environment to change it.
surf console # Get console messages
surf console --stream # Real-time console
surf console --stream --level error # Errors onlysurf js "return document.title"
surf js "document.querySelector('.btn').click()"surf perf.metrics # Current metrics snapshot
surf perf.start # Start trace
surf perf.stop # Stop and get resultssurf screenshot # Auto-saves to /tmp/surf-snap-*.png
surf screenshot --output /tmp/shot.png # Save to specific file
surf screenshot --selector ".card" # Element only
surf screenshot --full-page # Full page scroll capture
surf screenshot --full-page /tmp/full.png # Full page saved to path
surf screenshot --no-save # Return base64 only, don't save filesurf zoom # Get current zoom level
surf zoom 1.5 # Set zoom to 150%
surf zoom 1 # Reset to 100%surf cookie list # List cookies for current page
surf cookie list --domain .google.com
surf cookie set --name "token" --value "abc123"
surf cookie get "token"
surf cookie clear --all # Clear all cookies
surf cookie delete "token" # Clear one cookiesurf history --query "github" --max 20
surf bookmarks --query "docs"
surf bookmark.add --url "https://..." --title "My Bookmark"
surf bookmark.removesurf health --url "http://localhost:3000"
surf smoke --urls "http://localhost:3000" "http://localhost:3000/about"
surf smoke --urls "..." --screenshot /tmp/smokeExecute multi-step browser automation as a single command with smart auto-waits.
# Pipe-separated commands
surf do 'go "https://example.com" | click e5 | screenshot'
# Multi-step login flow
surf do 'go "https://example.com/login" | type "user@example.com" --selector "#email" | type "pass" --selector "#password" | click --selector "button[type=submit]"'
# Validate without executing
surf do 'go "url" | click e5' --dry-runSave workflows as JSON files in ~/.surf/workflows/ (user) or ./.surf/workflows/ (project):
# List available workflows
surf workflow.list
# Show workflow details
surf workflow.info my-workflow
# Run by name with arguments
surf do my-workflow --email "user@example.com" --password "secret"
# Validate workflow file
surf workflow.validate workflow.json{
"name": "Login Flow",
"description": "Automate login process",
"args": {
"email": { "required": true },
"password": { "required": true },
"url": { "default": "https://example.com/login" }
},
"steps": [
{ "tool": "navigate", "args": { "url": "%{url}" } },
{ "tool": "type", "args": { "text": "%{email}", "selector": "input[name=email]" } },
{ "tool": "type", "args": { "text": "%{password}", "selector": "input[name=password]" } },
{ "tool": "click", "args": { "selector": "button[type=submit]" } },
{ "tool": "screenshot", "args": {}, "as": "result" }
]
}{
"steps": [
// Capture step output for later use
{ "tool": "js", "args": { "code": "return [1,2,3]" }, "as": "items" },
// Fixed iterations
{ "repeat": 5, "steps": [
{ "tool": "click", "args": { "ref": "e5" } }
]},
// Iterate over array
{ "each": "%{items}", "as": "item", "steps": [
{ "tool": "js", "args": { "code": "console.log('%{item}')" } }
]},
// Repeat until condition
{ "repeat": 20, "until": { "tool": "js", "args": { "code": "return done" } }, "steps": [...] }
]
}--file, -f <path> # Load from JSON file
--dry-run # Parse and validate without executing
--on-error stop|continue # Error handling (default: stop)
--step-delay <ms> # Delay between steps (default: 100, 0 to disable)
--no-auto-wait # Disable automatic waits
--json # Structured JSON outputAuto-waits: Commands automatically wait for completion:
go, back, forward) → waits for page loadWhy use do? Instead of 6-8 separate CLI calls with LLM orchestration between each, a workflow executes deterministically. Faster, cheaper, and more reliable.
Use surf do for a direct command sequence. Use a playbook for a reusable site capability with provenance, browser-session network execution, workflow fallback, and write-safety policy.
surf playbook list
surf pb show page
surf pb ops page
surf use page read --jsonResolution order is project (./.surf/playbooks/), user (~/.surf/playbooks/), then built-in. Provider compatibility commands stay on their validated command paths until provider playbooks have real login-flow validation. A write op requires --write; Surf records semantic intent before dispatch so a timeout or concurrent retry cannot silently double-submit.
Author from redacted recent activity when it contains only read/navigation behavior, or use an explicit record for richer evidence:
surf pb suggest --since 1h
surf pb save example --op read --from-recent 1h
surf pb record start example --op read --network --watch
surf pb record mark "loaded results"
surf pb record stop --draft
surf pb save --from-record <record-id>
surf pb trace export --from-record <record-id> --har ./trace.har
surf pb export example --out ./example-playbook
surf pb import ./example-playbookRecords, trace slices, receipts, and the bounded activity journal are private Surf state. Inputs and authentication headers are redacted by default. Use --include-input-values only when the saved values are necessary and acceptable.
Client projections replay a validated read endpoint and never embed captured browser credentials:
surf pb client derive example --op read --from-record <record-id> --request-id <request-id> --out ./client
surf pb client export example --op read --out ./client
surf pb client verify ./client# Auto-capture screenshot + console on failure
surf wait.element ".missing" --auto-capture --timeout 2000
# Saves to /tmp/surf-error-*.png--tab-id <id> # Target specific tab
--window-id <id> # Target specific window
--json # Raw JSON output
--auto-capture # Screenshot + console on error
--timeout <ms> # Override default timeout--method jstab.name app then tab.switch app--auto-capture saves diagnostics on failuresurf grok --validate if queries fail to check UI changessurf aistudio gives less filtered responses than surf gemini for the same modelssurf do for multi-step tasks - Reduces token overhead and improves reliabilitysurf do '...' --dry-run validates without executingwindow.new + --window-id or --tab-id to keep agent work separate from your browsing--no-lock only when you intentionally want to bypass itsurf doctor or surf doctor --browser all before guessing at reinstall stepssurf page.html > artifact.html to save Claude artifacts or any rendered page as static HTMLsurf record --duration 2000 --fps 10 --output /tmp/anim.gif when the agent needs to see motion; use animate-audit for numeric timelines and perf-audit for jank/layout-shift snapshotsSURF_SOCKET values when agents must not share a host or targetlocate.role, locate.text, locate.label for more robust element findingframe.switch before interacting with iframe contentFor programmatic access:
echo '{"type":"tool_request","method":"execute_tool","params":{"tool":"tab.list","args":{}},"id":"1"}' | nc -U /tmp/surf.sock© w-winter, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 1 other file in skills/surf of w-winter/dot314.
Open the folder on GitHubat commit 0c6bbc7
We found 1 copy of this SKILL.md (exact, near-identical or edited) in other folders, from 1 other GitHub owner. This page covers the copy in w-winter/dot314, which our catalogue first saw on October 7, 2026.
Surf 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 |
|---|---|---|---|---|---|---|
| Surf this skillw-winter/dot314 | 139 | 1 repos | ~7.6k | Automated safety check: Warn | MIT | |
| Council Executionhex/claude-council | 848 | — | ~824 | Automated safety check: Pass | MIT | |
| Scrapingbee CLIScrapingBee/scrapingbee-cli | 108 | — | ~3.2k | Automated safety check: Notes | MIT | |
| Conversation Archivegarrytan/gbrain | 31k | — | ~5.6k | Automated safety check: Pass | MIT | |
| Browse Nownowledge-co/community | 185 | — | ~619 | Automated safety check: Pass | None | |
| Browser NavigationFactory-AI/factory-plugins | 110 | — | ~2.7k | Automated safety check: Pass | None |
hex/claude-council
Executes council queries by running the query pipeline across selected AI providers (Gemini, OpenAI, Grok, Perplexity), displaying formatted responses verbatim, and generating a synthesis of…
ScrapingBee/scrapingbee-cli
Fetch and read any web page, search the web, crawl a site, or pull structured data out of pages.
garrytan/gbrain
Import AI-assistant chat exports (ChatGPT, Claude, Perplexity) and agent session transcripts into the brain as one dated page per conversation under conversations/, validate each page against the…
nowledge-co/community
Control the user's actual browser through the browse-now CLI when a task needs authenticated pages, dynamic interaction, form filling, screenshots, or other browser automation that web search cannot…
Factory-AI/factory-plugins
Automate browser interactions for web testing, form filling, screenshots, and data extraction.
onvoyage-ai/gtm-engineer-skills
Researches what prompts people ask AI engines (ChatGPT, Gemini, Perplexity, Claude) about a product category and produces a prompts.csv artifact — a prioritized, strictly-schema'd list of the…
w-winter/dot314
Refresh RepoPrompt tool guidance when the CLI/MCP surface changes.
w-winter/dot314
Deep, exhaustive research on a topic across X (Twitter) by driving Grok (x.com/i/grok) through surf.
w-winter/dot314
Search indexed text corpora with qmd. An agent skill from w-winter/dot314.
w-winter/dot314
Review prose written for others (e.g., user-facing documentation, prompts for other LLMs, reports, plans, inline comments, docstrings) for local jargon leakage, orphaned references, missing…
w-winter/dot314
Always read this skill when the user mentions "rp" or "repoprompt", or before accessing a repository outside the current RepoPrompt workspace.
w-winter/dot314
Build/test Xcode projects via the XcodeBuildMCP MCP server using a local CLI wrapper for pi (no MCP support).
Works with
Control Chrome browser via CLI for testing, automation, and debugging. Surf is an agent skill from w-winter/dot314. Control Chrome browser via CLI for testing, automation, and debugging.
Surf fits situations like: the user needs browser automation; page inspection; network/CPU emulation; devTools streaming.
Run `npx skills add w-winter/dot314 --skill surf -a claude-code`. Or copy the skill folder (skills/surf in w-winter/dot314) into .claude/skills/surf in your project. Claude Code loads it when a task matches its description.
Run `npx skills add w-winter/dot314 --skill surf -a codex`. Or copy the skill folder (skills/surf in w-winter/dot314) into .agents/skills/surf 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 w-winter/dot314 --skill surf -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/surf, .gemini/skills/surf, .github/skills/surf and .opencode/skills/surf in your project.
SKILL.md names no scripts, command-line tools or credentials: Surf is instructions for the agent only.
SKILL.md names 3 domains. In commands or code: youtube.com, google.com and other.com; the agent is likely to contact these when it follows the instructions. This is read from the text; nothing was executed.
Our automated static check of SKILL.md flagged 1 warning(s): mentions a credentials file (ssh keys, cloud or package-manager tokens). Read the flagged lines before installing; the check is not a guarantee either way.
Surf is published under the MIT licence (from the LICENSE file in the skill folder). It allows redistribution, so the full SKILL.md is shown on this page.
About 7.6k tokens (SKILL.md is roughly 30k 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 Surf: Council Execution (hex/claude-council, 848 stars), Scrapingbee CLI (ScrapingBee/scrapingbee-cli, 108 stars), Conversation Archive (garrytan/gbrain, 31k stars) and Browse Now (nowledge-co/community, 185 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
w-winter (a GitHub user) maintains it in w-winter/dot314, which has 139 GitHub stars. The repository holds 7 skills in this directory. The repository was last updated on October 7, 2026.
Source: w-winter/dot314 on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.