Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 131 additions & 7 deletions .docs/code-example-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@ This guide defines the standards for code examples across the Kernel documentati

## General Principles

1. **Complete and runnable**: Every code example should be complete enough to run as-is
1. **Context-aware completeness**: Full examples must run as-is. Focused snippets can rely
on variables introduced by surrounding text or sibling examples, but they must make those
dependencies obvious.
2. **Consistent naming**: Use standardized variable names across all examples
3. **No hardcoded credentials**: Never include API keys or credentials in examples
4. **Multi-language support**: When applicable, show both TypeScript/JavaScript and Python examples
3. **No real secrets**: Never include real API keys, passwords, tokens, or live credentials.
Use obviously fake values when an auth-flow example needs credential-shaped input.
4. **Multi-language support**: When applicable, show TypeScript/JavaScript, Python, and Go examples

## Variable Naming Conventions

Expand All @@ -27,8 +30,25 @@ This guide defines the standards for code examples across the Kernel documentati
- Context: `context`
- Page: `page`

### Go
- SDK client: `client`
- Browser instance: `kernelBrowser`
- Additional browsers: `kernelBrowser2`, etc.
- Context: `ctx`
- Session ID: `sessionID`
- Invocation ID: `invocationID`

## Code Example Structure

### Full examples vs focused snippets

Use a full example when the reader needs to copy and run a standalone program. Include imports,
SDK initialization, context setup, the main operation, and error handling.

Use a focused snippet when the page is walking through one step in a larger flow. Keep the snippet
small, but rely only on variables the page already introduced, such as `client`, `ctx`,
`kernelBrowser`, `auth`, or `browser`.

### Minimal Example (Browser Creation)

Always include:
Expand All @@ -55,6 +75,29 @@ kernel = Kernel()
kernel_browser = kernel.browsers.create()
print(kernel_browser.session_id)
```

```go Go
package main

import (
"context"
"fmt"

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

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

kernelBrowser, err := client.Browsers.New(ctx, kernel.BrowserNewParams{})
if err != nil {
panic(err)
}

fmt.Println(kernelBrowser.SessionID)
}
```
</CodeGroup>

### Full Example (With Browser Automation)
Expand Down Expand Up @@ -129,6 +172,16 @@ const kernel = new Kernel();
kernel = Kernel()
```

```go
package main

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

func main() {
_ = kernel.NewClient()
}
```

The SDK automatically reads the API key from the `KERNEL_API_KEY` environment variable.

### ❌ Incorrect - Hardcoded credentials
Expand All @@ -145,6 +198,22 @@ kernel = Kernel(api_key="your-api-key")
kernel = Kernel(api_key=os.getenv("KERNEL_API_KEY"))
```

```go
// DON'T DO THIS
package main

import (
"github.com/kernel/kernel-go-sdk"
"github.com/kernel/kernel-go-sdk/option"
)

func main() {
_ = kernel.NewClient(
option.WithAPIKey("your-api-key"),
)
}
```

## Feature-Specific Examples

### Simple Feature Toggle
Expand All @@ -171,6 +240,28 @@ kernel_browser = kernel.browsers.create(
stealth=True,
)
```

```go Go
package main

import (
"context"

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

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

_, err := client.Browsers.New(ctx, kernel.BrowserNewParams{
Stealth: kernel.Bool(true),
})
if err != nil {
panic(err)
}
}
```
</CodeGroup>

### Feature with Configuration
Expand All @@ -197,10 +288,36 @@ kernel_browser = kernel.browsers.create(
stealth=True
)
```

```go Go
package main

import (
"context"

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

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

kernelBrowser, err := client.Browsers.New(ctx, kernel.BrowserNewParams{
Stealth: kernel.Bool(true),
})
if err != nil {
panic(err)
}

_ = kernelBrowser
}
```
</CodeGroup>

## App Development Examples

Kernel app examples currently use TypeScript/JavaScript and Python. Add a Go version only after the Go SDK has documented app framework support and the snippet has been tested against that SDK.

For Kernel app examples, follow this pattern:

<CodeGroup>
Expand Down Expand Up @@ -299,17 +416,19 @@ finally:
### Indentation
- TypeScript/JavaScript: 2 spaces
- Python: 4 spaces
- Go: tabs from `gofmt`

### String Quotes
- TypeScript/JavaScript: Single quotes `'` (except for avoiding escaping)
- Python: Double quotes `"`
- Go: Double quotes `"`

### Line Length
- Keep lines under 100 characters when possible
- Break long parameter lists across multiple lines

### Comments
- Use comments sparingly - code should be self-explanatory
- Use comments sparingly; keep code self-explanatory
- Add comments only for non-obvious logic or important context
- Never add comments like "NEW CODE:" or similar meta-comments

Expand Down Expand Up @@ -340,6 +459,10 @@ Always use `<CodeGroup>` with proper language labels:
```python Python
# Python code here
```

```go Go
// Go code here
```
</CodeGroup>
````

