From 90d64b41de195f807df9bad07518114f14031c39 Mon Sep 17 00:00:00 2001
From: hiroTamada <88675973+hiroTamada@users.noreply.github.com>
Date: Thu, 23 Apr 2026 20:15:58 +0000
Subject: [PATCH 1/7] Add Projects docs page
Documents the Projects feature: Default project backfill, deletion
rules, API key scoping, OAuth behavior, X-Kernel-Project-Id header,
SDK usage, and CRUD endpoints.
---
docs.json | 1 +
info/projects.mdx | 167 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 168 insertions(+)
create mode 100644 info/projects.mdx
diff --git a/docs.json b/docs.json
index 949528b..4980195 100644
--- a/docs.json
+++ b/docs.json
@@ -213,6 +213,7 @@
"pages": [
"browsers/faq",
"info/concepts",
+ "info/projects",
"info/pricing",
"info/support",
"info/unikernels"
diff --git a/info/projects.mdx b/info/projects.mdx
new file mode 100644
index 0000000..64c912b
--- /dev/null
+++ b/info/projects.mdx
@@ -0,0 +1,167 @@
+---
+title: "Projects"
+description: "Organize resources and isolate access within your Kernel organization"
+---
+
+A **Project** is a named container for Kernel resources inside an organization. Use projects to separate environments (like `production` and `staging`), split resources between teams, or isolate customer workloads — each project has its own browsers, profiles, credentials, proxies, extensions, deployments, and pools.
+
+## Why Projects?
+
+- **Isolate environments** — keep `production` resources apart from `staging` or experiments.
+- **Scope access** — issue API keys that can only see resources in one project.
+- **Per-project limits** — cap concurrency on a per-project basis so one team or environment can't exhaust your org quota.
+
+## The Default Project
+
+Every organization has at least one project. Resources that existed before projects were introduced have been moved into a project named **Default**, so your existing browsers, apps, profiles, and other resources continue to work without any changes on your end.
+
+Your organization must always have **at least one active project**. The API returns `409 Conflict` if you try to delete the last remaining project:
+
+```json
+{ "code": "conflict", "message": "organization must have at least one project" }
+```
+
+A project must also be empty before it can be deleted — archive or remove its active resources first.
+
+## Scoping Requests to a Project
+
+Pass the `X-Kernel-Project-Id` header on any API request to scope it to a specific project. Without the header (and without a project-scoped API key), requests operate org-wide.
+
+```bash
+curl https://api.onkernel.com/browsers \
+ -H "Authorization: Bearer $KERNEL_API_KEY" \
+ -H "X-Kernel-Project-Id: proj_abc123"
+```
+
+### SDK usage
+
+Set the header on the client so every request is scoped to the project. You can also override it per-request.
+
+
+```typescript TypeScript
+import Kernel from '@onkernel/sdk';
+
+// Scope the whole client to a project
+const kernel = new Kernel({
+ defaultHeaders: { 'X-Kernel-Project-Id': 'proj_abc123' },
+});
+
+const browser = await kernel.browsers.create();
+
+// Or override per-request
+const other = await kernel.browsers.create(
+ {},
+ { headers: { 'X-Kernel-Project-Id': 'proj_def456' } },
+);
+```
+
+```python Python
+from kernel import Kernel
+
+# Scope the whole client to a project
+kernel = Kernel(
+ default_headers={"X-Kernel-Project-Id": "proj_abc123"},
+)
+
+browser = kernel.browsers.create()
+
+# Or override per-request
+other = kernel.browsers.create(
+ extra_headers={"X-Kernel-Project-Id": "proj_def456"},
+)
+```
+
+
+## Authentication and Project Scope
+
+### API keys
+
+API keys can be **org-wide** or **project-scoped**.
+
+- **Existing API keys are org-wide.** They see every resource in your organization across all projects. Include an `X-Kernel-Project-Id` header to restrict a single request to one project.
+- **Project-scoped API keys** can only access resources inside the project they were issued for. Create one from the **API Keys** page in the dashboard and pick the target project when generating the key. Requests made with a scoped key are automatically limited to that project — no header required. If you do send an `X-Kernel-Project-Id` header and it conflicts with the key's project, the request is rejected with `403 Forbidden`.
+
+### OAuth
+
+OAuth tokens (used by the Kernel CLI and MCP server) are **always org-wide**. You cannot bind an OAuth session to a single project. To scope OAuth-authenticated requests, send the `X-Kernel-Project-Id` header with each request.
+
+## Managing Projects
+
+Use the `/projects` REST endpoints (or the SDKs' `projects` resource) to manage projects.
+
+| Method | Path | Description |
+| --- | --- | --- |
+| `GET` | `/projects` | List projects in the organization |
+| `POST` | `/projects` | Create a project |
+| `GET` | `/projects/{id}` | Get a project by ID |
+| `PATCH` | `/projects/{id}` | Update a project's name or status (`active` / `archived`) |
+| `DELETE` | `/projects/{id}` | Delete a project (must be empty and not the last active project) |
+| `GET` | `/projects/{id}/limits` | Get per-project concurrency limit overrides |
+| `PATCH` | `/projects/{id}/limits` | Update per-project concurrency limit overrides |
+
+### Create a project
+
+
+```typescript TypeScript
+import Kernel from '@onkernel/sdk';
+
+const kernel = new Kernel();
+
+const project = await kernel.projects.create({ name: 'staging' });
+console.log(project.id); // proj_abc123
+```
+
+```python Python
+from kernel import Kernel
+
+kernel = Kernel()
+
+project = kernel.projects.create(name="staging")
+print(project.id) # proj_abc123
+```
+
+
+### List projects
+
+
+```typescript TypeScript
+for await (const project of kernel.projects.list()) {
+ console.log(project.id, project.name, project.status);
+}
+```
+
+```python Python
+for project in kernel.projects.list():
+ print(project.id, project.name, project.status)
+```
+
+
+### Update a project
+
+
+```typescript TypeScript
+await kernel.projects.update('proj_abc123', { name: 'production' });
+```
+
+```python Python
+kernel.projects.update("proj_abc123", name="production")
+```
+
+
+### Delete a project
+
+
+```typescript TypeScript
+await kernel.projects.delete('proj_abc123');
+```
+
+```python Python
+kernel.projects.delete("proj_abc123")
+```
+
+
+
+ You can't delete a project that still owns active resources, and you can't delete the last remaining active project in your org.
+
+
+See the [API reference](https://kernel.sh/docs/api-reference/projects/list-projects) for full request and response schemas, including `ProjectLimits` for per-project concurrency caps.
From 43765a043201757733defa34682b57e2996ad4b7 Mon Sep 17 00:00:00 2001
From: hiroTamada <88675973+hiroTamada@users.noreply.github.com>
Date: Thu, 23 Apr 2026 20:32:45 +0000
Subject: [PATCH 2/7] Document CLI projects support
Add reference/cli/projects.mdx covering `kernel projects` subcommands
and the global `--project` flag + KERNEL_PROJECT env var. Link from
the CLI overview, add to nav, and cross-reference from info/projects.
---
docs.json | 1 +
info/projects.mdx | 26 +++++++++++-
reference/cli.mdx | 4 ++
reference/cli/projects.mdx | 83 ++++++++++++++++++++++++++++++++++++++
4 files changed, 113 insertions(+), 1 deletion(-)
create mode 100644 reference/cli/projects.mdx
diff --git a/docs.json b/docs.json
index 4980195..d9b508c 100644
--- a/docs.json
+++ b/docs.json
@@ -233,6 +233,7 @@
"reference/cli/auth",
"reference/cli/browsers",
"reference/cli/apps",
+ "reference/cli/projects",
"reference/cli/mcp",
"reference/cli/extensions"
]
diff --git a/info/projects.mdx b/info/projects.mdx
index 64c912b..d697709 100644
--- a/info/projects.mdx
+++ b/info/projects.mdx
@@ -83,7 +83,31 @@ API keys can be **org-wide** or **project-scoped**.
### OAuth
-OAuth tokens (used by the Kernel CLI and MCP server) are **always org-wide**. You cannot bind an OAuth session to a single project. To scope OAuth-authenticated requests, send the `X-Kernel-Project-Id` header with each request.
+OAuth tokens (used by the Kernel CLI and MCP server) are **always org-wide**. You cannot bind an OAuth session to a single project. To scope OAuth-authenticated requests, send the `X-Kernel-Project-Id` header with each request — or use the CLI's `--project` flag (see below).
+
+## Using Projects from the CLI
+
+The Kernel [CLI](/reference/cli/projects) has first-class project support:
+
+- A global `--project ` flag scopes any command to a single project. Names are resolved case-insensitively, so `--project staging` works.
+- The `KERNEL_PROJECT` (and legacy `KERNEL_PROJECT_ID`) environment variable does the same, so you can set it once in your shell or CI.
+- A `kernel projects` command group lets you list, create, get, and delete projects, and manage per-project limit overrides.
+
+```bash
+# Scope a single command
+kernel browsers list --project staging
+
+# Scope every command in the shell
+export KERNEL_PROJECT=staging
+kernel apps list
+
+# Manage projects
+kernel projects list
+kernel projects create staging
+kernel projects limits set staging --max-concurrent-sessions 5
+```
+
+Under the hood, `--project` (or the env var) adds the `X-Kernel-Project-Id` header to every authenticated request. It's the recommended way to target a specific project when you're logged in with OAuth (`kernel login`), since OAuth itself is always org-wide.
## Managing Projects
diff --git a/reference/cli.mdx b/reference/cli.mdx
index 44f7b4a..8ab3939 100644
--- a/reference/cli.mdx
+++ b/reference/cli.mdx
@@ -43,6 +43,9 @@ kernel --version
Install Kernel MCP server configuration for AI tools.
+
+ Manage projects and scope commands with `--project`.
+
## Quick Start
@@ -66,6 +69,7 @@ kernel invoke my-app action-name --payload '{"key":"value"}'
- `--version`, `-v` - Print the CLI version
- `--no-color` - Disable color output
- `--log-level ` - Set the log level (trace, debug, info, warn, error, fatal, print)
+- `--project ` - Scope the request to a specific [project](/reference/cli/projects) (also reads `KERNEL_PROJECT` or `KERNEL_PROJECT_ID`)
## JSON Output
diff --git a/reference/cli/projects.mdx b/reference/cli/projects.mdx
new file mode 100644
index 0000000..bb63287
--- /dev/null
+++ b/reference/cli/projects.mdx
@@ -0,0 +1,83 @@
+---
+title: "Projects"
+---
+
+Manage [Projects](/info/projects) from the CLI and scope other commands to a specific project.
+
+## Scoping commands to a project
+
+Use the global `--project` flag (or the `KERNEL_PROJECT` / `KERNEL_PROJECT_ID` environment variable) to scope any `kernel` command to a project. The flag accepts either a **project ID** or a **project name** — names are resolved case-insensitively by listing your projects.
+
+```bash
+# Scope a single command by name
+kernel browsers list --project staging
+
+# Scope by ID
+kernel browsers list --project proj_abc123
+
+# Scope via environment variable
+export KERNEL_PROJECT=staging
+kernel apps list
+```
+
+Under the hood, the flag adds the `X-Kernel-Project-Id` header to every authenticated API request. OAuth-based logins (`kernel login`) remain org-wide by default, so this is the recommended way to target a single project when logged in with OAuth.
+
+
+ Project-scoped API keys are already bound to a project server-side, so you don't need `--project` when using them — but if you do pass it, it must match the key's project or the request is rejected.
+
+
+If the name is ambiguous (multiple projects share it) or no match is found, the CLI returns a clear error; pass the project ID instead.
+
+## Commands
+
+### `kernel projects list`
+
+List all projects in the authenticated organization.
+
+### `kernel projects create `
+
+Create a new project with the given name.
+
+```bash
+kernel projects create staging
+```
+
+### `kernel projects get `
+
+Show details for a project by ID or name.
+
+### `kernel projects delete `
+
+Delete a project. The project must be empty, and it can't be the last active project in the org.
+
+## Project limits
+
+Each project can have its own concurrency limit overrides that cap resource use below the org-wide limits.
+
+### `kernel projects limits get `
+
+Show the per-project limit overrides. Fields show `unlimited` when no project-level cap is set (the org limit applies).
+
+| Flag | Description |
+|------|-------------|
+| `--output json`, `-o json` | Output raw JSON object. |
+
+### `kernel projects limits set `
+
+Update per-project limit overrides. Pass `0` to a limit to remove the cap for that field.
+
+| Flag | Description |
+|------|-------------|
+| `--max-concurrent-sessions ` | Maximum concurrent browser sessions (0 to remove cap). |
+| `--max-persistent-sessions ` | Maximum persistent browser sessions (0 to remove cap). |
+| `--max-concurrent-invocations ` | Maximum concurrent app invocations (0 to remove cap). |
+| `--max-pooled-sessions ` | Maximum pooled sessions capacity (0 to remove cap). |
+| `--output json`, `-o json` | Output raw JSON object. |
+
+```bash
+# Cap staging to 5 concurrent browser sessions
+kernel projects limits set staging --max-concurrent-sessions 5
+
+# Remove the cap
+kernel projects limits set staging --max-concurrent-sessions 0
+```
From cbc9b21c987fe6770a3161d15f5f20290a2c5a77 Mon Sep 17 00:00:00 2001
From: hiroTamada <88675973+hiroTamada@users.noreply.github.com>
Date: Thu, 23 Apr 2026 20:34:17 +0000
Subject: [PATCH 3/7] Drop KERNEL_PROJECT_ID from CLI project docs
KERNEL_PROJECT_ID has never shipped; only document the supported
KERNEL_PROJECT env var.
---
info/projects.mdx | 2 +-
reference/cli.mdx | 2 +-
reference/cli/projects.mdx | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/info/projects.mdx b/info/projects.mdx
index d697709..2a42164 100644
--- a/info/projects.mdx
+++ b/info/projects.mdx
@@ -90,7 +90,7 @@ OAuth tokens (used by the Kernel CLI and MCP server) are **always org-wide**. Yo
The Kernel [CLI](/reference/cli/projects) has first-class project support:
- A global `--project ` flag scopes any command to a single project. Names are resolved case-insensitively, so `--project staging` works.
-- The `KERNEL_PROJECT` (and legacy `KERNEL_PROJECT_ID`) environment variable does the same, so you can set it once in your shell or CI.
+- The `KERNEL_PROJECT` environment variable does the same, so you can set it once in your shell or CI.
- A `kernel projects` command group lets you list, create, get, and delete projects, and manage per-project limit overrides.
```bash
diff --git a/reference/cli.mdx b/reference/cli.mdx
index 8ab3939..5c3c4f4 100644
--- a/reference/cli.mdx
+++ b/reference/cli.mdx
@@ -69,7 +69,7 @@ kernel invoke my-app action-name --payload '{"key":"value"}'
- `--version`, `-v` - Print the CLI version
- `--no-color` - Disable color output
- `--log-level ` - Set the log level (trace, debug, info, warn, error, fatal, print)
-- `--project ` - Scope the request to a specific [project](/reference/cli/projects) (also reads `KERNEL_PROJECT` or `KERNEL_PROJECT_ID`)
+- `--project ` - Scope the request to a specific [project](/reference/cli/projects) (also reads the `KERNEL_PROJECT` env var)
## JSON Output
diff --git a/reference/cli/projects.mdx b/reference/cli/projects.mdx
index bb63287..ff2fe45 100644
--- a/reference/cli/projects.mdx
+++ b/reference/cli/projects.mdx
@@ -6,7 +6,7 @@ Manage [Projects](/info/projects) from the CLI and scope other commands to a spe
## Scoping commands to a project
-Use the global `--project` flag (or the `KERNEL_PROJECT` / `KERNEL_PROJECT_ID` environment variable) to scope any `kernel` command to a project. The flag accepts either a **project ID** or a **project name** — names are resolved case-insensitively by listing your projects.
+Use the global `--project` flag (or the `KERNEL_PROJECT` environment variable) to scope any `kernel` command to a project. The flag accepts either a **project ID** or a **project name** — names are resolved case-insensitively by listing your projects.
```bash
# Scope a single command by name
From b1f37d21c94c58c3f9f78bfd94ced30d1531f335 Mon Sep 17 00:00:00 2001
From: hiroTamada <88675973+hiroTamada@users.noreply.github.com>
Date: Thu, 23 Apr 2026 21:36:53 +0000
Subject: [PATCH 4/7] Move projects page to Intermediate section
---
docs.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs.json b/docs.json
index d9b508c..ee30183 100644
--- a/docs.json
+++ b/docs.json
@@ -87,6 +87,7 @@
"group": "Intermediate",
"expanded": true,
"pages": [
+ "info/projects",
"browsers/replays",
"browsers/viewport",
"browsers/gpu-acceleration",
@@ -213,7 +214,6 @@
"pages": [
"browsers/faq",
"info/concepts",
- "info/projects",
"info/pricing",
"info/support",
"info/unikernels"
From 6990d6f77318e8ea5862ae0b1d87a4114236477f Mon Sep 17 00:00:00 2001
From: hiroTamada <88675973+hiroTamada@users.noreply.github.com>
Date: Thu, 23 Apr 2026 21:42:39 +0000
Subject: [PATCH 5/7] Move projects to bottom of Intermediate section
---
docs.json | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs.json b/docs.json
index ee30183..1d39a23 100644
--- a/docs.json
+++ b/docs.json
@@ -87,7 +87,6 @@
"group": "Intermediate",
"expanded": true,
"pages": [
- "info/projects",
"browsers/replays",
"browsers/viewport",
"browsers/gpu-acceleration",
@@ -110,7 +109,8 @@
"browsers/file-io",
"browsers/ssh",
"browsers/computer-controls",
- "browsers/playwright-execution"
+ "browsers/playwright-execution",
+ "info/projects"
]
},
{
From b3dd354c029bec2800448dd0e197fd061c362e93 Mon Sep 17 00:00:00 2001
From: hiroTamada <88675973+hiroTamada@users.noreply.github.com>
Date: Thu, 23 Apr 2026 21:43:41 +0000
Subject: [PATCH 6/7] Move projects to bottom of Basics section
---
docs.json | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/docs.json b/docs.json
index 1d39a23..b3a1a75 100644
--- a/docs.json
+++ b/docs.json
@@ -80,7 +80,8 @@
"browsers/live-view",
"browsers/termination",
"browsers/standby",
- "browsers/headless"
+ "browsers/headless",
+ "info/projects"
]
},
{
@@ -109,8 +110,7 @@
"browsers/file-io",
"browsers/ssh",
"browsers/computer-controls",
- "browsers/playwright-execution",
- "info/projects"
+ "browsers/playwright-execution"
]
},
{
From dc1a077004737320580b989de48ddff18d3ccc01 Mon Sep 17 00:00:00 2001
From: hiroTamada <88675973+hiroTamada@users.noreply.github.com>
Date: Thu, 23 Apr 2026 21:44:43 +0000
Subject: [PATCH 7/7] Drop persistent sessions flag from projects limits docs
---
reference/cli/projects.mdx | 1 -
1 file changed, 1 deletion(-)
diff --git a/reference/cli/projects.mdx b/reference/cli/projects.mdx
index ff2fe45..1312878 100644
--- a/reference/cli/projects.mdx
+++ b/reference/cli/projects.mdx
@@ -69,7 +69,6 @@ Update per-project limit overrides. Pass `0` to a limit to remove the cap for th
| Flag | Description |
|------|-------------|
| `--max-concurrent-sessions ` | Maximum concurrent browser sessions (0 to remove cap). |
-| `--max-persistent-sessions ` | Maximum persistent browser sessions (0 to remove cap). |
| `--max-concurrent-invocations ` | Maximum concurrent app invocations (0 to remove cap). |
| `--max-pooled-sessions ` | Maximum pooled sessions capacity (0 to remove cap). |
| `--output json`, `-o json` | Output raw JSON object. |