> ## Documentation Index
> Fetch the complete documentation index at: https://kernel.sh/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Hand setup to your coding agent, or create your first cloud browser yourself

export const CopyPromptButton = props => {
  const {label = 'copy prompt'} = props || ({});
  const [copied, setCopied] = useState(false);
  const prompt = props && props.prompt || `# Setup Kernel

## Prerequisites
- Read the kernel-cli skill at https://github.com/kernel/skills/blob/main/plugins/kernel-cli/skills/kernel-cli/SKILL.md for reference on commands and capabilities.

## Steps

1. **Check if Kernel CLI is installed:**
   - Run \`kernel --version\`.
   - If not found, install via \`brew install kernel/tap/kernel\`.
   - If found, run \`brew upgrade kernel/tap/kernel\` to ensure latest version.
   - Verify with \`kernel --version\` and confirm >= v0.16.0.

2. **Check authentication:**
   - Run \`kernel auth\`.
   - If authenticated, done.
   - If not, run \`kernel login\` and tell the user to complete the browser flow.
     Poll \`kernel auth\` every 5 seconds, up to 5 minutes.
     If it times out, stop and ask the user for help.

3. **Create a browser and open Live View:**
   - Run a Kernel CLI command that creates a browser session and goes to \`https://www.kernel.sh/docs/browsers/live-view\`
   - Capture the returned \`browser_live_view_url\`.
   - Open that URL in the user's browser.
   - Tell the user they can use the live view immediately.
   - If browser creation fails, stop and ask the user for help.`;
  const handleCopy = useCallback(async () => {
    try {
      await navigator.clipboard.writeText(prompt);
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    } catch {
      const textarea = document.createElement('textarea');
      textarea.value = prompt;
      textarea.style.position = 'fixed';
      textarea.style.opacity = '0';
      document.body.appendChild(textarea);
      textarea.select();
      document.execCommand('copy');
      document.body.removeChild(textarea);
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    }
  }, []);
  return <button onClick={handleCopy} style={{
    display: 'inline-flex',
    alignItems: 'center',
    justifyContent: 'center',
    gap: '0.5rem',
    width: '100%',
    maxWidth: '352px',
    height: '56px',
    padding: '0 32px',
    fontSize: '0.9375rem',
    fontWeight: 500,
    letterSpacing: '0.01em',
    color: '#fff',
    backgroundColor: '#111',
    border: '1px solid rgba(255, 255, 255, 0.08)',
    cursor: 'pointer',
    textDecoration: 'none',
    transition: 'text-decoration 0.15s ease',
    fontFamily: 'inherit'
  }} onMouseEnter={e => {
    e.currentTarget.style.textDecoration = 'underline';
  }} onMouseLeave={e => {
    e.currentTarget.style.textDecoration = 'none';
  }}>
      {copied ? <>
          <svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
            <polyline points="3.5 8.5 6.5 11.5 12.5 4.5" />
          </svg>
          copied!
        </> : <>
          <svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
            <rect x="5.5" y="5.5" width="8" height="8" rx="1.5" />
            <path d="M10.5 5.5V3.5C10.5 2.67 9.83 2 9 2H3.5C2.67 2 2 2.67 2 3.5V9C2 9.83 2.67 10.5 3.5 10.5H5.5" />
          </svg>
          {label}
        </>}
    </button>;
};

Pick the way in that matches how you work. The first two are walked through on this page; the rest open their own guides.

<Columns className="responsive-columns" cols={4}>
  <Card title="Hand it to your coding agent" icon="robot" href="#path-1-hand-it-to-your-coding-agent">
    Copy one prompt into Cursor, Claude Code, or Codex and let it set up KERNEL.
  </Card>

  <Card title="Write it with an SDK" icon="code" href="#path-2-write-it-yourself-with-an-sdk">
    Create and drive your first browser in TypeScript, Python, or Go.
  </Card>

  <Card title="Call the REST API" icon="brackets-curly" href="https://www.kernel.sh/docs/api-reference/browsers/create-a-browser-session">
    Call KERNEL over HTTP from any language, starting with creating a browser.
  </Card>

  <Card title="Use the CLI" icon="terminal" href="/docs/reference/cli">
    Create, drive, and debug browsers from a terminal.
  </Card>

  <Card title="Connect over MCP" icon="plug" href="/docs/reference/mcp-server">
    Give any MCP client, like Claude or Cursor, a cloud browser as a set of tools.
  </Card>

  <Card title="Add Agent Skills" icon="wand-magic-sparkles" href="/docs/skills/overview">
    Teach your coding agent the KERNEL CLI, SDKs, and auth with one install.
  </Card>

  <Card title="Use your framework" icon="puzzle-piece" href="/docs/integrations/overview">
    Guides for the agent frameworks, models, and platforms you already use.
  </Card>

  <Card title="Follow a cookbook" icon="book-open" href="/docs/cookbooks">
    Clone an end-to-end recipe and adapt it to your task.
  </Card>
</Columns>

## Path 1: hand it to your coding agent

Copy this prompt into Claude Code, Codex, Cursor, or any agent that can run terminal commands. It installs the KERNEL CLI, signs you in, and opens a live view of a KERNEL browser that you or your agent can drive. From there, ask your agent to do a task on a site you care about.

<div className="copy-prompt-full" style={{ margin: '1rem 0' }}>
  <CopyPromptButton />
</div>

