Skip to content

feat: add kernel browsers curl command#146

Open
rgarcia wants to merge 4 commits intomainfrom
raf/browser-curl-cli
Open

feat: add kernel browsers curl command#146
rgarcia wants to merge 4 commits intomainfrom
raf/browser-curl-cli

Conversation

@rgarcia
Copy link
Copy Markdown
Contributor

@rgarcia rgarcia commented Apr 9, 2026

Summary

Adds a curl-like command for making HTTP requests through a browser session's Chrome network stack. Requests inherit the browser's TLS fingerprint, cookies, proxy configuration, and headers.

Usage

# Simple GET
kernel browsers curl $ID https://example.com

# POST with JSON body
kernel browsers curl $ID -X POST -H "Content-Type: application/json" -d '{"key":"val"}' https://api.example.com

# Save response to file (uses streaming raw mode)
kernel browsers curl $ID -o page.html https://example.com

# Include response headers
kernel browsers curl $ID -i https://example.com

# Full JSON response (status, headers, body, duration)
kernel browsers curl $ID --json https://example.com

Flags

Flag Description
-X, --request HTTP method (default: GET)
-H, --header HTTP header, repeatable ("Key: Value" format)
-d, --data Request body
--data-file Read request body from file
--timeout Request timeout in milliseconds (default: 30000)
--encoding Response encoding: utf8 or base64
-o, --output Write response body to file (uses streaming mode)
--raw Use streaming mode (no JSON wrapper)
-i, --include Include response headers in output
-s, --silent Suppress progress output
--json Output full JSON response

Implementation notes

  • Uses raw HTTP calls to the /browsers/{id}/curl and /browsers/{id}/curl/raw API endpoints (the Go SDK doesn't have the curl method yet)
  • Two modes: JSON mode (default) parses the response, raw/streaming mode (--raw or -o) pipes the proxied response directly
  • Depends on kernel API changes in https://github.com/kernel/kernel-images-private/pull/145

Test plan

  • kernel browsers curl <id> https://example.com returns page body
  • -X POST -d '...' sends POST with body
  • -H "Key: Value" sets custom headers
  • -o output.html saves response to file
  • -i prints response headers before body
  • --json returns full JSON with status, headers, body, duration
  • --raw streams response without JSON wrapper
  • --data-file reads body from file
  • Error cases: invalid session ID, unreachable URL, auth failure

🤖 Generated with Claude Code


Note

Medium Risk
Adds a new command that performs authenticated raw HTTP requests and file output/streaming, plus updates the Kernel SDK dependency via a replace; mistakes here could break CLI networking/auth behavior or compatibility with the API.

Overview
Adds kernel browsers curl <session-id> <url> to make HTTP requests through an existing browser session, supporting headers/method/body (-X, -H, -d/--data-file), timeouts, optional response encoding, and optional header-inclusive output.

Implements two execution paths: a default SDK-backed JSON response mode and a raw/streaming mode (--raw or -o) that hits /browsers/{id}/curl/raw directly, including bearer auth token resolution from KERNEL_API_KEY or stored tokens.

Updates proxy health-check calls to match an SDK signature change (Check(..., kernel.ProxyCheckParams{})), extends fakes accordingly, and pins the SDK via go.mod replace to github.com/stainless-sdks/kernel-go (with corresponding go.sum updates).

Reviewed by Cursor Bugbot for commit d112191. Bugbot is set up for automated code reviews on this repo. Configure here.

rgarcia and others added 2 commits April 9, 2026 17:01
Adds a CLI command that makes HTTP requests through a browser session's
Chrome network stack, inheriting TLS fingerprint, cookies, proxy config,
and headers. Mirrors real curl UX with -X, -H, -d flags.

Two modes:
- Structured (default): POST /browsers/{id}/curl with JSON response
- Raw (--raw or -o): GET /browsers/{id}/curl/raw for streaming

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The API expects single-value headers (map[string]string), not
multi-value (map[string][]string). The previous type would serialize
as {"Content-Type": ["application/json"]} causing a runtime unmarshal
error on the server.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@firetiger-agent
Copy link
Copy Markdown

I'll monitor the rollout of the new kernel browsers curl command. This change adds CLI functionality for making HTTP requests through browser sessions, supporting both standard and streaming/raw modes.

What I'll watch for:

  • Traffic appearing on the new /browsers/{id}/curl and /browsers/{id}/curl/raw API endpoints (confirms backend is deployed and users are adopting)
  • Authentication failures, especially on the raw endpoint which handles auth differently than the SDK path
  • Error rates compared to similar browser endpoints like /browsers/{id}/playwright/execute
  • Latency distributions to ensure requests complete within the 30s default timeout

This is a low-risk change since it's a CLI-only addition that depends on existing API endpoints. The main thing to watch is whether the backend /browsers/{id}/curl* routes are deployed and working. I'll post updates as the deployment progresses.

View agent

…ser curl

Replace the hand-rolled POST /browsers/{id}/curl with the generated
BrowserCurlParams/BrowserCurlResponse types from the Stainless preview
SDK. The raw/streaming mode (curlRaw) remains custom HTTP as before.

Also updates ProxyService.Check interface to match the new SDK signature
(added ProxyCheckParams parameter).

Uses a temporary replace directive pointing kernel-go-sdk at the
stainless-sdks/kernel-go preview module.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@kernel-internal
Copy link
Copy Markdown
Contributor

kernel-internal bot commented Apr 10, 2026

🔧 CI Fix Available
I've pushed a fix for the CI failure.

👉 Click here to create a PR with the fix

golang.org/x/sync v0.19.0
)

