Skip to content
Open
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
13 changes: 6 additions & 7 deletions .github/workflows/sdk-coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@ jobs:
const testsPassed = '${{ steps.tests.outcome }}' === 'success';
const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
const COMMENT_MARKER = '<!-- sdk-coverage-report -->';

let lines = [COMMENT_MARKER];

if (!testsPassed) {
let failedTests = [];
try {
Expand Down Expand Up @@ -173,17 +173,17 @@ jobs:
lines.push(`[📋 View workflow run](${runUrl})`);
}
}

const comment = lines.join('\n');

const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number
});

const existingComment = comments.find(c => c.body.includes(COMMENT_MARKER));

if (existingComment) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
Expand All @@ -199,4 +199,3 @@ jobs:
body: comment
});
}

2 changes: 1 addition & 1 deletion .github/workflows/smoke-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ on:
required: true
type: string
discriminator:
default: "true"
default: 'true'
type: string
workflow_dispatch:
inputs:
Expand Down
35 changes: 35 additions & 0 deletions EXAMPLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@ Runnable examples live in [`examples/`](./examples).
- [Secrets with Devbox and Agent Gateway](#secrets-with-devbox)

<a id="blueprint-with-build-context"></a>

## Blueprint with Build Context

**Use case:** Create a blueprint using the object store to provide docker build context files, then verify files are copied into the image.

**Tags:** `blueprint`, `object-store`, `build-context`, `devbox`, `cleanup`

### Workflow

- Create a temporary directory with sample application files
- Upload the directory to object storage as build context
- Create a blueprint with a Dockerfile that copies the context files
Expand All @@ -31,28 +33,33 @@ Runnable examples live in [`examples/`](./examples).
- Shutdown devbox and delete blueprint and storage object

### Prerequisites

- `RUNLOOP_API_KEY`

### Run

```sh
yarn tsn -T examples/blueprint-with-build-context.ts
```

### Test

```sh
yarn test:examples
```

**Source:** [`examples/blueprint-with-build-context.ts`](./examples/blueprint-with-build-context.ts)

<a id="devbox-from-blueprint-lifecycle"></a>

## Devbox From Blueprint (Run Command, Shutdown)

**Use case:** Create a devbox from a blueprint, run a command, fetch logs, validate output, and cleanly tear everything down.

**Tags:** `devbox`, `blueprint`, `commands`, `logs`, `cleanup`

### Workflow

- Create a blueprint
- Fetch blueprint build logs
- Create a devbox from the blueprint
Expand All @@ -62,28 +69,33 @@ yarn test:examples
- Shutdown devbox and delete blueprint

### Prerequisites

- `RUNLOOP_API_KEY`

### Run

```sh
yarn tsn -T examples/devbox-from-blueprint-lifecycle.ts
```

### Test

```sh
yarn test:examples
```

**Source:** [`examples/devbox-from-blueprint-lifecycle.ts`](./examples/devbox-from-blueprint-lifecycle.ts)

<a id="devbox-mounts"></a>

## Devbox Mounts (Agent, Code, Object)

**Use case:** Launch a devbox that combines an agent mount for Claude Code, a code mount for the Runloop CLI repo, and an object mount for startup files.

**Tags:** `devbox`, `mounts`, `agent`, `code`, `object`, `claude-code`, `agent-gateway`, `ttl`

### Workflow

- Create or reuse an agent by name
- Create a secret for an agent and route it through agent gateway
- Upload a temporary directory as a storage object with a TTL
Expand All @@ -93,29 +105,34 @@ yarn test:examples
- Shutdown the devbox and delete the temporary secret and object

### Prerequisites

- `RUNLOOP_API_KEY`
- `ANTHROPIC_API_KEY`

### Run

```sh
ANTHROPIC_API_KEY=sk-ant-xxx yarn tsn -T examples/devbox-mounts.ts
```

### Test

```sh
yarn test:examples
```

**Source:** [`examples/devbox-mounts.ts`](./examples/devbox-mounts.ts)

<a id="devbox-snapshots"></a>

## Devbox Snapshots (Suspend, Resume, Restore, Delete)

**Use case:** Upload a file to a devbox, preserve it across suspend and resume, create a disk snapshot, restore multiple devboxes from that snapshot, mutate each copy independently, and delete the snapshot when finished.

**Tags:** `devbox`, `snapshot`, `suspend`, `resume`, `files`, `cleanup`

### Workflow

- Create a source devbox
- Upload a file and mutate it into a shared baseline
- Suspend and resume the source devbox
Expand All @@ -125,28 +142,33 @@ yarn test:examples
- Shutdown the devboxes and delete the snapshot

### Prerequisites

- `RUNLOOP_API_KEY`

### Run

```sh
yarn tsn -T examples/devbox-snapshots.ts
```

### Test

```sh
yarn test:examples
```

**Source:** [`examples/devbox-snapshots.ts`](./examples/devbox-snapshots.ts)

<a id="devbox-tunnel"></a>

## Devbox Tunnel (HTTP Server Access)

**Use case:** Create a devbox with a tunnel, start an HTTP server, and access the server from the local machine through the tunnel.

**Tags:** `devbox`, `tunnel`, `networking`, `http`

### Workflow

- Create a devbox with a tunnel
- Start an HTTP server inside the devbox
- Read the tunnel details from the devbox
Expand All @@ -155,28 +177,33 @@ yarn test:examples
- Shutdown the devbox

### Prerequisites

- `RUNLOOP_API_KEY`

### Run

```sh
yarn tsn -T examples/devbox-tunnel.ts
```

### Test

```sh
yarn test:examples
```

**Source:** [`examples/devbox-tunnel.ts`](./examples/devbox-tunnel.ts)

<a id="mcp-github-tools"></a>

## MCP Hub + Claude Code + GitHub

**Use case:** Connect Claude Code running in a devbox to GitHub tools through MCP Hub without exposing raw GitHub credentials to the devbox.

**Tags:** `mcp`, `devbox`, `github`, `commands`, `cleanup`

### Workflow

- Create an MCP config for GitHub
- Store GitHub token as a Runloop secret
- Launch a devbox with MCP Hub wiring
Expand All @@ -185,30 +212,35 @@ yarn test:examples
- Shutdown devbox and clean up cloud resources

### Prerequisites

- `RUNLOOP_API_KEY`
- `GITHUB_TOKEN (GitHub PAT with repo scope)`
- `ANTHROPIC_API_KEY`

### Run

```sh
GITHUB_TOKEN=ghp_xxx ANTHROPIC_API_KEY=sk-ant-xxx yarn tsn -T examples/mcp-github-tools.ts
```

### Test

```sh
yarn test:examples
```

**Source:** [`examples/mcp-github-tools.ts`](./examples/mcp-github-tools.ts)

<a id="secrets-with-devbox"></a>

## Secrets with Devbox and Agent Gateway

**Use case:** Use a normal secret for sensitive app data in the devbox and agent gateway for upstream API credentials that should never be exposed to the agent.

**Tags:** `secrets`, `devbox`, `agent-gateway`, `credentials`, `environment-variables`, `cleanup`

### Workflow

- Create a secret for application data that should be available inside the devbox
- Create a separate secret for an upstream API credential
- Create an agent gateway config for an upstream API
Expand All @@ -217,14 +249,17 @@ yarn test:examples
- Shutdown the devbox and delete the gateway config and both secrets

### Prerequisites

- `RUNLOOP_API_KEY`

### Run

```sh
yarn tsn -T examples/secrets-with-devbox.ts
```

### Test

```sh
yarn test:examples
```
Expand Down
8 changes: 2 additions & 6 deletions packages/mcp-server/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@
"entry_point": "index.js",
"mcp_config": {
"command": "node",
"args": [
"${__dirname}/index.js"
],
"args": ["${__dirname}/index.js"],
"env": {
"RUNLOOP_API_KEY": "${user_config.RUNLOOP_API_KEY}"
}
Expand All @@ -41,7 +39,5 @@
"node": ">=18.0.0"
}
},
"keywords": [
"api"
]
"keywords": ["api"]
}
18 changes: 10 additions & 8 deletions scripts/generate-examples-md.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,7 @@ function readExampleFiles() {
.readdirSync(EXAMPLES_DIR)
.filter(
(file) =>
file.endsWith('.ts') &&
!file.startsWith('_') &&
file !== 'types.ts' &&
file !== 'registry.ts',
file.endsWith('.ts') && !file.startsWith('_') && file !== 'types.ts' && file !== 'registry.ts',
)
.sort();
}
Expand Down Expand Up @@ -107,9 +104,7 @@ function ensureLlmsReferences(examples) {
}

