* fix(ocp-connect): seed per-agent auth-profiles for OpenClaw multi-agent + UX hotfixes
Fixes#12. ocp-connect bumped to v1.1.0.
## What was broken
OpenClaw's per-agent auth loader reads <agentDir>/auth-profiles.json
(NOT the root openclaw.json's auth.profiles section, NOT env vars).
ocp-connect only wrote the root config, so OpenClaw multi-agent setups
- any agent with an explicit or implicit agentDir, including the
default `main` agent - silently failed with "No API key found for
provider X" on every Telegram/IDE message. The smoke test passed but
the user's actual workflow was broken.
3 unrelated UX papercuts compounded the bad experience:
* Smoke test only verified OCP direct connectivity, never the
IDE/agent -> OCP path, so the script printed "Smoke test passed"
while the bot was silently broken.
* `read ... </dev/tty 2>/dev/null || fallback` leaked
`Device not configured` errors from the parent shell in CI/SSH/no-tty
environments. The fallback path worked correctly, but the stderr
noise looked like a bug.
* Help text claimed `Detects and configures IDEs (OpenClaw, Cline,
Continue.dev, Cursor)` while only OpenClaw is actually configured.
Full investigation, evidence, and reviewer findings in #12.
## What this commit does
### B1: write per-agent auth-profiles.json (CRITICAL)
After writing root openclaw.json, iterate `agents.list[]`. For each
agent: derive agentDir from the explicit `agentDir` field, OR fall
back to `<openclaw_root>/agents/<id>/agent/` for agents that omit it.
This catches the default `main` agent, discovered via end-to-end
Telegram testing. Merge into existing auth-profiles.json (preserving
other providers' keys), upsert `<provider>:default` with the real
key, chmod 0600.
Anonymous mode (no --key) explicitly skips agentDir writes (empty
keys are dropped by OpenClaw's pi-auth-credentials anyway) and
prints a clear warning that OpenClaw multi-agent requires --key.
This is the "Path C" decision from #12 section 14.
Error handling is split for safety:
* `JSONDecodeError` on existing file -> back up to `.bak`, rebuild
* `OSError` on read -> skip this agent. Do NOT clobber the user's
existing profile, which may hold other providers' real keys.
* `OSError` on mkdir/write -> record in `_failed` list, surface in
output. Not silently swallowed.
Three independent report sections (`_seeded` / `_failed` /
`_skipped_anonymous`) so mixed scenarios don't hide warnings behind
each other.
### B2: smoke test caveat
After "Smoke test passed", append three lines explaining that the
test only verifies OCP direct connectivity, and instructing the user
to restart OpenClaw and send a real bot message to verify
end-to-end.
### B3: suppress /dev/tty stderr
Wrap all four `read ... </dev/tty` calls as
`{ read ... </dev/tty; } 2>/dev/null || fallback` so the brace group
captures the shell's own `Device not configured` error before it
reaches the user's terminal. The fallback semantics are unchanged.
### B6: help text wording
Change item 5 from old wording mentioning IDE auto-configuration to
"Configures OpenClaw automatically; prints setup hints for other
IDEs - manual configuration required". Detection logic itself is NOT
changed in this commit. That is deferred to a future PR. See #12
section 9 for details.
### Version bump
Per dev iron rule #5 (version bump before push):
* `OCP_CONNECT_VERSION="1.1.0"` constant
* `--version` CLI flag
* Banner shows version
## Test evidence
End-to-end verified on macOS 13 with the actual OpenClaw 2026.4.11
+ Telegram bot setup that exposed #12:
1. cold-install state (clean ~/.openclaw, no agent profiles)
2. run `ocp-connect 172.16.2.30 --key ocp_xxx` -> exit 0
3. verify both `~/.openclaw/agents/main/agent/auth-profiles.json`
and `~/.openclaw/agents/macbook_bot/agent/auth-profiles.json`
are written with mode 0600 and the real key
4. restart gateway -> `agent model: ocp/claude-sonnet-4-6` loads
5. send a real Telegram message -> bot responds via
`ocp/claude-sonnet-4-6`, `[telegram] sendMessage ok`,
`auth-state.json` updates `lastUsed` and shows
`errorCount: 0, lastGood: ocp:default`
6. zero `No API key found` / 401 / lane-error events anywhere
Offline test matrix (also all green):
* anonymous mode -> warning prints, no agentDir write
* corrupted existing auth-profiles.json -> backed up to .bak, rebuilt
* no-tty execution -> 0 `Device not configured` leakage
* `--help` -> new B6 wording
* `--version` -> `ocp-connect 1.1.0`
## Code review
Two independent reviewer subagents (opus, spec compliance + code
quality) plus one blind implementer subagent (sonnet, control
group). The blind implementer reproduced exactly the two MUST-FIX
issues the code-quality reviewer flagged in the first draft (silent
data loss on `except Exception`, misleading success on per-agent
write failure), validating that the review process caught real
non-obvious problems. Both must-fixes are addressed in this commit;
re-tested green.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(ocp-connect): drop "with agentDir" from anonymous warning
The message previously said "agents with agentDir" but B1.5 now also
seeds agents that omit the field (their dir is derived). Reviewer
feedback on PR #13.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: taodeng <taodeng@Taos-MBP>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Removed v3.0.x migration guide, old idleTimeoutSeconds workaround
(auto-handled by setup.mjs since v3.2.1), and manual session cleanup
instructions. Replaced with concise troubleshooting for common issues.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ocp-connect now detects installed IDEs and offers to configure them
automatically. OpenClaw gets full interactive setup (provider name,
primary/backup priority, model aliases). Other IDEs (Cline, Continue.dev,
Cursor) get manual config instructions printed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Writes to both .bashrc and .zshrc on macOS (covers both shells)
- macOS: launchctl setenv for GUI apps and daemons
- Linux: ~/.config/environment.d/ocp.conf for systemd user services
- Ensures IDEs and daemons can discover OCP models
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When the /api/oauth/usage endpoint returns 429 (rate limit), fall back
to the most recent cached data instead of returning an error. Also
extended cache TTL from 5min to 15min to reduce API calls.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds CLAUDE_NO_CONTEXT=true env var that passes
CLAUDE_CODE_DISABLE_CLAUDE_MDS=1 and CLAUDE_CODE_DISABLE_AUTO_MEMORY=1
to Claude CLI child processes. This suppresses CLAUDE.md and auto-memory
injection while preserving OAuth auth — needed for third-party agents
like Hermes that have their own memory systems.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
In zero-config auth mode, the server allows anonymous access even in
multi mode. The script now probes /v1/models first — if it succeeds,
no key is needed. Also updated README examples and version to 3.5.1.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replaces the old approach (sending a real messages API request just to
read rate-limit headers) with the dedicated usage endpoint that Claude
Code CLI uses. Fixes intermittent "unknown" plan usage.
- GET /api/oauth/usage with Bearer auth + anthropic-beta header
- Auto-refresh expired OAuth tokens via refresh_token grant
- Try both keychain label formats (claude-code-credentials, Claude Code-credentials)
- Zero API quota consumption for usage checks
- Parse new JSON response format (five_hour/seven_day structure)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Multi mode now allows unauthenticated requests as "anonymous".
Keys are optional: provide one for per-key usage tracking, or
skip it for zero-config access. Invalid keys are still rejected.
Localhost requests are always admin-level (can manage keys,
view dashboard data, etc.) without any token.
This makes OCP much friendlier for home LAN setups — family
members can use it immediately without any key configuration.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Requests from 127.0.0.1/::1 skip authentication even in multi/shared
auth modes. Only remote (LAN) clients need API keys.
This simplifies local tool integration — IDEs and agents on the same
machine no longer need to configure Bearer tokens.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Support ?token=xxx query parameter for dashboard auth (enables
headless browser screenshots and direct links)
- Token is saved to localStorage and URL is cleaned up
- Fix pathname matching to handle query parameters in URL
- Replace html2canvas screenshot with Playwright (accurate colors)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Clarify that /ocp commands are for Telegram/Discord via gateway plugin,
while terminal CLI uses ocp (without slash).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add LAN mode to share one Claude Pro/Max subscription across a household:
- 3-tier auth: none / shared / multi (per-user API keys)
- SQLite-backed key management and per-request usage tracking
- Embedded web dashboard with real-time monitoring
- CLI commands: keys, lan, usage --by-key
- Zero external dependencies (uses node:sqlite)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add LAN CLI commands (keys, lan, usage --by-key), new API endpoints
(dashboard, keys, usage), LAN env vars (CLAUDE_BIND, CLAUDE_AUTH_MODE,
OCP_ADMIN_KEY), and expanded security section.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add _curl wrapper that reads OCP_ADMIN_KEY env or ~/.ocp/admin-key file
- All admin API calls (keys, usage) use _curl for auth
- Fix ocp lan IP detection to try en0 and en1
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
better-sqlite3 native addon fails on Node v25. Node.js built-in SQLite
(node:sqlite) has an identical synchronous API and requires no compilation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix 1 (keys.mjs): listKeys() no longer leaks full API key field in response
- Fix 2 (server.mjs): Remove BIND_ADDRESS admin bypass from isAdmin check
- Fix 3 (server.mjs): Admin key comparison now uses timingSafeEqual
- Fix 4 (server.mjs): Cap limit (max 500) and hours (max 720) in GET /api/usage
- Fix 5 (server.mjs): Streaming error path now computes promptChars from messages
- Fix 6 (server.mjs): Warn at startup if AUTH_MODE=shared but PROXY_API_KEY is empty
- Fix 7 (server.mjs): All recordUsage calls wrapped in try/catch to prevent DB errors crashing server
- Fix 8 (server.mjs): CORS fallback changed from "*" to specific origin (http://127.0.0.1:<PORT>)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
setup.mjs now resolves /opt/homebrew/Cellar/node/X.Y.Z/ to
/opt/homebrew/opt/node/ so the LaunchAgent plist survives node upgrades.
Bump to v3.3.1.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove firstByteTimeout, adaptive tier algorithm, and MODEL_TIMEOUT_TIERS.
Claude tool-use causes 30s-5min pauses in token streams, making fine-grained
timeouts unreliable — they repeatedly killed valid requests. A single generous
timeout (10 min, matching LiteLLM/OpenAI SDK defaults) is simpler and correct.
Breaking: CLAUDE_FIRST_BYTE_TIMEOUT env var removed, default timeout changed
from 300s to 600s. Bump to v3.3.0.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The adaptive timeout calculation ignored BASE_FIRST_BYTE_TIMEOUT (set via
CLAUDE_FIRST_BYTE_TIMEOUT env), always using the tier base (120s for Sonnet).
Now uses whichever is larger: adaptive or env override. Bump to v3.2.2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
setup.mjs now sets agents.defaults.llm.idleTimeoutSeconds=0 in
openclaw.json during installation. Without this, OpenClaw's default
60s idle timeout kills Claude connections during tool use (Bash, Read,
etc.), causing exit 143 errors and stuck sessions.
Also adds troubleshooting section to README. Bump to v3.2.1.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
BASH_SOURCE returns the symlink path, not the target. This broke
ocp update on systems where ocp is installed as a symlink
(e.g. ~/.local/bin/ocp → repo/ocp).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- `ocp update`: pulls latest from GitHub, syncs plugin, restarts proxy
- `ocp update --check`: shows current vs latest version without applying
- `ocp restart`: now handles both dev.ocp.proxy and legacy ai.openclaw.proxy
service names on macOS/Linux
- Bumps to v3.2.0
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
OpenClaw's gateway scans LaunchAgent plists and systemd units for
"openclaw" markers and flags them as conflicting gateway-like services.
Renamed service identifiers to avoid false positives:
- macOS: ai.openclaw.proxy → dev.ocp.proxy
- Linux: openclaw-proxy.service → ocp-proxy.service
- Logs: ~/.openclaw/logs/ → ~/.ocp/logs/
Setup auto-removes legacy service names on upgrade. Uninstall handles
both old and new names. Also bumps version to 3.1.0.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Renamed from OpenClaw Control Plane to Open Claude Proxy. README
rewritten to position OCP as a universal proxy for any IDE that
speaks the OpenAI protocol, not just OpenClaw.
Added: supported tools table (Cline, OpenCode, Aider, Continue.dev),
simplified Quick Start, architecture diagram showing multi-IDE flow.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Documented the intermittent "Unknown skill: ocp" issue caused by
OpenClaw gateway session routing bug (#26895). Workaround: /new
followed by /ocp restart.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The slash session workaround was incomplete — root cause still under
investigation. Removed to avoid misleading users. Will add back with
accurate info once the issue is fully resolved.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New subcommands:
- /ocp restart [gateway|all] — restart proxy, gateway, or both
- /ocp version — show version, uptime, platform info
- /ocp test — end-to-end proxy test (sends haiku request)
- /ocp backends — list registered backends with health status
Also includes clean-slash-sessions.sh workaround for OpenClaw #26895.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Document OpenClaw gateway bug (#26895, #54485) where telegram:slash
sessions interfere with registerCommand plugin routing. Include
workaround script and warning not to add ocp to agent skills lists.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
On Linux (no macOS keychain), read ~/.claude/.credentials.json first.
Falls through to macOS keychain if file not found. Fixes /ocp usage
showing "No OAuth token" on Linux servers and RPi.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Common issue: ocp not in PATH after clone. Added explicit symlink
instructions with absolute paths and a troubleshooting note.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>