diff --git a/README.md b/README.md
index f4d42e6..55b0798 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@
-A CLI tool to create the scaffolding for a new Kernel applications. This tool helps you get started with building browser automation applications using Kernel's platform.
+A CLI tool to create the scaffolding for a new Kernel applications. This tool helps you get started with building browser automation applications using Kernel's platform.
## Features
@@ -52,30 +52,36 @@ create-kernel-app [app-name] [options]
### Examples
Create a TypeScript application with a sample app:
+
```bash
npx @onkernel/create-kernel-app my-app --language typescript --template sample-app
```
Create a Typescript application with Stagehand template:
+
```bash
npx @onkernel/create-kernel-app my-app --language typescript --template stagehand
```
Create a Typescript application with Computer Use template:
+
```bash
npx @onkernel/create-kernel-app my-app --language typescript --template computer-use
```
Create a Python application with a sample app:
+
```bash
npx @onkernel/create-kernel-app my-app --language python --template sample-app
```
Create a Python application with Browser Use template:
+
```bash
npx @onkernel/create-kernel-app my-app --language python --template browser-use
```
-```
+
+````
## Next Steps
@@ -84,18 +90,21 @@ After creating your application:
1. Navigate to your project directory:
```bash
cd my-app
-```
+````
2. Set up your environment:
+
- For TypeScript: `npm install`
- For Python: `uv venv && source .venv/bin/activate && uv sync`
3. Set your Kernel API key:
+
```bash
-export KERNEL_API_KEY=
+kernel login # or: export KERNEL_API_KEY=
```
4. Deploy your application:
+
```bash
# Typscript
kernel deploy index.ts # --env OPENAI_API_KEY=XXX if Stagehand; --env ANTHROPIC_API_KEY=XXX if Computer Use
@@ -107,6 +116,7 @@ kernel deploy main.py # --env OPENAI_API_KEY=XXX if Browser Use
If deploying an app that requires environment variables, make sure to [set them](https://docs.onkernel.com/launch/deploy#environment-variables) when you `deploy`.
5. Invoke your application:
+
```bash
# Typescript + Sample App
kernel invoke ts-basic get-page-title --payload '{"url": "https://www.google.com"}'
@@ -134,18 +144,19 @@ kernel invoke python-cua cua-task --payload '{"task": "Get current market price
These are the sample apps currently available when you run `npx @onkernel/create-kernel-app`:
-| Template | Description | Framework | Query Parameters |
-|----------|-------------|-----------|------------------|
-| **sample-app** | Returns the page title of a specified URL | Playwright | `{ url }` |
-| **browser-use** | Completes a specified task | Browser Use | `{ task }` |
-| **stagehand** | Returns the first result of a specified Google search | Stagehand | `{ query }` |
-| **advanced-sample** | Implements sample apps using advanced Kernel configs | n/a |
-| **computer-use** | Implements a prompt loop | Anthropic Computer Use API | `{ query }` |
-| **cua** | Implements the OpenAI Computer Using Agent (CUA) | OpenAI CUA | `{ task }` |
+| Template | Description | Framework | Query Parameters |
+| ------------------- | ----------------------------------------------------- | -------------------------- | ---------------- |
+| **sample-app** | Returns the page title of a specified URL | Playwright | `{ url }` |
+| **browser-use** | Completes a specified task | Browser Use | `{ task }` |
+| **stagehand** | Returns the first result of a specified Google search | Stagehand | `{ query }` |
+| **advanced-sample** | Implements sample apps using advanced Kernel configs | n/a |
+| **computer-use** | Implements a prompt loop | Anthropic Computer Use API | `{ query }` |
+| **cua** | Implements the OpenAI Computer Using Agent (CUA) | OpenAI CUA | `{ task }` |
## Documentation
For more information about Kernel and its features, visit:
+
- [Kernel Documentation](https://docs.onkernel.com/quickstart)
- [Kernel Homepage](https://onkernel.com)
@@ -156,4 +167,3 @@ Contributions are welcome! Please feel free to submit a pull request. See [Contr
## License
MIT © [Kernel](https://onkernel.com)
-
diff --git a/index.ts b/index.ts
index b4d51f5..0beacdc 100644
--- a/index.ts
+++ b/index.ts
@@ -66,8 +66,7 @@ const TEMPLATES: Record = {
},
[TEMPLATE_ADVANCED_SAMPLE]: {
name: "Advanced Samples",
- description:
- "Implements sample actions with advanced Kernel configs",
+ description: "Implements sample actions with advanced Kernel configs",
languages: [LANGUAGE_TYPESCRIPT, LANGUAGE_PYTHON],
},
[TEMPLATE_COMPUTER_USE]: {
@@ -91,8 +90,7 @@ const INVOKE_SAMPLES: Record<
'kernel invoke ts-basic get-page-title --payload \'{"url": "https://www.google.com"}\'',
[TEMPLATE_STAGEHAND]:
'kernel invoke ts-stagehand stagehand-task --payload \'{"query": "Best wired earbuds"}\'',
- [TEMPLATE_ADVANCED_SAMPLE]:
- 'kernel invoke ts-advanced test-captcha-solver',
+ [TEMPLATE_ADVANCED_SAMPLE]: "kernel invoke ts-advanced test-captcha-solver",
[TEMPLATE_COMPUTER_USE]:
'kernel invoke ts-cu cu-task --payload \'{"query": "Return the first url of a search result for NYC restaurant reviews Pete Wells"}\'',
[TEMPLATE_CUA]:
@@ -104,7 +102,7 @@ const INVOKE_SAMPLES: Record<
[TEMPLATE_BROWSER_USE]:
'kernel invoke python-bu bu-task --payload \'{"task": "Compare the price of gpt-4o and DeepSeek-V3"}\'',
[TEMPLATE_ADVANCED_SAMPLE]:
- 'kernel invoke python-advanced test-captcha-solver',
+ "kernel invoke python-advanced test-captcha-solver",
[TEMPLATE_COMPUTER_USE]:
'kernel invoke python-cu cu-task --payload \'{"query": "Return the first url of a search result for NYC restaurant reviews Pete Wells"}\'',
[TEMPLATE_CUA]:
@@ -117,28 +115,18 @@ const REGISTERED_APP_NAMES: Record<
Partial>
> = {
[LANGUAGE_TYPESCRIPT]: {
- [TEMPLATE_SAMPLE_APP]:
- 'ts-basic',
- [TEMPLATE_STAGEHAND]:
- 'ts-stagehand',
- [TEMPLATE_ADVANCED_SAMPLE]:
- 'ts-advanced',
- [TEMPLATE_COMPUTER_USE]:
- 'ts-cu',
- [TEMPLATE_CUA]:
- 'ts-cua',
+ [TEMPLATE_SAMPLE_APP]: "ts-basic",
+ [TEMPLATE_STAGEHAND]: "ts-stagehand",
+ [TEMPLATE_ADVANCED_SAMPLE]: "ts-advanced",
+ [TEMPLATE_COMPUTER_USE]: "ts-cu",
+ [TEMPLATE_CUA]: "ts-cua",
},
[LANGUAGE_PYTHON]: {
- [TEMPLATE_SAMPLE_APP]:
- 'python-basic',
- [TEMPLATE_BROWSER_USE]:
- 'python-bu',
- [TEMPLATE_ADVANCED_SAMPLE]:
- 'python-advanced',
- [TEMPLATE_COMPUTER_USE]:
- 'python-cu',
- [TEMPLATE_CUA]:
- 'python-cua',
+ [TEMPLATE_SAMPLE_APP]: "python-basic",
+ [TEMPLATE_BROWSER_USE]: "python-bu",
+ [TEMPLATE_ADVANCED_SAMPLE]: "python-advanced",
+ [TEMPLATE_COMPUTER_USE]: "python-cu",
+ [TEMPLATE_CUA]: "python-cua",
},
};
@@ -311,14 +299,14 @@ function copyTemplateFiles(
fs.copySync(templatePath, appPath, {
filter: (src, dest) => {
const filename = path.basename(src);
- if (filename === '_gitignore') {
+ if (filename === "_gitignore") {
fs.copyFileSync(src, dest);
// Rename it to .gitignore
- fs.renameSync(dest, path.join(path.dirname(dest), '.gitignore'));
+ fs.renameSync(dest, path.join(path.dirname(dest), ".gitignore"));
return false; // Skip the original copy since we handled it
}
return true; // Copy all other files normally
- }
+ },
});
}
@@ -363,7 +351,8 @@ function printNextSteps(
): void {
// Determine which sample command to show based on language and template
const deployCommand =
- language === LANGUAGE_TYPESCRIPT && (template === TEMPLATE_SAMPLE_APP || template === TEMPLATE_ADVANCED_SAMPLE)
+ language === LANGUAGE_TYPESCRIPT &&
+ (template === TEMPLATE_SAMPLE_APP || template === TEMPLATE_ADVANCED_SAMPLE)
? "kernel deploy index.ts"
: language === LANGUAGE_TYPESCRIPT && template === TEMPLATE_STAGEHAND
? "kernel deploy index.ts --env OPENAI_API_KEY=XXX"
@@ -371,7 +360,9 @@ function printNextSteps(
? "kernel deploy index.ts --env ANTHROPIC_API_KEY=XXX"
: language === LANGUAGE_TYPESCRIPT && template === TEMPLATE_CUA
? "kernel deploy index.ts --env OPENAI_API_KEY=XXX"
- : language === LANGUAGE_PYTHON && (template === TEMPLATE_SAMPLE_APP || template === TEMPLATE_ADVANCED_SAMPLE)
+ : language === LANGUAGE_PYTHON &&
+ (template === TEMPLATE_SAMPLE_APP ||
+ template === TEMPLATE_ADVANCED_SAMPLE)
? "kernel deploy main.py"
: language === LANGUAGE_PYTHON && template === TEMPLATE_BROWSER_USE
? "kernel deploy main.py --env OPENAI_API_KEY=XXX"
@@ -388,11 +379,11 @@ function printNextSteps(
Next steps:
brew install onkernel/tap/kernel
cd ${appName}
- export KERNEL_API_KEY=
+ kernel login # or: export KERNEL_API_KEY=
${deployCommand}
${INVOKE_SAMPLES[language][template]}
# Do this in a separate tab
- export KERNEL_API_KEY=
+ kernel login # or: export KERNEL_API_KEY=
kernel logs ${REGISTERED_APP_NAMES[language][template]} --follow
`)
);
diff --git a/templates/python/advanced-sample/main.py b/templates/python/advanced-sample/main.py
index 92d8b50..17994cc 100644
--- a/templates/python/advanced-sample/main.py
+++ b/templates/python/advanced-sample/main.py
@@ -15,7 +15,7 @@
None
Invoke this via CLI:
- export KERNEL_API_KEY=
+ kernel login # or: export KERNEL_API_KEY=
kernel deploy main.py # If you haven't already deployed this app
kernel invoke py-advanced test_captcha_solver
kernel logs py-advanced -f # Open in separate tab
@@ -36,7 +36,7 @@ async def test_captcha_solver(ctx: kernel.KernelContext) -> None:
page = context.pages[0] if context.pages else await context.new_page()
# Access the live view. Retrieve this live_view_url from the Kernel logs in your CLI:
- # export KERNEL_API_KEY=
+ # kernel login # or: export KERNEL_API_KEY=
# kernel logs py-advanced --follow
print("Kernel browser live view url: ", kernel_browser.browser_live_view_url)
diff --git a/templates/python/cua/main.py b/templates/python/cua/main.py
index 6ec301a..d6f0872 100644
--- a/templates/python/cua/main.py
+++ b/templates/python/cua/main.py
@@ -15,7 +15,7 @@
Returns:
An answer to the task, elapsed time and optionally the messages stack
Invoke this via CLI:
- export KERNEL_API_KEY=
+ kernel login # or: export KERNEL_API_KEY=
kernel deploy main.py -e OPENAI_API_KEY=XXXXX --force
kernel invoke python-cua cua-task -p '{"task":"go to https://news.ycombinator.com and list top 5 articles"}'
kernel logs python-cua -f # Open in separate tab
diff --git a/templates/python/sample-app/main.py b/templates/python/sample-app/main.py
index e27a4c0..6ba3d73 100644
--- a/templates/python/sample-app/main.py
+++ b/templates/python/sample-app/main.py
@@ -17,7 +17,7 @@
Returns:
A dictionary containing the page title
Invoke this via CLI:
- export KERNEL_API_KEY=
+ kernel login # or: export KERNEL_API_KEY=
kernel deploy main.py # If you haven't already deployed this app
kernel invoke python-basic get-page-title -p '{"url": "https://www.google.com"}'
kernel logs python-basic -f # Open in separate tab
@@ -74,7 +74,7 @@ async def get_page_title(ctx: kernel.KernelContext, input_data: PageTitleInput)
Returns:
A dictionary containing the browser live view url
Invoke this via CLI:
- export KERNEL_API_KEY=
+ kernel login # or: export KERNEL_API_KEY=
kernel deploy main.py # If you haven't already deployed this app
kernel invoke python-basic create-persisted-browser
kernel logs python-basic -f # Open in separate tab
diff --git a/templates/typescript/advanced-sample/index.ts b/templates/typescript/advanced-sample/index.ts
index c213431..86bd531 100644
--- a/templates/typescript/advanced-sample/index.ts
+++ b/templates/typescript/advanced-sample/index.ts
@@ -8,20 +8,19 @@ const app = kernel.app("ts-advanced");
/**
* Example showing Kernel's auto-CAPTCHA solver
* Visit the live view url to see the Kernel browser auto-solve the CAPTCHA on the site
- *
+ *
* Args:
* ctx: Kernel context containing invocation information
* Returns:
* None
- *
+ *
* Invoke this via CLI:
- * export KERNEL_API_KEY=
+ * kernel login # or: export KERNEL_API_KEY=
* kernel deploy index.ts # If you haven't already deployed this app
* kernel invoke ts-advanced test-captcha-solver
* kernel logs ts-advanced -f # Open in separate tab
*/
-app.action("test-captcha-solver", async(ctx: KernelContext): Promise => {
-
+app.action("test-captcha-solver", async (ctx: KernelContext): Promise => {
const kernelBrowser = await kernel.browsers.create({
invocation_id: ctx.invocation_id,
stealth: true,
@@ -32,15 +31,18 @@ app.action("test-captcha-solver", async(ctx: KernelContext): Promise => {
const browser = await chromium.connectOverCDP(kernelBrowser.cdp_ws_url);
// Access the live view. Retrieve this live_view_url from the Kernel logs in your CLI:
- // export KERNEL_API_KEY=
+ // kernel login # or: export KERNEL_API_KEY=
// kernel logs ts-advanced --follow
- console.log("Kernel browser live view url: ", kernelBrowser.browser_live_view_url);
+ console.log(
+ "Kernel browser live view url: ",
+ kernelBrowser.browser_live_view_url
+ );
// Navigate to a site with a CAPTCHA
- const context = await browser.contexts()[0] || (await browser.newContext());
- const page = await context.pages()[0] || (await context.newPage());
+ const context = browser.contexts()[0] || (await browser.newContext());
+ const page = context.pages()[0] || (await context.newPage());
await page.waitForTimeout(10000); // Add a delay to give you time to visit the live view url
await page.goto("https://www.google.com/recaptcha/api2/demo");
// Watch Kernel auto-solve the CAPTCHA!
await browser.close();
-});
\ No newline at end of file
+});
diff --git a/templates/typescript/cua/index.ts b/templates/typescript/cua/index.ts
index 4b01c69..b4fc803 100644
--- a/templates/typescript/cua/index.ts
+++ b/templates/typescript/cua/index.ts
@@ -28,7 +28,7 @@ if (!process.env.OPENAI_API_KEY) {
* Returns:
* An answer to the task, elapsed time and optionally the messages stack
* Invoke this via CLI:
- * export KERNEL_API_KEY=
+ * kernel login # or: export KERNEL_API_KEY=
* kernel deploy index.ts -e OPENAI_API_KEY=XXXXX --force
* kernel invoke ts-cua cua-task -p "{\"task\":\"current market price range for a used dreamcast\"}"
* kernel logs ts-cua -f # Open in separate tab
diff --git a/templates/typescript/sample-app/index.ts b/templates/typescript/sample-app/index.ts
index 30b9688..c62df63 100644
--- a/templates/typescript/sample-app/index.ts
+++ b/templates/typescript/sample-app/index.ts
@@ -1,9 +1,9 @@
-import { Kernel, type KernelContext } from '@onkernel/sdk';
-import { chromium } from 'playwright';
+import { Kernel, type KernelContext } from "@onkernel/sdk";
+import { chromium } from "playwright";
const kernel = new Kernel();
-const app = kernel.app('ts-basic');
+const app = kernel.app("ts-basic");
/**
* Example app that extracts the title of a webpage
@@ -13,7 +13,7 @@ const app = kernel.app('ts-basic');
* Returns:
* A dictionary containing the page title
* Invoke this via CLI:
- * export KERNEL_API_KEY=
+ * kernel login # or: export KERNEL_API_KEY=
* kernel deploy index.ts # If you haven't already deployed this app
* kernel invoke ts-basic get-page-title -p '{"url": "https://www.google.com"}'
* kernel logs ts-basic -f # Open in separate tab
@@ -26,13 +26,19 @@ interface PageTitleOutput {
title: string;
}
app.action(
- 'get-page-title',
- async (ctx: KernelContext, payload?: PageTitleInput): Promise => {
+ "get-page-title",
+ async (
+ ctx: KernelContext,
+ payload?: PageTitleInput
+ ): Promise => {
if (!payload?.url) {
- throw new Error('URL is required');
+ throw new Error("URL is required");
}
-
- if (!payload.url.startsWith('http://') && !payload.url.startsWith('https://')) {
+
+ if (
+ !payload.url.startsWith("http://") &&
+ !payload.url.startsWith("https://")
+ ) {
payload.url = `https://${payload.url}`;
}
@@ -47,11 +53,14 @@ app.action(
invocation_id: ctx.invocation_id,
});
- console.log("Kernel browser live view url: ", kernelBrowser.browser_live_view_url);
+ console.log(
+ "Kernel browser live view url: ",
+ kernelBrowser.browser_live_view_url
+ );
const browser = await chromium.connectOverCDP(kernelBrowser.cdp_ws_url);
- const context = await browser.contexts()[0] || (await browser.newContext());
- const page = await context.pages()[0] || (await context.newPage());
+ const context = browser.contexts()[0] || (await browser.newContext());
+ const page = context.pages()[0] || (await context.newPage());
try {
//////////////////////////////////////
@@ -63,7 +72,7 @@ app.action(
} finally {
await browser.close();
}
- },
+ }
);
/**
@@ -75,7 +84,7 @@ app.action(
* Returns:
* A dictionary containing the browser live view url
* Invoke this via CLI:
- * export KERNEL_API_KEY=
+ * kernel login # or: export KERNEL_API_KEY=
* kernel deploy index.ts # If you haven't already deployed this app
* kernel invoke ts-basic create-persisted-browser
* kernel logs ts-basic -f # Open in separate tab
@@ -83,9 +92,9 @@ app.action(
interface CreatePersistedBrowserOutput {
browser_live_view_url: string;
}
-app.action("create-persisted-browser",
+app.action(
+ "create-persisted-browser",
async (ctx: KernelContext): Promise => {
-
const kernelBrowser = await kernel.browsers.create({
invocation_id: ctx.invocation_id,
persistence: {
@@ -98,4 +107,4 @@ app.action("create-persisted-browser",
browser_live_view_url: kernelBrowser.browser_live_view_url,
};
}
-);
\ No newline at end of file
+);