Expand All @@ -350,11 +473,13 @@ Before publishing a code example, verify:
- [ ] Includes all necessary imports
- [ ] SDK is initialized without hardcoded API keys
- [ ] Variable names follow conventions
- [ ] Code is complete and runnable
- [ ] Code is complete and runnable, or it is a focused snippet with obvious prerequisites
- [ ] Includes error handling (for full examples)
- [ ] Includes cleanup code (for full examples)
- [ ] Uses proper indentation and formatting
- [ ] Both TypeScript and Python versions are provided (when applicable)
- [ ] TypeScript/JavaScript, Python, and Go versions are provided (when applicable)
- [ ] Go examples are formatted with `gofmt`
- [ ] Go examples are tested against the actual Go SDK version the docs claim to support
- [ ] Code has been tested or follows proven patterns

## Reference
Expand All @@ -363,4 +488,3 @@ See these files for examples:
- `introduction/create.mdx` - Standard browser creation pattern
- `apps/develop.mdx` - App development pattern
- `browsers/file-io.mdx` - Complex automation example

30 changes: 7 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,31 +11,15 @@ This is the documentation for the Kernel platform. It's connected to [onkernel.c

## Code Snippets

Code samples in the docs are generated from our OpenAPI spec so the examples stay in sync with the API. There are two ways the generator is invoked:
Code samples in the docs are authored inline in MDX. Keep SDK examples aligned with the SDK repos, and follow the standards in `.docs/code-example-guide.md` when adding or editing examples.

- Custom MDX tag: use `<OpenAPICodeGroup>get /api/v1/users</OpenAPICodeGroup>` (or omit the verb to use the default behavior).
When you add Go examples:

How the generator works (current behavior):

- The script is `.github/scripts/generate_code_samples.ts` and is executed with Bun. It fetches the OpenAPI spec from the URL configured at the top of that script.
- It reads `x-codeSamples` entries for each operation and extracts samples for TypeScript/JavaScript and Python. Samples are normalized and may be transformed by simple "overrides" (see the script for the override parsing and injection heuristics).
- It writes snippet files under `snippets/openapi/` as MDX files containing a `<CodeGroup>` with the generated code fences. It also updates any MDX files under `apps/` and `browsers/` that contain the inline or tag forms by replacing them with the generated `<CodeGroup>` blocks.
- The generator can produce a base snippet and additional variant snippets controlled by `.github/scripts/code_samples.config.json` (variants are keyed by `"method /path"`).
- The script also removes stale snippet files matching the `-.mdx` suffix pattern.

How it affects the repository:

- New or updated files are created under `snippets/openapi/*.mdx`.
- MDX pages in `apps/` and `browsers/` may be modified in-place to replace `<OpenAPICodeGroup>`/mustache tags with generated `<CodeGroup>` blocks.
- A GitHub Action (`.github/workflows/generate_code_snippets.yaml`) runs the script on push (except to `main`), commits any changes, and pushes them to the `gh_action_generated_docs` branch so Mintlify can deploy the generated docs.

Notes and gotchas:

- The generator runs remotely against the OpenAPI URL defined in the script, so it needs network access and the spec to include `x-codeSamples` for useful output.
- The override parsing and code injection are heuristic. Complex sample sources might not be transformed exactly as intended. See the script for details on how keys/`log` overrides are applied.
- The GitHub Action installs Bun and runs the script; if you run it locally, install Bun and run `bun run .github/scripts/generate_code_samples.ts` from the repo root.

Example: to add a snippet placeholder to a page, add `<OpenAPICodeGroup>get /api/v1/users</OpenAPICodeGroup>` and let the generator fill `snippets/openapi` and update the page during the next run.
- Test complete snippets, or wrapped focused snippets, against the minimum released Go SDK version
that supports the API you're documenting.
- Run `gofmt` on complete snippets and on wrapper files used to validate focused snippets before
publishing.
- Note the validation you ran in the pull request description.

## Local Development

Expand Down
55 changes: 55 additions & 0 deletions apps/invoke.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,33 @@ invocation = kernel.invocations.create(
)
print(invocation.id)
```

```go Go
package main

import (
"context"
"fmt"

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

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

invocation, err := client.Invocations.New(ctx, kernel.InvocationNewParams{
ActionName: "analyze",
AppName: "my-app",
Version: "1.0.0",
})
if err != nil {
panic(err)
}

fmt.Println(invocation.ID)
}
```
</CodeGroup>

### Asynchronous invocations
Expand Down Expand Up @@ -70,6 +97,34 @@ invocation = kernel.invocations.create(
)
print(invocation.id)
```

```go Go
package main

import (
"context"
"fmt"

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

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

invocation, err := client.Invocations.New(ctx, kernel.InvocationNewParams{
Async: kernel.Bool(true),
ActionName: "analyze",
AppName: "my-app",
Version: "1.0.0",
})
if err != nil {
panic(err)
}

fmt.Println(invocation.ID)
}
```
</CodeGroup>

## Via CLI
Expand Down
29 changes: 29 additions & 0 deletions apps/logs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,35 @@ from kernel import Kernel
kernel = Kernel()
logs = kernel.invocations.follow(invocation_id)
```

```go Go
package main

import (
"context"
"fmt"

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

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

logs := client.Invocations.FollowStreaming(ctx, "inv_123", kernel.InvocationFollowParams{})
defer logs.Close()

for logs.Next() {
event := logs.Current()
if event.Event == "log" {
fmt.Println(event.Message)
}
}
if err := logs.Err(); err != nil {
panic(err)
}
}
```
</CodeGroup>

<Info>Log lines will be truncated to 64KiB. For large payloads write data to external storage and log a reference instead.</Info>
Expand Down
Loading
Loading