if (referencedFiles.size === 0) {
throw new Error(
`${path.relative(ROOT, LLMS_FILE)}: expected at least one reference to examples/*.ts`,
);
throw new Error(`${path.relative(ROOT, LLMS_FILE)}: expected at least one reference to examples/*.ts`);
}

const generatedFiles = new Set(examples.map((example) => example.fileName));
Expand All @@ -125,24 +120,29 @@ function ensureLlmsReferences(examples) {
function markdownForExample(example) {
return [
`<a id="${example.slug}"></a>`,
'',
`## ${example.title}`,
'',
`**Use case:** ${example.use_case}`,
'',
`**Tags:** ${example.tags.map((tag) => `\`${tag}\``).join(', ')}`,
'',
'### Workflow',
'',
...example.workflow.map((step) => `- ${step}`),
'',
'### Prerequisites',
'',
...example.prerequisites.map((item) => `- \`${item}\``),
'',
'### Run',
'',
'```sh',
example.run,
'```',
'',
'### Test',
'',
'```sh',
example.test,
'```',
Expand Down Expand Up @@ -256,7 +256,9 @@ function main() {
fs.writeFileSync(OUTPUT_FILE, markdown);
fs.writeFileSync(OUTPUT_REGISTRY_FILE, registrySource);
process.stdout.write(`Wrote ${path.relative(ROOT, OUTPUT_FILE)} from ${examples.length} example(s)\n`);
process.stdout.write(`Wrote ${path.relative(ROOT, OUTPUT_REGISTRY_FILE)} from ${examples.length} example(s)\n`);
process.stdout.write(
`Wrote ${path.relative(ROOT, OUTPUT_REGISTRY_FILE)} from ${examples.length} example(s)\n`,
);
}

main();
Loading