Skip to main content
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:
{ "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.
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.
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' } },
);

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 — or use the CLI’s --project flag (see below).

Using Projects from the CLI

The Kernel CLI has first-class project support:
  • A global --project <id-or-name> flag scopes any command to a single project. Names are resolved case-insensitively, so --project staging works.
  • 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.
# 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

Use the /projects REST endpoints (or the SDKs’ projects resource) to manage projects.
MethodPathDescription
GET/projectsList projects in the organization
POST/projectsCreate 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}/limitsGet per-project concurrency limit overrides
PATCH/projects/{id}/limitsUpdate per-project concurrency limit overrides

Create a project

import Kernel from '@onkernel/sdk';

const kernel = new Kernel();

const project = await kernel.projects.create({ name: 'staging' });
console.log(project.id); // proj_abc123

List projects

for await (const project of kernel.projects.list()) {
  console.log(project.id, project.name, project.status);
}

Update a project

await kernel.projects.update('proj_abc123', { name: 'production' });

Delete a project

await 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 for full request and response schemas, including ProjectLimits for per-project concurrency caps.