diff --git a/docs.json b/docs.json index 949528b..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" ] }, { @@ -232,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 new file mode 100644 index 0000000..2a42164 --- /dev/null +++ b/info/projects.mdx @@ -0,0 +1,191 @@ +--- +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 — 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` 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 + +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. diff --git a/reference/cli.mdx b/reference/cli.mdx index 44f7b4a..5c3c4f4 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 the `KERNEL_PROJECT` env var) ## JSON Output diff --git a/reference/cli/projects.mdx b/reference/cli/projects.mdx new file mode 100644 index 0000000..1312878 --- /dev/null +++ b/reference/cli/projects.mdx @@ -0,0 +1,82 @@ +--- +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` 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-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 +```