<AccordionGroup>
  <Accordion title="See what this prompt does">
    1. Checks for the KERNEL CLI and installs or upgrades it with Homebrew.
    2. Checks whether you're signed in, and if not, runs `kernel login` and waits for you to finish signing in.
    3. Creates a browser and opens its live view so you can watch it.

    It stops and asks you for help if any step fails.
  </Accordion>

  <Accordion title="Agent-readable surfaces">
    | Surface | What it's for |
    | - | - |
    | [`kernel.sh/llms.txt`](https://www.kernel.sh/llms.txt) | Hand-written. What KERNEL is, when to use it, every machine endpoint. Start here. |
    | [`kernel.sh/docs/llms.txt`](https://www.kernel.sh/docs/llms.txt) | Index of every docs page, for fetching the ones a task needs. |
    | [`kernel.sh/docs/llms-full.txt`](https://www.kernel.sh/docs/llms-full.txt) | The whole docs corpus in one file, for agents with room for it. |
    | [Agent Skills](/docs/skills/overview) | KERNEL know-how installed into the agent, so it doesn't re-read docs every session. |
    | [MCP server](/docs/reference/mcp-server) | KERNEL's API as tools, for agents that call tools instead of writing code. |
    | [OpenAPI 3.1](https://www.kernel.sh/openapi.json) | For generating a client or calling the REST API directly. |
  </Accordion>
</AccordionGroup>

## Path 2: write it yourself with an SDK

<Steps>
  <Step title="Set your API key">
    Create an API key in the [dashboard](https://dashboard.onkernel.com) and set it as `KERNEL_API_KEY`. Every SDK, the CLI, and the MCP server read it from the environment.

    ```bash theme={null}
    export KERNEL_API_KEY=<your-api-key>
    ```
  </Step>

  <Step title="Install an SDK">
    <CodeGroup>
      ```bash TypeScript theme={null}
      npm install @onkernel/sdk
      ```

      ```bash Python theme={null}
      pip install kernel
      ```

      ```bash Go theme={null}
      go get github.com/kernel/kernel-go-sdk
      ```
    </CodeGroup>
  </Step>

  <Step title="Create a browser and drive it">
    This creates a browser, runs Playwright code inside the browser's VM, returns the result, and cleans up. No local Chromium, no CDP connection to manage.

    <CodeGroup>
      ```typescript TypeScript theme={null}
      import Kernel from '@onkernel/sdk';

      const kernel = new Kernel();

      const browser = await kernel.browsers.create({ timeout_seconds: 300 });
      console.log('live view:', browser.browser_live_view_url);

      try {
        const { result } = await kernel.browsers.playwright.execute(browser.session_id, {
          code: `
            await page.goto('https://news.ycombinator.com');
            return await page.$$eval('.titleline > a', (as) => as.slice(0, 5).map((a) => a.textContent));
          `,
        });
        console.log(result);
      } finally {
        await kernel.browsers.deleteByID(browser.session_id);
      }
      ```

      ```python Python theme={null}
      from kernel import Kernel

      kernel = Kernel()

      browser = kernel.browsers.create(timeout_seconds=300)
      print("live view:", browser.browser_live_view_url)

      try:
          response = kernel.browsers.playwright.execute(
              browser.session_id,
              code="""
                await page.goto('https://news.ycombinator.com');
                return await page.$$eval('.titleline > a', (as) => as.slice(0, 5).map((a) => a.textContent));
              """,
          )
          print(response.result)
      finally:
          kernel.browsers.delete_by_id(browser.session_id)
      ```

      ```go Go theme={null}
      package main

      import (
      	"context"
      	"fmt"

      	"github.com/kernel/kernel-go-sdk"
      )

      func main() {
      	ctx := context.Background()
      	client := kernel.NewClient()

      	browser, err := client.Browsers.New(ctx, kernel.BrowserNewParams{
      		TimeoutSeconds: kernel.Int(300),
      	})
      	if err != nil {
      		panic(err)
      	}
      	defer client.Browsers.DeleteByID(ctx, browser.SessionID)
      	fmt.Println("live view:", browser.BrowserLiveViewURL)

      	res, err := client.Browsers.Playwright.Execute(ctx, browser.SessionID, kernel.BrowserPlaywrightExecuteParams{
      		Code: `
      			await page.goto('https://news.ycombinator.com');
      			return await page.$$eval('.titleline > a', (as) => as.slice(0, 5).map((a) => a.textContent));
      		`,
      	})
      	if err != nil {
      		panic(err)
      	}
      	fmt.Println(res.Result)
      }
      ```
    </CodeGroup>

    Open `browser_live_view_url` while it runs and you'll watch the page load.
  </Step>
</Steps>

## Next steps

Two things determine the shape of everything after this: which control surface you use, and where your loop runs. [How you drive the browser](/docs/introduction/control) covers both.

<Columns className="responsive-columns" cols={4}>
  <Card title="Getting blocked?" icon="user-secret" href="/docs/browsers/bot-detection/overview">
    Stealth and proxies to get past bot detection.
  </Card>

  <Card title="Behind a login?" icon="key" href="/docs/auth/overview">
    Fill credentials from a vault, or let managed auth log in.
  </Card>

  <Card title="Need to pay?" icon="credit-card" href="/docs/browsers/payments">
    Complete checkouts without exposing card data to your agent.
  </Card>

  <Card title="Want a worked example?" icon="book-open" href="/docs/cookbooks">
    End-to-end recipes you can clone and run.
  </Card>
</Columns>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.