replace github.com/kernel/kernel-go-sdk => github.com/stainless-sdks/kernel-go v0.0.0-20260410014529-98c58b154bb9
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Development SDK replace directive left in go.mod

High Severity

The replace directive redirects github.com/kernel/kernel-go-sdk to a pre-release commit from the private github.com/stainless-sdks/kernel-go repository. This is development scaffolding generated by scripts/go-mod-replace-kernel.sh (as documented in DEVELOPMENT.md) and needs to be removed before merging. Shipping with this replace ties the build to an unreleased private SDK commit, breaking builds for anyone without access to that private repo.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 7f8cece. Configure here.

- Pass encoding param to /curl/raw endpoint (was silently ignored)
- Print response headers to stdout when -i and -o are combined
- Remove unused client field from BrowsersCmd

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

There are 3 total unresolved issues (including 1 from previous review).

Fix All in Cursor

Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issues. You can view the agent here.

Reviewed by Cursor Bugbot for commit d112191. Configure here.

if resp.StatusCode == http.StatusNotFound {
respBody, _ := io.ReadAll(resp.Body)
return fmt.Errorf("not found (%d): %s", resp.StatusCode, strings.TrimSpace(string(respBody)))
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Raw mode error checks intercept proxied target responses

Medium Severity

In curlRaw, the status code checks for 401/403/404 cannot distinguish between API-level errors (e.g., invalid session) and legitimate proxied responses from the target URL. If the target URL itself returns a 401, 403, or 404, the CLI will incorrectly report it as an authentication or "not found" error instead of streaming the proxied response body to the user. This breaks the core "raw mode" contract of transparently piping the proxied response.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit d112191. Configure here.

return ""
}
return tokens.AccessToken
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Raw mode uses expired OAuth tokens without refreshing

High Severity

getAuthToken loads OAuth tokens via auth.LoadTokens() and returns tokens.AccessToken without checking whether the token is expired or attempting a refresh. The main auth path in auth.GetAuthenticatedClient checks tokens.IsExpired() and calls RefreshTokens when needed. In raw/streaming mode, users with expired (but refreshable) OAuth tokens will get authentication errors even though they're properly logged in, while JSON mode works fine via the SDK client.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit d112191. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant