Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions cmd/jcode/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,19 @@ import (

"github.com/spf13/cobra"

"github.com/cnjack/jcode/internal/browser"
"github.com/cnjack/jcode/internal/command"
)

func main() {
// Native-messaging launch: Chrome/Edge start `jcode chrome-extension://<id>/`
// when the browser extension calls connectNative. Handle it before cobra —
// this mode speaks the stdio native-messaging protocol and must not print
// anything else to stdout.
if browser.MaybeRunNativeHost(os.Args[1:]) {
return
}

var (
prompt string
resumeUUID string
Expand Down
61 changes: 61 additions & 0 deletions extension/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# jcode Browser Bridge (Chrome extension)

Lets jcode see and operate **your** Chrome — with your logins and sessions —
via the Chrome DevTools Protocol. This is the `extension` backend of jcode's
browser-use feature (the other backend is a managed Chrome jcode launches
itself; that one needs no extension). See
[`internal-doc/browser-use-design.md`](../internal-doc/browser-use-design.md).

The extension has a **fixed id** (`ekcnniaefmnhnemnpphikhgfoofnojnd`, pinned by
the `key` field in `manifest.json`) so the id is stable across machines and
reloads. That's what makes the one-click deeplink below possible.

## Install (unpacked, for development)

1. Start jcode web/desktop.
2. Open `chrome://extensions` (or `edge://extensions`), enable **Developer mode**.
3. Click **Load unpacked** and select this `extension/` folder.

## Connect — Auto-connect

Make sure jcode is running with browser use enabled (Settings → Browser → on).
Click the extension's toolbar icon → **Auto-connect to jcode**.

It uses Chrome Native Messaging to find the running jcode app (even on a dynamic
desktop-app port), fetch the server URL + a token, and connect. No code, no URL,
and it self-heals when the app restarts on a new port.

- Requires the native-host manifest, which jcode **installs automatically** when
it starts with browser use enabled (macOS/Linux: a file under the browser's
`NativeMessagingHosts` dir; Windows: a registry key under HKCU). If
Auto-connect reports the host is unavailable, start/restart jcode once with
browser use enabled, then try again.

Auto-connect exchanges for a long-lived token in `chrome.storage.local`;
afterwards the extension reconnects silently — you connect once. Use
**Disconnect** in the popup to stop and forget the token.
Comment on lines +34 to +36

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Security section contradicts the token description above.

Lines 34-36 describe a "long-lived token" persisted in storage and reused silently, but the Security section (lines 59-60) says the bridge "authenticates with a short-lived pairing code." This mismatches actual behavior in background.js (token stored via chrome.storage.local and reused across reconnects until Disconnect) and could confuse users about the real security model.

Also applies to: 57-61

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@extension/README.md` around lines 34 - 36, The README security wording is
inconsistent with the actual reconnect behavior in background.js and the token
flow described earlier. Update the Security section and nearby token description
so both use the same terminology and clearly state that the extension stores a
long-lived token in chrome.storage.local, reconnects silently until Disconnect
is used, and does not describe this as a short-lived pairing code. Refer to the
background.js token storage/reconnect behavior and the README Security section
text to keep the wording aligned.


## How it works

- The service worker (`background.js`) holds a websocket to
`/api/browser/ext/ws` on the jcode server.
- jcode sends CDP commands over that socket; the worker relays them to the
target tab with `chrome.debugger.sendCommand` and streams events back.
- jcode-controlled tabs are placed in a **"jcode 🔎"** tab group so you can see
which tabs are under agent control. Detaching the debugger (or the Chrome
"started debugging" bar → Cancel) hands control back — jcode stops.

## Permissions

- `debugger` — the CDP control channel (Chrome shows a banner while attached).
- `tabs`, `tabGroups` — create/switch/group tabs.
- `storage` — persist the server URL and pairing token.
- `scripting` — reserved for future in-page helpers.
- `host_permissions` limited to `127.0.0.1` / `localhost` — it only ever talks
to your local jcode.
Comment on lines +48 to +55

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Permissions list omits alarms and nativeMessaging.

manifest.json declares alarms (keepalive) and nativeMessaging (Auto-connect discovery), both documented as core features earlier in this README, but they're missing from the Permissions list.

📝 Proposed addition
 - `debugger` — the CDP control channel (Chrome shows a banner while attached).
 - `tabs`, `tabGroups` — create/switch/group tabs.
 - `storage` — persist the server URL and pairing token.
 - `scripting` — reserved for future in-page helpers.
+- `alarms` — periodic keepalive ping/reconnect while the service worker sleeps.
+- `nativeMessaging` — talk to the jcode native host for zero-input Auto-connect.
 - `host_permissions` limited to `127.0.0.1` / `localhost` — it only ever talks
   to your local jcode.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
## Permissions
- `debugger` — the CDP control channel (Chrome shows a banner while attached).
- `tabs`, `tabGroups` — create/switch/group tabs.
- `storage` — persist the server URL and pairing token.
- `scripting` — reserved for future in-page helpers.
- `host_permissions` limited to `127.0.0.1` / `localhost` — it only ever talks
to your local jcode.
## Permissions
- `debugger` — the CDP control channel (Chrome shows a banner while attached).
- `tabs`, `tabGroups` — create/switch/group tabs.
- `storage` — persist the server URL and pairing token.
- `scripting` — reserved for future in-page helpers.
- `alarms` — periodic keepalive ping/reconnect while the service worker sleeps.
- `nativeMessaging` — talk to the jcode native host for zero-input Auto-connect.
- `host_permissions` limited to `127.0.0.1` / `localhost` — it only ever talks
to your local jcode.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@extension/README.md` around lines 48 - 55, The Permissions section is missing
two manifest-declared capabilities, `alarms` and `nativeMessaging`, even though
they are part of the extension’s core behavior. Update the Permissions list in
the README to include both entries alongside the existing permissions, keeping
the descriptions aligned with their roles in keepalive and auto-connect
discovery as reflected in manifest.json.


## Security

The bridge only connects to a loopback jcode server and authenticates with a
short-lived pairing code. Nothing is sent to any third party. Use the popup's
**Disconnect** to revoke the token and detach all tabs.
Loading
Loading