⚠️ DisclaimerClausy is experimental software. Use it at your own risk.
Automating web-based AI services may violate the terms of service of those providers. The author takes no responsibility for account bans, data loss, or any other consequences resulting from the use of this software.
Clausy is an OpenAI-compatible LLM proxy that lets agent frameworks like OpenClaw talk to browser-based AI systems like ChatGPT, xAi, Gemini and Claude.
It exposes a standard OpenAI API while internally routing requests to browser-based LLM interfaces using Playwright and Chrome DevTools.
This allows tools that expect an OpenAI API (for example OpenClaw) to work with web-based AI systems without API access.
Many powerful AI systems are only accessible through web interfaces, while developer tools and agent frameworks expect a stable API.
Clausy bridges that gap.
It translates between:
- OpenAI-compatible APIs used by tools and agents
- browser-based AI interfaces used by modern LLM services
This enables systems that are independent of any single AI provider.
OpenClaw, OpenClaw proxy, OpenAI-compatible proxy, LLM proxy, ChatGPT, Claude, Grok, Gemini, openAI, Anthropic, xAi, Google, browser gateway, AI agents
Client / Agent (OpenClaw)
│
│ OpenAI API
▼
┌─────────────────┐
│ Clausy │
│ LLM Gateway │
└────────┬────────┘
│
│ Playwright + CDP
▼
┌───────────────┐
│ Browser LLMs │
│ ChatGPT │
│ Claude │
│ Gemini (soon) │
└───────────────┘
Clausy behaves like a normal LLM server externally but internally communicates with browser-based AI interfaces.
- OpenAI-compatible endpoint:
POST /v1/chat/completions - streaming responses (SSE)
- tool-call passthrough
- tool-call user notification (e.g.
Running tool: exec (ls -la)) - per-session browser tabs (
X-Clausy-Sessionheader) - secret filtering and leak prevention
- provider abstraction layer (ChatGPT + Claude + Grok + Gemini web providers)
Example tool-call notification:
Running tool: exec (ls -la)
Implemented:
- ChatGPT Web
- Claude Web
- Grok Web
- Gemini Web
Implemented:
- Perplexity
- Poe
- DeepSeek Web
Clausy exposes an OpenAI-compatible API to clients.
Internally it communicates with browser LLMs using a simple text-vs-tool-call protocol:
User-facing text is emitted as plain text only:
plain text response (streamed)
Tool execution is emitted as exactly one fenced tool call block:
```tool call
exec {"command": "ls -la"}
```
Clausy parses that block and converts it into standard OpenAI/OpenClaw tool_calls JSON before returning it to the client.
Generated tool_calls[].function.arguments are always a JSON-encoded object string.
Legacy <<<CONTENT>>> / <<<TOOLS>>> marker output is still accepted for compatibility, but new prompts instruct providers not to use it.
⚠️ Experimental. Browser UIs change often. Use at your own risk.
- Python 3.10+
- Playwright
- a logged-in browser session for the target LLM
Clausy now performs runtime browser detection and startup:
- tries existing CDP endpoint first (
CLAUSY_CDP_HOST/CLAUSY_CDP_PORT) - if unavailable, bootstraps Chrome/Chromium automatically by default (
CLAUSY_BROWSER_BOOTSTRAP=auto) - if no usable Chrome/Chromium binary is found during bootstrap, attempts a one-time
python -m playwright install chromiumfallback (disable withCLAUSY_BROWSER_AUTO_INSTALL=0) - supports explicit binary override with
CLAUSY_BROWSER_BINARY
One-line bootstrap (recommended):
curl -fsSL https://raw.githubusercontent.com/chloe-awakes/clausy/main/install.sh | bashDocker-mode install (keeps OpenClaw provider base URL on 3108):
curl -fsSL https://raw.githubusercontent.com/chloe-awakes/clausy/main/install.sh | bash -s -- --dockerWhat this means:
- local/native Clausy (
python -m clausy) listens on127.0.0.1:3108 - Docker/Compose deployments should publish container port
5000to host port3108(for example-p 127.0.0.1:3108:5000) - the installer always wires OpenClaw to
http://127.0.0.1:3108/v1unless--base-urlis explicitly set - the installer also configures and auto-starts a per-user background service by default:
- macOS:
~/Library/LaunchAgents/com.clausy.gateway.plist - Linux:
~/.config/systemd/user/clausy.service
- macOS:
- installer now attempts a global
clausycommand shim (symlink to.venv/bin/clausy) in standard PATH locations, preferring/usr/local/binand falling back across/opt/homebrew/bin,/usr/bin, and~/.local/bin - if global shim locations are not writable, interactive installs offer an optional sudo retry; fallback remains shell-rc PATH update
- on interactive installs (TTY), the installer prompts for:
- preferred provider (persisted via
clausy provider ...) - optional Playwright Chromium fallback install (
Install Chromium fallback now? [y/N], default: No) - optional shell PATH update (
Add Clausy to PATH in shell rc? [y/N]) with duplicate-safe append for bash/zsh/fish, but only when a global shim was not installed into an existing PATH directory
- preferred provider (persisted via
- in non-interactive mode (e.g. curl pipes, CI), prompts are skipped, shim setup is best-effort only (no sudo/prompt hang), and defaults stay unchanged
- on first local interactive install, the installer opens the selected provider URL inside the Clausy-managed Playwright/Chrome instance via managed navigation (
page.goto) so you can log in once; this is one-time and then skipped on later reinstalls - strict policy: provider navigation in this first-run flow is managed-browser only (no OS URL-opener fallback path)
- after install/setup steps, installer now verifies
http://127.0.0.1:3108/health(configurable viaCLAUSY_HEALTH_ENDPOINT); if down, it performs one bounded auto-repair cycle (clausy stop,clausy start, retry health), then prints either explicit runtime-health success (pid/port/endpoint) or exact next commands
Re-running the installer updates the service definition and restarts it cleanly.
- macOS:
launchctl list | grep com.clausy.gateway ; curl -s http://127.0.0.1:3108/health - Linux:
systemctl --user status clausy --no-pager ; curl -s http://127.0.0.1:3108/health
Skip service setup when needed (CI/minimal/container environments):
curl -fsSL https://raw.githubusercontent.com/chloe-awakes/clausy/main/install.sh | bash -s -- --no-serviceSkip first-run browser auto-open:
curl -fsSL https://raw.githubusercontent.com/chloe-awakes/clausy/main/install.sh | bash -s -- --no-browserModule bootstrap alternative:
python -m clausy.installEquivalent manual steps:
python -m venv .venv
source .venv/bin/activate
pip install -U pip
pip install -e '.[dev]'
playwright install chromiumrequirements.txt is kept as a convenience mirror of the canonical dependencies in pyproject.toml.
clausy status # runtime snapshot
clausy config # show effective config (env > file > defaults)
clausy start # start Clausy in background with current config (opens configured provider page on browser startup)
clausy stop # stop running Clausy service/process (safe if not running)
clausy chrome # start in visible Chrome mode (also opens configured provider page on browser startup)With no args, clausy prints status plus concise usage help (it does not start the server).
clausy headless
clausy headless off
clausy bootstrap always
clausy provider claude
clausy port 3110
clausy auto-install on
clausy novnc offSupported direct settings: headless, bootstrap, provider, port, auto-install, novnc.
This creates an isolated Chrome profile in ./profile (DO NOT commit it).
open -na "Google Chrome" --args \
--remote-debugging-port=9200 \
--user-data-dir=./profile \
--no-first-run \
--no-default-browser-check \
--disable-session-crashed-bubbleLog in to the desired AI service once.
python -m clausyDefaults:
- API:
http://127.0.0.1:3108 - Provider: ChatGPT Web (
CLAUSY_PROVIDER=chatgpt)
- Liveness:
GET /health - Readiness:
GET /ready
Example:
curl -s http://127.0.0.1:3108/health | jq
curl -s http://127.0.0.1:3108/ready | jqContainer startup now uses strict runtime precedence:
- Attempt host-browser launch path first (outside container) and probe configured CDP endpoint.
- If host launch/probe fails, fallback to local in-container Chromium and continue.
Container startup still uses Xvfb + openbox to provide a Docker-compatible headful display for local Chromium CDP mode.
Run host Chrome with remote debugging (example on macOS host):
open -na "Google Chrome" --args \
--remote-debugging-address=0.0.0.0 \
--remote-debugging-port=9200 \
--user-data-dir="$HOME/.clausy-host-profile" \
--no-first-run \
--no-default-browser-check \
--disable-session-crashed-bubbleThen build and run the Clausy container (single command) with localhost-only API + noVNC:
docker build -t clausy . && docker run --rm \
-p 127.0.0.1:3108:5000 \
-p 127.0.0.1:6080:6080 \
--add-host=host.docker.internal:host-gateway \
-e CLAUSY_BIND=0.0.0.0 \
-e CLAUSY_PORT=5000 \
-e CLAUSY_CDP_HOST=host.docker.internal \
-e CLAUSY_CDP_PORT=9200 \
-e CLAUSY_BROWSER_BOOTSTRAP=auto \
-e CLAUSY_HOST_BROWSER_LAUNCH_CMD='true' \
-e CLAUSY_NOVNC_PORT=6080 \
-e CLAUSY_VNC_PORT=5900 \
-v "$(pwd)/profile:/app/profile" \
clausyCLAUSY_CHROME_NO_SANDBOX=1 is now baked into the Docker image by default, so no runtime -e CLAUSY_CHROME_NO_SANDBOX=1 flag is needed for container runs.
Notes:
- Open noVNC at
http://127.0.0.1:6080/vnc.html. ⚠️ noVNC currently has no auth. Keep it localhost-only (127.0.0.1:6080:6080) unless you add your own network controls.CLAUSY_HOST_BROWSER_LAUNCH_CMDis an optional best-effort command executed by container startup before probing CDP.- If omitted/unavailable, startup still probes
CLAUSY_CDP_HOST:CLAUSY_CDP_PORTthen falls back automatically.
If external host Chrome is unavailable, startup script launches local Chromium in-container with CDP flags (--remote-debugging-address/port, --user-data-dir) and proceeds.
You can force this path by setting an unreachable host endpoint (or by leaving host launch command unavailable) and keeping CLAUSY_BROWSER_BOOTSTRAP=auto.
docker compose up --buildCompose defaults target host Chrome first (host.docker.internal:9200) and retain in-container fallback capability automatically.
Compose also publishes localhost-only noVNC on 127.0.0.1:6080 (no auth; keep local-only).
Operational details: docs/runbook-browser-runtime.md.
Non-streaming (host endpoint defaults to port 3108 for both local and Docker-mapped setups):
curl http://127.0.0.1:3108/v1/chat/completions -H 'Content-Type: application/json' -H 'X-Clausy-Session: demo' -d '{
"model":"chatgpt-web",
"stream": false,
"messages":[{"role":"user","content":"Say hello in one sentence."}]
}'Streaming (SSE):
curl -N http://127.0.0.1:3108/v1/chat/completions -H 'Content-Type: application/json' -H 'X-Clausy-Session: demo' -d '{
"model":"chatgpt-web",
"stream": true,
"messages":[{"role":"user","content":"Explain Docker in 3 short sentences."}]
}'CLI-persisted config file:
~/.config/clausy/config.json- lifecycle pid file:
~/.config/clausy/clausy.pid(used byclausy start/stop) - Clausy-managed browser pid metadata:
~/.config/clausy/browser-bootstrap.pid(used soclausy stoponly terminates browser processes launched by Clausy itself)
Effective runtime precedence:
- Environment variables (
CLAUSY_*) - CLI-persisted config file (
~/.config/clausy/config.json) - Built-in server defaults
Environment variables:
CLAUSY_PORT(default3108)CLAUSY_BIND(default0.0.0.0)CLAUSY_PROVIDER(defaultchatgpt)CLAUSY_AUTO_MODEL_SWITCH(0|1, default1): auto-route each request by incoming model id (for exampleclaude-web→ Claude provider,openai-api→ OpenAI API provider)CLAUSY_FALLBACK_CHAIN(optional comma-separated provider names): ordered fallback providers to try when the selected provider fails (example:ollama,openai,openrouter)CLAUSY_COST_AWARE_ROUTING(0|1, default0): reorder primary+fallback candidates by configured provider cost (lowest first)CLAUSY_PROVIDER_COSTS(optional comma-separatedprovider:costmap): used when cost-aware routing is enabled (example:ollama:0.1,openai:2.0,openrouter:3.5)CLAUSY_CHATGPT_URL(defaulthttps://chatgpt.com)CLAUSY_CLAUDE_URL(defaulthttps://claude.ai)CLAUSY_GROK_URL(defaulthttps://grok.com)CLAUSY_GEMINI_WEB_URL(defaulthttps://gemini.google.com)CLAUSY_PERPLEXITY_URL(defaulthttps://www.perplexity.ai)CLAUSY_POE_URL(defaulthttps://poe.com)CLAUSY_DEEPSEEK_URL(defaulthttps://chat.deepseek.com)ALLOW_ANON_BROWSER(0|1, default1): when1, ChatGPT/Claude/Grok web providers attempt guest/unauth flow first and only return auth error when the page is actually login-blocked. Set to0to require authenticated sessions.CLAUSY_CDP_HOST(default127.0.0.1)CLAUSY_CDP_PORT(default9200)CLAUSY_PROFILE_DIR(default./profile)CLAUSY_PROFILE_BY_PROVIDER(optional comma-separatedprovider:pathmap): switch browser user-data profile automatically by selected web provider (example:chatgpt:./profile-chatgpt,claude:./profile-claude)CLAUSY_PROFILE_ROTATION_ENABLED(0|1, default0) enables anti-detection profile rotation for browser providersCLAUSY_PROFILE_ROTATION_COUNT(default0) number of rotating profile suffixes (<profile>-rot1..rotN); values0/1disable effective rotationCLAUSY_BROWSER_BOOTSTRAP(auto|always|never, defaultauto)CLAUSY_BROWSER_BINARY(optional absolute path to Chrome/Chromium binary)CLAUSY_BROWSER_AUTO_INSTALL(0|1, default1) allows one-time runtime fallback topython -m playwright install chromiumwhen no browser binary is detected during bootstrapCLAUSY_BROWSER_ARGS(optional extra browser args, space-separated)CLAUSY_CDP_CONNECT_TIMEOUT(seconds, default20; valid range0.1..300, invalid values fall back to default)CLAUSY_HOST_BROWSER_LAUNCH_CMD(optional; startup command executed in container before CDP probe, placeholders supported:{host}{port}{profile_dir})CLAUSY_CHROME_NO_SANDBOX(0|1, app default0; Docker image sets1by default)CLAUSY_HEADLESS(0|1, default0)CLAUSY_ENABLE_NOVNC(0|1, app default0; Docker image sets1by default; when enabled docker-start launches x11vnc + noVNC)CLAUSY_NOVNC_PORT(default6080)CLAUSY_VNC_PORT(default5900)CLAUSY_SESSION_HEADER(defaultX-Clausy-Session)CLAUSY_MAX_REPAIRS(default2)CLAUSY_RESET_TURNS(default20)CLAUSY_RESET_SUMMARY_MAX_CHARS(default1500)CLAUSY_BROWSER_RESTART_EVERY_RESETS(default0) restarts the browser connection after N conversation resets (0disables)CLAUSY_BROWSER_RESTART_EVERY_REQUESTS(default0) restarts the browser connection after N completed requests per session (0disables)CLAUSY_EVENT_LOG_ENABLED(0|1, default1) enables in-memory request/response event loggingCLAUSY_EVENT_LOG_MAX_ITEMS(default500) ring-buffer size for/v1/eventsCLAUSY_TOOL_PASSWORD(optional; when set, tool calls are only returned if password header matches)CLAUSY_TOOL_PASSWORD_HEADER(defaultX-Clausy-Tool-Password)CLAUSY_TOOL_PASSWORD_MESSAGE(defaultTool execution is password-protected. Provide a valid tool password to continue.)CLAUSY_BADWORD_FILTER_MODE(off|mask|block, defaultoff)CLAUSY_BADWORD_WORDS(comma-separated words, default empty)CLAUSY_BADWORD_REPLACEMENT(default[CENSORED])CLAUSY_BADWORD_BLOCK_MESSAGE(defaultContent blocked by safety filter.)CLAUSY_KEYWORD_ALERTS_ENABLED(1|0, default0)CLAUSY_KEYWORD_ALERTS_KEYWORDS(comma-separated keywords)CLAUSY_KEYWORD_ALERTS_CASE_SENSITIVE(1|0, default0)CLAUSY_KEYWORD_ALERTS_WINDOW_SECONDS(default300, bounded1..86400)CLAUSY_KEYWORD_ALERTS_MAX_PER_WINDOW(default1, bounded1..1000)CLAUSY_ALERT_TELEGRAM_BOT_TOKEN,CLAUSY_ALERT_TELEGRAM_CHAT_ID,CLAUSY_ALERT_TELEGRAM_API_BASECLAUSY_ALERT_EMAIL_SMTP_HOST,CLAUSY_ALERT_EMAIL_SMTP_PORT(bounded1..65535, default587),CLAUSY_ALERT_EMAIL_USERNAME,CLAUSY_ALERT_EMAIL_PASSWORD,CLAUSY_ALERT_EMAIL_FROM,CLAUSY_ALERT_EMAIL_TO,CLAUSY_ALERT_EMAIL_STARTTLS
Clausy can filter secrets in both directions:
- Outbound (before sending prompts to the web LLM UI)
- Inbound (before returning content/tool calls to the client)
Default mode is smart:
- Outbound: filters only known local secrets collected from ENV and (optionally)
~/.openclaw/** - Inbound: filters known local secrets plus hard patterns (private keys, Bearer tokens, JWT-like tokens)
Environment variables:
CLAUSY_FILTER_MODE=smart|both|outbound|off(default:smart)CLAUSY_FILTER_SCAN_OPENCLAW=1|0(default:1)CLAUSY_FILTER_SCAN_PATHS=~/.openclaw(comma-separated; default:~/.openclaw)CLAUSY_FILTER_MAX_BYTES=2000000CLAUSY_FILTER_MAX_TAIL=32768CLAUSY_FILTER_PREFIX_PATTERNS=1|0(optional paranoia mode)
Notes:
- Your browser profile is never scanned
- Clausy masks secrets like
abc…xyz.
If streaming tail exceeds CLAUSY_FILTER_MAX_TAIL, Clausy emits:
[FILTERED_MAX_TAIL_REACHED]
If a stream ends while holding more than half of a known secret prefix, Clausy emits:
[FILTERED_PARTIAL_SECRET_FLUSH]
Optional second-stage text filtering can mask or block configured words in outbound responses and web-search snippets.
Set:
CLAUSY_BADWORD_FILTER_MODE=off|mask|blockCLAUSY_BADWORD_WORDS=word1,word2,word3CLAUSY_BADWORD_REPLACEMENT=[CENSORED](mask mode)CLAUSY_BADWORD_BLOCK_MESSAGE=Content blocked by safety filter.(block mode)
Clausy can notify operators when configured keywords appear in user input, assistant output, or tool-call payloads.
Set:
CLAUSY_KEYWORD_ALERTS_ENABLED=1CLAUSY_KEYWORD_ALERTS_KEYWORDS=token,password,secretCLAUSY_KEYWORD_ALERTS_CASE_SENSITIVE=0CLAUSY_KEYWORD_ALERTS_WINDOW_SECONDS=300(bounded1..86400)CLAUSY_KEYWORD_ALERTS_MAX_PER_WINDOW=1(bounded1..1000)
Telegram channel:
CLAUSY_ALERT_TELEGRAM_BOT_TOKEN=...CLAUSY_ALERT_TELEGRAM_CHAT_ID=...CLAUSY_ALERT_TELEGRAM_API_BASE=https://api.telegram.org(optional)
Email channel:
CLAUSY_ALERT_EMAIL_SMTP_HOST=smtp.example.comCLAUSY_ALERT_EMAIL_SMTP_PORT=587(bounded1..65535)CLAUSY_ALERT_EMAIL_USERNAME=...CLAUSY_ALERT_EMAIL_PASSWORD=...CLAUSY_ALERT_EMAIL_FROM=clausy@example.comCLAUSY_ALERT_EMAIL_TO=ops@example.com,security@example.comCLAUSY_ALERT_EMAIL_STARTTLS=1
Alert transport failures are swallowed and logged so /v1/chat/completions responses are never blocked by notifier issues.
Set:
CLAUSY_PROVIDER=chatgpt
CLAUSY_PROVIDER=claude
CLAUSY_PROVIDER=grok
CLAUSY_PROVIDER=gemini_web
CLAUSY_PROVIDER=perplexity
CLAUSY_PROVIDER=poe
CLAUSY_PROVIDER=deepseek
Clausy can also proxy direct HTTP providers via OpenAI-compatible /v1/chat/completions.
Set one of:
CLAUSY_PROVIDER=openai
CLAUSY_PROVIDER=anthropic
CLAUSY_PROVIDER=ollama
CLAUSY_PROVIDER=gemini
CLAUSY_PROVIDER=openrouter
Required env vars:
- OpenAI:
CLAUSY_OPENAI_API_KEY, optionalCLAUSY_OPENAI_BASE_URL - Anthropic:
CLAUSY_ANTHROPIC_API_KEY, optionalCLAUSY_ANTHROPIC_BASE_URL - Ollama: optional
CLAUSY_OLLAMA_API_KEY, optionalCLAUSY_OLLAMA_BASE_URL(defaulthttp://127.0.0.1:11434) - Gemini:
CLAUSY_GEMINI_API_KEY, optionalCLAUSY_GEMINI_BASE_URL(defaulthttps://generativelanguage.googleapis.com/v1beta) - OpenRouter:
CLAUSY_OPENROUTER_API_KEY, optionalCLAUSY_OPENROUTER_BASE_URL(defaulthttps://openrouter.ai/api/v1), optionalCLAUSY_OPENROUTER_SITE_URL, optionalCLAUSY_OPENROUTER_APP_NAME
Notes:
- Non-stream responses are normalized into OpenAI Chat Completions JSON shape.
- Streaming responses are emitted as OpenAI-compatible SSE chunks (
data: ...,data: [DONE]). - Ollama mode targets native Ollama
/api/chatand normalizes to OpenAI-compatible responses. - Browser providers (
chatgpt,claude,grok,gemini_web,perplexity,poe,deepseek) are unchanged. - With
CLAUSY_AUTO_MODEL_SWITCH=1, Clausy can keep one default provider while automatically routing requests bymodel(chatgpt-web,claude-web,openai-api, etc.). - If
CLAUSY_FALLBACK_CHAINis set, Clausy retries providers in that order when the primary provider errors (first successful provider wins). - If
CLAUSY_COST_AWARE_ROUTING=1, Clausy reorders the candidate list (primary + fallback chain) byCLAUSY_PROVIDER_COSTSso cheaper providers are attempted first. - If
CLAUSY_PROFILE_BY_PROVIDERis configured, Clausy automatically switches browser profile directories when provider routing changes (for isolated sessions/cookies per provider). - If
CLAUSY_PROFILE_ROTATION_ENABLED=1andCLAUSY_PROFILE_ROTATION_COUNT>1, Clausy round-robins profile directories per provider (<base>-rot1..rotN) to reduce repeated fingerprint/session reuse. - If
CLAUSY_BROWSER_RESTART_EVERY_REQUESTSis set toN>0, Clausy restarts the browser connection automatically after every N completed requests per session (in addition toCLAUSY_BROWSER_RESTART_EVERY_RESETS).
Optional URLs:
CLAUSY_CHATGPT_URL=https://chatgpt.comCLAUSY_CLAUDE_URL=https://claude.aiCLAUSY_GROK_URL=https://grok.comCLAUSY_GEMINI_WEB_URL=https://gemini.google.comCLAUSY_PERPLEXITY_URL=https://www.perplexity.aiCLAUSY_POE_URL=https://poe.comCLAUSY_DEEPSEEK_URL=https://chat.deepseek.com
To inspect selectors:
python scripts/inspect_ui.py --provider claudeIf you use OpenClaw and want Clausy to be added as a provider automatically, run:
# installed CLI (recommended)
clausy-openclaw-install
# module form
python -m clausy.openclaw_install
# repo-local compatibility wrapper
python scripts/openclaw_install_clausy.pyThis will:
- add a
clausyprovider (default base URLhttp://127.0.0.1:3108/v1) - keep default base URL
http://127.0.0.1:3108/v1in both normal and--dockermode - allow explicit override with
--base-url(takes precedence over defaults) - register provider config using current OpenClaw schema (
models.providers.clausy.baseUrl+models[]) - set default primary to
agents.defaults.model.primary = "local/clausy" - keep existing config and create a timestamped backup before writing
Examples:
# local/default (wires OpenClaw to http://127.0.0.1:3108/v1)
clausy-openclaw-install
# docker mode (compatibility flag; still wires OpenClaw to http://127.0.0.1:3108/v1)
clausy-openclaw-install --docker
# explicit custom URL (overrides both defaults)
clausy-openclaw-install --base-url http://127.0.0.1:9000/v1Use --dry-run to preview changes.
- Your Chrome profile contains cookies and session data. Keep it private.
- This project automates third-party web UIs. Consider rate limits and account policies.
Run all tests offline:
.venv/bin/python -m pytest -qIf pytest/build are missing in your venv, install dev tooling first:
.venv/bin/python -m pip install -e '.[dev]'Run the full release gate (tests + targeted routing/provider checks + install/build smoke):
scripts/release-gate.shDocker API + noVNC smoke check (requires local Docker daemon):
bash scripts/smoke/docker-novnc-smoke.shRun grouped suites:
# API contract (stream/non-stream + tool-call shape)
.venv/bin/python -m pytest -q -m contract
# profanity + secret filtering behavior
.venv/bin/python -m pytest -q -m filtering
# provider routing behavior
.venv/bin/python -m pytest -q -m routingThese tests use local fixtures/test doubles and do not require browser login or network access.
GitHub Actions workflow: .github/workflows/ci.yml
It runs on pushes/PRs and performs:
- offline pytest suite
- package build (
python -m build) - import smoke check
VISION.mdROADMAP.md
MIT (see LICENSE).
Clausy includes a simple web-search proxy endpoint:
POST /v1/web_searchProviders:
brave(default): requiresBRAVE_SEARCH_API_KEYgoogle: requiresGOOGLE_CSE_API_KEYandGOOGLE_CSE_CX
Example:
curl http://127.0.0.1:3108/v1/web_search \
-H 'Content-Type: application/json' \
-d '{"q":"open source llm proxy","provider":"brave","count":5}'Notes:
- Clausy uses official HTTP APIs, not scraping.
Clausy supports web search via official APIs (recommended) and via browser UI scraping (best-effort).
POST /v1/web_search with mode="api" uses:
- Brave Search API (
provider="brave", requiresBRAVE_SEARCH_API_KEY) - Google Custom Search JSON API (
provider="google", requiresGOOGLE_CSE_API_KEYandGOOGLE_CSE_CX)
mode="browser" opens the provider website in the existing Chrome instance (CDP) and scrapes the results.
Providers:
provider="google_web"(scrapes Google Search results page)provider="brave_web"(scrapes Brave Search results page)
Example:
curl http://127.0.0.1:3108/v1/web_search \
-H 'Content-Type: application/json' \
-d '{"q":"open source llm proxy","mode":"browser","provider":"google_web","count":5}'Notes:
- Browser scraping is inherently less stable (DOM changes, consent screens).
- Respect provider terms and rate limits.
Clausy can expose a lightweight in-memory event feed for observability:
GET /v1/events?limit=100&since_id=0&session_id=<optional>Returns recent request / response / tool_call events from a ring buffer.
Use this for basic local monitoring and troubleshooting.
For grouped tool-chain visualization per completion request:
GET /v1/tool_chains?limit=50&since_id=0&session_id=<optional>Each chain is grouped by request_id and includes the ordered event timeline.
For flat tool execution traces (one item per tool_call event):
GET /v1/tool_traces?limit=100&since_id=0&session_id=<optional>Each trace includes request_id, tool_count, and structured calls with tool name + arguments excerpt.