Use this skill to turn a ClawHub-installed js-eyes bundle into a working OpenClaw browser automation stack.
Treat {baseDir} as the installed skill root. The plugin path that must be registered in OpenClaw is {baseDir}/openclaw-plugin, not {baseDir} itself.
js_eyes_* tools are missing after installation.
Disconnected.
skill.contract.js) into a running OpenClaw, or to verify that such a skill is actually loaded.
Authoring A New Extension Skill below) rather than writing files from nothing.
A successful setup has all of the following:
npm install has been run in {baseDir} with Node.js 22 or newer.
{baseDir}/openclaw-plugin via plugins.load.paths.
plugins.entries["js-eyes"].enabled is true.
tools.alsoAllow (preferred) or tools.allow includes js-eyes, so the plugin's optional tools are actually exposed to the model.
openclaw js-eyes status.
http://: , the popup Server Token field is populated (2.2.0+), and js-eyes with action: browser/get-tabs returns real tabs.
{baseDir}/skills are enabled by default in the JS Eyes host config, and the main plugin auto-loads enabled skills from {baseDir}/skills or the configured skillsDir (primary), plus any read-only directories listed in extraSkillDirs (extras). The user can later use js-eyes actions skills/discover and skills/plan-install to add more extension skills dynamically.
js-eyes doctor reports an acceptable security posture for this skill's deployment (token present, allowAnonymous=false, allowRawEval=true in ~/.js-eyes/config/config.json, host bound to loopback, skill integrity OK). doctor will still label raw eval as insecure — that is expected when following this skill.
Treat {baseDir} as the bundle or repository root that contains openclaw-plugin/, skills/, and the package manifests.
There are two supported complete deployment modes:
{baseDir} is the installed JS Eyes bundle root.
npm install in {baseDir} so the plugin runtime can resolve its dependencies.
{baseDir}/openclaw-plugin in OpenClaw.
{baseDir} is the root of a local js-eyes git clone.
npm install in the repo root, not inside openclaw-plugin/.
plugins.load.paths at the repo-root openclaw-plugin directory.
extensions/chrome/ or extensions/firefox/manifest.json as appropriate.
openclaw-plugin/ itself (or any packages/* module the plugin imports directly) require restarting / refreshing OpenClaw so the plugin module is re-required. Edits to individual skill files (skills//skill.contract.js , an extraSkillDirs entry's contract, etc.) are picked up hot by the SkillRegistry + chokidar watcher — no restart needed.
For both deployment modes above, treat host-side raw eval as part of the default install: merge security.allowRawEval: true into ~/.js-eyes/config/config.json (Windows: %USERPROFILE%/.js-eyes/config/config.json) during deployment — not in openclaw.json. The js-eyes server reads this file; the browser extension syncs the value on WebSocket handshake (2.5.1+). Restart the server / OpenClaw after changing it so execute_script raw JavaScript is not blocked with RAW_EVAL_DISABLED.
Also for both modes, if the operator will use the extension popup Sync Token From Host / 从本机同步 (2.4.0+), register the Native Messaging host on that machine. Preferred (local launcher, no network): from the checked-out repo run bin/js-eyes-native-host-install.sh --browser all (macOS/Linux) or ./bin/js-eyes-native-host-install.ps1 -Browser all (Windows); both forward to node apps/cli/bin/js-eyes.js native-host install, which never touches the npm registry. Since 2.6.3 the launchers also run js-eyes server token init (idempotent) at the end, so the host has a token file to read on the very first popup sync attempt — without that step the host returns token-missing until the operator either runs js-eyes server token init manually or starts OpenClaw / the server (ensureToken() runs on server boot). Pass --skip-token-init (-SkipTokenInit on Windows) to opt out of the auto-init. Fallback: npx js-eyes native-host install --browser all — only recommended when js-eyes is globally installed and the operator trusts the npm registry at install time; this fallback does not seed the token, so pair it with npx js-eyes server token init explicitly. Confirm with node apps/cli/bin/js-eyes.js native-host status (manifest + launcher must exist; on Windows the .bat lives under %LOCALAPPDATA%\js-eyes\native-host\). Then restart the browser or reload the extension. Skipping this step leaves manual token paste as the only path and often surfaces native-messaging-disconnected in the popup. See docs/native-messaging.md.
This section is informational — the default Setup Workflow below still opts
into allowRawEval=true for full compatibility with the 2.6.x SKILL contract.
If an operator explicitly wants the host-hardened posture (ClawHub's
security.allowRawEval=false default), use the guidance here; nothing outside
this section changes.
allowRawEval: js-eyes actions such as
browser/open-url, browser/get-tabs, skills/reload, security/reload,
plus every extension-skill action that avoids raw JavaScript. For the
vast majority of browsing / form-filling / data-extraction flows this is
sufficient.
RAW_EVAL_DISABLED: browser/execute-script and
other raw-JS entry points. Sensitive actions
that also happen to run raw JS (e.g. some inject_css variants when a skill
passes inline scripts) will soft-fail the same way; the dispatcher prints
reason: RAW_EVAL_DISABLED in the audit log.
doctor output differs: when allowRawEval=false,
js-eyes doctor / js-eyes doctor --json reports no "expected insecure"
footnote on that row — the default value is the safe value, so the tool
treats it as a clean posture. Everything else (token presence,
allowAnonymous=false, loopback bind, skill integrity, extraSkillDirs
integrity if verifyExtraSkillDirs=true) is reported identically to the
standard SKILL deployment.
security.allowRawEval: true merge from step 5
of the Setup Workflow (or set it to false in an existing
~/.js-eyes/config/config.json), restart the js-eyes server / OpenClaw, and
optionally flip security.verifyExtraSkillDirs=true to close the
extraSkillDirs gap described in
below without any of these tweaks, the runtime behaviour in 2.6.3 is
identical to 2.6.1 — Safe Default Mode is purely additive guidance.
(2.6.3 only changes the install-time UX around server.token seeding;
it does not alter the policy / consent / egress runtime.)
When the user asks to install, configure, or repair JS Eyes, follow this exact order:
node -v must be >= 22
openclaw --version should work
{baseDir}, run npm install if dependencies are missing or if the user just installed the bundle.
openclaw.json:
plugins.load.paths contains the absolute path to {baseDir}/openclaw-plugin
plugins.entries["js-eyes"].enabled is true
tools.alsoAllow contains js-eyes (preferred additive mode), or ensure tools.allow includes js-eyes
plugins.entries["js-eyes"].config with:
serverHost: "localhost"
serverPort: 18080
autoStartServer: true
~/.js-eyes/config/config.json (Windows: %USERPROFILE%/.js-eyes/config/config.json) with security.allowRawEval: true and default-enable the bundled first-party skills under skillsEnabled so deployment matches this skill (see Host security config below). Restart the js-eyes server after edits (or restart OpenClaw if it auto-starts the server).
openclaw js-eyes status.
~/.js-eyes/runtime/server.token exists before anyone clicks the popup's Sync Token From Host / 从本机同步 button — otherwise the native host replies token-missing and the popup falls back to manual paste. Three ways to create it, any one is enough:
js-eyes server token init directly (idempotent — no-op if the file already exists).
bin/js-eyes-native-host-install.sh --browser all (macOS/Linux) / ./bin/js-eyes-native-host-install.ps1 -Browser all (Windows) — since 2.6.3 it does the token init for you (skip with --skip-token-init).
autoStartServer: true) or js-eyes server start once — the server calls ensureToken() on boot.
Then run the local launcher above (or the equivalent node apps/cli/bin/js-eyes.js native-host install --browser all) to register the Native Messaging manifest without hitting the npm registry. npx js-eyes native-host install remains as a fallback when the operator already has js-eyes globally installed; the npx path does not seed the token, so pair it with npx js-eyes server token init. If the operator can't or won't use Native Messaging at all, run js-eyes server token show --reveal and paste the value into the extension popup Server Token field under Advanced.
js-eyes tool actions skills/discover + skills/plan-install — 2.2.0+ writes a plan under runtime/pending-skills/.json ; finalize with js-eyes skills approve then js-eyes skills enable .
js-eyes skills link — it appends the path to extraSkillDirs, auto-enables it on first discovery, and the running plugin hot-loads it within ~300 ms via the config watcher. Reverse with js-eyes skills unlink . No OpenClaw restart is needed for either direction; see the Dynamic Extension Skills section for the full zero-restart contract.
js-eyes doctor to confirm the deployment posture (token present, allowAnonymous=false, allowRawEval enabled — doctor may still print it as insecure, which is expected here, loopback-bound, skill integrity OK) before handing off.
When asked to fix a broken setup, prefer repairing the existing config instead of repeating the whole installation.
Use this precedence order:
OPENCLAW_CONFIG_PATH
OPENCLAW_STATE_DIR/openclaw.json
OPENCLAW_HOME/.openclaw/openclaw.json
~/.openclaw/openclaw.json
%USERPROFILE%/.openclaw/openclaw.json
Do not assume ~/.openclaw/openclaw.json if any of the environment variables above are set.
Update the resolved OpenClaw config so it contains the plugin path and enablement entry. Append to existing arrays and objects; do not remove unrelated plugins.
{
"tools": {
"alsoAllow": ["js-eyes"]
},
"plugins": {
"load": {
"paths": ["/absolute/path/to/js-eyes/openclaw-plugin"]
},
"entries": {
"js-eyes": {
"enabled": true,
"config": {
"serverHost": "localhost",
"serverPort": 18080,
"autoStartServer": true
}
}
}
}
}
~/.js-eyes/config/config.json)
This file is not openclaw.json. For deployments following this skill, ensure at least:
{
"skillsEnabled": {
"js-bilibili-ops-skill": true,
"js-browser-ops-skill": true,
"js-github-ops-skill": true,
"js-jike-ops-skill": true,
"js-reddit-ops-skill": true,
"js-wechat-ops-skill": true,
"js-x-ops-skill": true,
"js-xiaohongshu-ops-skill": true,
"js-youtube-ops-skill": true,
"js-zhihu-ops-skill": true
},
"security": {
"allowRawEval": true
}
}
Merge with existing keys (for example skillsDir, skillsEnabled). The bundled first-party skills above are part of the default install and should be enabled unless the operator explicitly opts out of a platform. Operators who do not need raw execute_script may set allowRawEval to false instead; optional plugin tools then still work, but raw JS payloads are rejected until enabled.
Important details:
openclaw-plugin.
C:/Users/name/skills/js-eyes/openclaw-plugin.
paths or entries already exist, merge rather than overwrite.
js-eyes registers one optional plugin tool, so a complete deployment also needs tools.alsoAllow: ["js-eyes"] or an equivalent tools.allow entry.
skillsEnabled lives in the JS Eyes host config, not in openclaw.json. Enabling a bundled skill exposes its actions through the main js-eyes router; disabling it leaves the files on disk but skips loading it.
{baseDir}/skills (e.g. a user's private ~/my-skills/js-foo-ops-skill), either add absolute paths to plugins.entries["js-eyes"].config.extraSkillDirs: [...] directly, or let the CLI handle it: js-eyes skills link does the dedup append and also triggers an in-memory reload on the running plugin. Entries are read-only to js-eyes (no install / approve / verify / integrity check).
true): watchConfig (listen on ~/.js-eyes/config/config.json) and devWatchSkills (listen on discovered skill directories). Turn them off only if fs-watch load is a concern or in sandboxed environments.
Some security.* fields can be swapped into the running JS Eyes server without restarting OpenClaw or the server. The server-core ships its own chokidar watcher on ~/.js-eyes/config/config.json (separate from the plugin's skill watcher) and a reloadSecurity() handle that the js-eyes action security/reload calls on demand.
js-eyes action security/reload):
security.egressAllowlist
security.toolPolicies
security.sensitiveCookieDomains
security.allowedOrigins
security.enforcement
ignored in the reload summary, with a one-line warning in the gateway log): serverHost, serverPort, allowAnonymous, allowRemoteBind, allowRawEval, requireLockfile, and anything outside security.* (token rotation, requestTimeout, etc.).
PolicyContext, which means per-session js-eyes egress approve grants are dropped. Agents re-issue the approval on the next pending-egress response; no action needed for standard allow edits because those are part of the static allowlist and get picked up automatically.
~/.js-eyes/config/config.json and save — chokidar debounces 300 ms and fires reloadSecurity({ source: 'fs-watch' }).
js-eyes with action: security/reload (returns { changed, applied, ignored, generation, egressAllowlist }).
js-eyes security reload — read-only dry run that prints what would be applied (CLI does not own the server event loop, so trigger #1 or #2 is required for the actual swap).
~/.js-eyes/logs/audit.log) gains three new events — config.hot-reload, config.hot-reload.error, automation.policy-rebuilt — and GET /api/browser/status now includes data.policy.generation / data.policy.egressAllowlist so operators can externally confirm the live generation.
After setup, verify the stack in this order:
openclaw plugins inspect js-eyes
openclaw js-eyes status
js-eyes with action: browser/get-tabs or run openclaw js-eyes tabs.
js-eyes with action: skills/discover only after the base stack works.
Expected status checks:
openclaw plugins inspect js-eyes shows the plugin as loaded.
http://localhost:18080 by default.
openclaw js-eyes status shows uptime and browser client counts.
browser/get-tabs returns tabs instead of an empty browser list.
When the user asks "did my skill get picked up?", check all four:
~/.js-eyes/config/config.json has skillsEnabled[""]: true and (for externals) the skill's directory or a parent is listed in extraSkillDirs.
[js-eyes]:
Skill sources: primary= extras= — confirms extras were seen at startup.
Loaded local skill "" with K tool(s) — initial load at plugin boot.
Hot-loaded skill "" with K tool(s) — loaded at runtime by the config / skill-dir watcher.
Discovered skill(s): active — gives a numeric sanity check.
js-eyes with action: skills/reload; the returned summary must contain the id under added or reloaded.
js-eyes skills list from the host shell; each entry is annotated with Source: primary or Source: extra () .
If steps 2-4 all fail for a freshly linked external skill, see the Custom Extension Skill Not Picked Up troubleshooting entry below.
If the plugin is enabled but no browser is connected:
~/.js-eyes/runtime/server.token exists (Windows: %USERPROFILE%/.js-eyes/runtime/server.token). If it doesn't, run js-eyes server token init, or start OpenClaw / js-eyes server start once so the server's ensureToken() creates it. Without this file the native host returns token-missing and the popup sync silently falls back to manual paste.
bin/js-eyes-native-host-install.sh --browser all (macOS/Linux) or ./bin/js-eyes-native-host-install.ps1 -Browser all (Windows) — equivalent to node apps/cli/bin/js-eyes.js native-host install --browser all; this never contacts the npm registry. Since 2.6.3 the launcher also runs js-eyes server token init for you (skip with --skip-token-init / -SkipTokenInit), so steps 2 and 3 collapse into one command in the common case. npx js-eyes native-host install --browser all remains as a fallback but does not seed the token — pair it with npx js-eyes server token init explicitly. Either path sets up Native Messaging so the extension auto-syncs server.token and the HTTP URL; restart the browser (or reload the extension) so it picks up the new manifest, then open the popup and click Sync Token From Host.
http://: , paste the output of js-eyes server token show --reveal into the Server Token (2.2.0+) field, and click Connect.
openclaw js-eyes status.
The browser extension is not bundled inside the main ClawHub skill. It must be installed separately. Connections without a matching server token are rejected unless the operator has set security.allowAnonymous=true.
When the user wants to create a brand-new extension skill (not install / mount an existing one), do not scaffold files from scratch. Guide them through the canonical starter flow:
examples/js-eyes-skills/js-hello-ops-skill/ to a directory of their choice (typically ~/my-skills/js--ops-skill/ ). Point out that the starter already ships a working skill.contract.js, package.json, an async runtime.dispose() hook, a sample tool, and a SKILL.md frontmatter.
package.json.name, SKILL.md frontmatter name:, and skill.contract.js → id + name. Discovery resolves id via contract.id || pkg.name || path.basename(skillDir) (see normalizeSkillMetadata in packages/protocol/skills.js), so mismatches do not break load — but skillsEnabled., js-eyes skills link/enable/disable , and log messages all key off whatever the contract finally resolves to. Keeping directory name / pkg name / contract id identical is the only reliable way to keep CLI and config references coherent.
docs/dev/js-eyes-skills/authoring.zh.md — directory layout, discovery rules, quick-start.
docs/dev/js-eyes-skills/contract.zh.md — skill.contract.js surface (tools / runtime / runtime.dispose() lifecycle).
docs/dev/js-eyes-skills/deployment.zh.md — the zero-restart deployment flow the skill will end up in.
npm install inside the new skill directory so ws / @js-eyes/client-sdk resolve at load time.
js-eyes skills link ; the running plugin auto-discovers it within ~300 ms. Iterate on skill.contract.js in place — saves are hot-reloaded by the SkillRegistry skill-dir watcher; no OpenClaw restart is needed because all skill capabilities route through the single js-eyes tool.
skills/ directory (registry / ClawHub distribution) or keeping it external via extraSkillDirs / link forever — both paths are supported and zero-restart after mount.
Do not invent a different layout. Extension skills are discovered only if they satisfy the exact contract the starter demonstrates.
The main js-eyes bundle ships first-party extension skills under {baseDir}/skills. A complete default install enables those bundled skills through ~/.js-eyes/config/config.json → skillsEnabled, so they load through the main plugin without separate OpenClaw child-plugin entries.
Bundled first-party skills:
js-bilibili-ops-skill
js-browser-ops-skill
js-github-ops-skill
js-jike-ops-skill
js-reddit-ops-skill
js-wechat-ops-skill
js-x-ops-skill
js-xiaohongshu-ops-skill
js-youtube-ops-skill
js-zhihu-ops-skill
There are two complementary discovery surfaces — pick the right one when the user asks "what skills do I have?":
js-eyes skills list from the host shell, or js-eyes action skills/reload which returns a live diff. Each entry carries a Source: primary vs Source: extra () annotation.
skills.json): js-eyes action skills/discover. Installed rows are marked ✓ 已安装, installable rows ○ 未安装.
After the base plugin works:
js-eyes skills list or js-eyes action skills/reload to verify they are loaded.
js-eyes action skills/discover to list registry skills when the user wants to install a skill that is not already present in {baseDir}/skills, or to compare installed versions with the registry.
js-eyes action skills/plan-install to stage a plan — 2.2.0+ downloads the bundle, verifies its sha256 against skills.json, and writes runtime/pending-skills/.json without installing.
js-eyes skills approve , then enable it with js-eyes skills enable .
js-eyes skills verify (or js-eyes doctor) to confirm .integrity.json still matches the on-disk skill files.
SkillRegistry + a chokidar watcher on the host config — no OpenClaw restart needed. For external custom skills, prefer js-eyes skills link / js-eyes skills unlink ; to force a refresh, call js-eyes skills reload or have the agent invoke js-eyes action skills/reload (it returns an added / removed / reloaded / toggledOff / conflicts diff).
Use this table to pick the correct command for any user intent. All rows are zero-restart unless otherwise noted.
| Intent | Registry skill (shipped in skills.json) | External skill (arbitrary directory on disk) |
|---|---|---|
| Inspect what is installed locally | js-eyes skills list | same (entries annotated Source: extra () |
| Browse what can be installed | js-eyes action skills/discover | N/A (externals are out-of-registry by definition) |
| Install / mount | js-eyes action skills/plan-install → js-eyes skills approve → js-eyes skills enable | js-eyes skills link (auto-enables on first discovery) |
| Upgrade to the latest registry version | js-eyes skills update (preserves skillsEnabled, honors minParentVersion); js-eyes skills update --all for every primary-source skill; rerunning curl … \| JS_EYES_SKILL= works too | N/A — externals are managed in their source tree; pull/rebuild there |
| Temporarily stop without removing | js-eyes skills disable — runtime.dispose() fires, tools stop responding, files stay on disk | js-eyes skills disable (works the same; the link path stays in extraSkillDirs) |
| Re-enable | js-eyes skills enable | js-eyes skills enable |
| Replace / edit in place | Edit {baseDir}/skills/ and save — picked up by the skill-dir watcher, or call js-eyes skills reload | Same, against the external directory |
| Verify integrity | js-eyes skills verify [ — checks .integrity.json | N/A — integrity manifests only exist for registry installs |
| Remove / uninstall | The CLI intentionally has no uninstall subcommand. Soft-remove: js-eyes skills disable (recommended). Hard-remove: after disable, delete {baseDir}/skills/ manually, then optionally clear the skillsEnabled. key from ~/.js-eyes/config/config.json to keep it tidy. | js-eyes skills unlink — removes the path from extraSkillDirs and hot-unloads every skill that was sourced from it |
| Force a re-scan | js-eyes skills reload or js-eyes action skills/reload | Same |
The agent SHOULD execute these commands directly when it has shell access. If it does not (read-only / "ask" mode), it SHOULD print the exact command for the user to run and then re-verify via js-eyes skills list or js-eyes action skills/reload afterwards.
Do not instruct the user to register child-skill plugin paths manually. Child skills no longer ship their own openclaw-plugin wrappers.
Prefer the built-in install flow over manual zip extraction when the user wants additional JS Eyes capabilities.
Cannot find module 'ws'
Run npm install in {baseDir}. The bundle expects dependencies to be installed from the skill root.
js-eyes tool does not appear
Check:
plugins.load.paths points to {baseDir}/openclaw-plugin.
plugins.entries["js-eyes"].enabled is true.
tools.alsoAllow or tools.allow includes js-eyes.
skillsEnabled., extraSkillDirs, edits to a skill.contract.js) do not need a restart; they are applied by the SkillRegistry config / skill-dir watcher.
skillsEnabled.: true ) and that legacy OpenClaw child-plugin entries are removed.
For a custom external skill mounted via js-eyes skills link where no skill/ actions work and the log has no Loaded local skill " / Hot-loaded skill " line, check in order:
~/.js-eyes/config/config.json → extraSkillDirs contains the path; skillsEnabled[""] is true.
cd && ls skill.contract.js package.json succeed, and npm install has been run inside that directory so transitive deps like ws / @js-eyes/client-sdk resolve.
Failed to load skill "" entry; if it does, the error message identifies the offending require or syntax issue. Fix in place and call js-eyes skills reload (or js-eyes action skills/reload) — no OpenClaw restart needed.
Skipping extra skill ... same id already loaded from primary. Primary wins by design; rename the custom skill's id in its package.json / skill.contract.js or move it into primary.
git pull / upgrade but before restart): the running plugin may predate the single-tool router. In the gateway log look for [js-eyes] Watching host config: ... and verify OpenClaw exposes only js-eyes; if not, restart OpenClaw once to pick up the new plugin code; subsequent skill changes stay zero-restart.
Check:
openclaw js-eyes status
serverHost / serverPort in plugin config
autoStartServer is true
js-eyes server token show --reveal. On 2.4.0+ installs, prefer re-running the popup's Sync Token From Host button (powered by the Native Messaging host — see docs/native-messaging.md). Tail logs/audit.log via js-eyes audit tail — conn.reject with reason: token or reason: origin points to token/Origin mismatches.
Sync Token From Host reports token-missing: the manifest is registered but ~/.js-eyes/runtime/server.token doesn't exist yet. Either run js-eyes server token init (idempotent), start OpenClaw / js-eyes server start once so ensureToken() creates it, or re-run the local launcher bin/js-eyes-native-host-install.sh / .ps1 (2.6.3+ seeds the token automatically). Tail ~/.js-eyes/logs/native-host.log to confirm — a get-config: token-missing line on every popup click is the smoking gun.
Sync Token From Host does nothing / errors with Could not establish connection: the manifest isn't actually registered for this browser, or the browser was open before native-host install ran. Re-run node apps/cli/bin/js-eyes.js native-host status to confirm the manifest + launcher exist for the right browser, then fully restart the browser (not just reload the extension) so it re-scans the NativeMessagingHosts directory.
execute_script, get_cookies, upload_file*, inject_css, and install_skill default to the confirm policy and wait for operator approval.
js-eyes consent list to see pending requests.
js-eyes consent approve or js-eyes consent deny to resolve.
security.toolPolicies.=allow in config.json (logs an audit event).
If js_eyes_open_url or other browser tools return text mentioning pending-egress, 出站策略, or POLICY_SOFT_BLOCK, the server applied the policy engine before the extension ran the action (navigation may never reach the browser).
js-eyes security show and inspect egressAllowlist and taskOrigin (hosts must be in static allowlist, session scope, or task-origin scope — see SECURITY.md Policy Engine).
js-eyes egress list; use js-eyes egress approve for a queued host or js-eyes egress allow to append to security.egressAllowlist.
js-eyes with action: browser/get-tabs (or ensure the automation client has seeded tab state) so the active tab's host is in scope before opening URLs on that host.
This is separate from consent (js-eyes consent …) and from extension disconnect issues.
The main plugin refuses to register skills whose files no longer match .integrity.json.
js-eyes skills verify to see which files drifted.
js-eyes skills install → js-eyes skills approve → js-eyes skills enable .
.integrity.json by hand.
Always resolve OPENCLAW_CONFIG_PATH, OPENCLAW_STATE_DIR, and OPENCLAW_HOME before editing config or telling the user where to look.
js_eyes_* tools.
共 5 个版本