Skip to content
Open
Show file tree
Hide file tree
Changes from 10 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
51 changes: 49 additions & 2 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,30 @@ jobs:
timeout-minutes: 5
outputs:
supported_pythons: ${{ env.SUPPORTED_PYTHONS }}
playground_changed: ${{ steps.playground-changes.outputs.changed }}
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- run: echo "supported_pythons=$SUPPORTED_PYTHONS"
- name: Check playground changes
id: playground-changes
env:
BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.merge_group.base_sha || github.event.before }}
run: |
if [[ "${{ github.event_name }}" == "workflow_dispatch" || -z "$BASE_SHA" || "$BASE_SHA" =~ ^0+$ ]]; then
echo "changed=true" >> "$GITHUB_OUTPUT"
elif git diff --quiet "$BASE_SHA" "$GITHUB_SHA" -- \
.github/workflows/ci.yaml \
mise.lock \
mise.toml \
playground-tests \
'pkg/cli/playground*' \
pkg/cli/root.go; then
echo "changed=false" >> "$GITHUB_OUTPUT"
else
echo "changed=true" >> "$GITHUB_OUTPUT"
fi

# =============================================================================
# Version Check - Validates VERSION.txt format and sync
Expand Down Expand Up @@ -211,6 +233,25 @@ jobs:
name: CogBinary
path: cog

test-playground:
name: Test playground
needs: setup
if: needs.setup.outputs.playground_changed == 'true'
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v6
with:
node-version: 24.18.0
- uses: jdx/mise-action@v4
with:
version: 2026.4.27
cache_key_prefix: mise-ci-${{ github.job }}
- name: Test playground
run: |
mise run test:playground
go test ./pkg/cli -run '^(TestPlayground|TestVendorAssets)' -count=1
# =============================================================================
# Format Checks - Fast, parallel
# =============================================================================
Expand Down Expand Up @@ -696,6 +737,7 @@ jobs:
name: CI Complete
needs:
- setup
- test-playground
- version-check
- build-cog
- build-sdk
Expand Down Expand Up @@ -725,6 +767,7 @@ jobs:
- name: Check job results
run: |
echo "Job results:"
echo " test-playground: ${{ needs.test-playground.result }}"
echo " version-check: ${{ needs.version-check.result }}"
echo " build-cog: ${{ needs.build-cog.result }}"
echo " build-sdk: ${{ needs.build-sdk.result }}"
Expand All @@ -748,8 +791,7 @@ jobs:
echo " integration-shards: ${{ needs.integration-shards.result }}"
echo " test-integration: ${{ needs.test-integration.result }}"

# Fail if any required job failed.
# lint-rust-advisories is excluded: it uses continue-on-error because
# Fail if any required job failed. lint-rust-advisories is excluded:
# advisory DB updates shouldn't block unrelated PRs.
FAILED=false
for result in \
Expand Down Expand Up @@ -781,6 +823,11 @@ jobs:
fi
done

if [ "${{ needs.setup.outputs.playground_changed }}" = "true" ] && \
{ [ "${{ needs.test-playground.result }}" = "failure" ] || [ "${{ needs.test-playground.result }}" = "cancelled" ]; }; then
FAILED=true
fi

if [ "$FAILED" = "true" ]; then
echo "::error::Some jobs failed or were cancelled"
exit 1
Expand Down
7 changes: 6 additions & 1 deletion .github/workflows/release-build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ on:
tags: ["v[0-9]+.[0-9]+.[0-9]+*"]

permissions:
contents: write
contents: read

env:
CARGO_TERM_COLOR: always
Expand Down Expand Up @@ -298,6 +298,8 @@ jobs:

create-release:
name: Create release
permissions:
contents: write
needs: [verify-tag, build-sdk, build-coglet-wheels]
# macOS arm64 runner: native clang for darwin targets, zig for linux targets.
# CGo required for go-tree-sitter (static Python schema parser).
Expand Down Expand Up @@ -327,6 +329,9 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Verify vendored playground assets
run: go test ./pkg/cli -run '^(TestVendorAssetsMatchLock|TestPlaygroundAssetGraphComplete)$' -count=1

# Goreleaser builds CLI binaries and creates draft release
- name: Build CLI and create draft release
uses: goreleaser/goreleaser-action@v7
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,8 @@ target

# Generated docs
/site

# Playground frontend
/playground/
/playground-tests/coverage/
/playground-tests/node_modules/
2 changes: 2 additions & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ linters:
- weakCond
exclusions:
generated: strict
paths:
- playground-tests/node_modules
rules:
# Exclude some linters from running on test files
- path: '(.+)_test\.go'
Expand Down
3 changes: 3 additions & 0 deletions .markdownlint-cli2.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ ignores:
- "site/**"
- "docs/llms.txt"
- "CLAUDE.md"
- "playground/**"
- "playground-tests/node_modules/**"
- "playground-tests/coverage/**"

config:
default: false
Expand Down
88 changes: 44 additions & 44 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,83 +127,83 @@ Choose your platform for installation instructions.
<details>
<summary>macOS</summary>

The easiest way to install Cog on macOS is with Homebrew:
The easiest way to install Cog on macOS is with Homebrew:

```console
brew install replicate/tap/cog
```
```console
brew install replicate/tap/cog
```

You can also use the install script:
You can also use the install script:

```sh
# bash, zsh, and other shells
sh <(curl -fsSL https://cog.run/install.sh)
```sh
# bash, zsh, and other shells
sh <(curl -fsSL https://cog.run/install.sh)

# fish shell
sh (curl -fsSL https://cog.run/install.sh | psub)
# fish shell
sh (curl -fsSL https://cog.run/install.sh | psub)

# download with wget and run in a separate command
wget -qO- https://cog.run/install.sh
sh ./install.sh
```
# download with wget and run in a separate command
wget -qO- https://cog.run/install.sh
sh ./install.sh
```

Or install manually:
Or install manually:

```console
sudo curl -o /usr/local/bin/cog -L "https://github.com/replicate/cog/releases/latest/download/cog_$(uname -s)_$(uname -m | sed 's/aarch64/arm64/')"
sudo chmod +x /usr/local/bin/cog
sudo xattr -d com.apple.quarantine /usr/local/bin/cog 2>/dev/null || true
```
```console
sudo curl -o /usr/local/bin/cog -L "https://github.com/replicate/cog/releases/latest/download/cog_$(uname -s)_$(uname -m | sed 's/aarch64/arm64/')"
sudo chmod +x /usr/local/bin/cog
sudo xattr -d com.apple.quarantine /usr/local/bin/cog 2>/dev/null || true
```

If you see a Gatekeeper warning saying the binary "cannot be opened because the developer cannot be verified", run:
If you see a Gatekeeper warning saying the binary "cannot be opened because the developer cannot be verified", run:

```console
sudo xattr -d com.apple.quarantine /usr/local/bin/cog
```
```console
sudo xattr -d com.apple.quarantine /usr/local/bin/cog
```

</details>

<details>
<summary>Linux</summary>

You can install Cog using the install script:
You can install Cog using the install script:

```sh
# bash, zsh, and other shells
sh <(curl -fsSL https://cog.run/install.sh)
```sh
# bash, zsh, and other shells
sh <(curl -fsSL https://cog.run/install.sh)

# fish shell
sh (curl -fsSL https://cog.run/install.sh | psub)
# fish shell
sh (curl -fsSL https://cog.run/install.sh | psub)

# download with wget and run in a separate command
wget -qO- https://cog.run/install.sh
sh ./install.sh
```
# download with wget and run in a separate command
wget -qO- https://cog.run/install.sh
sh ./install.sh
```

Or install manually:
Or install manually:

```console
sudo curl -o /usr/local/bin/cog -L "https://github.com/replicate/cog/releases/latest/download/cog_$(uname -s)_$(uname -m | sed 's/aarch64/arm64/')"
sudo chmod +x /usr/local/bin/cog
```
```console
sudo curl -o /usr/local/bin/cog -L "https://github.com/replicate/cog/releases/latest/download/cog_$(uname -s)_$(uname -m | sed 's/aarch64/arm64/')"
sudo chmod +x /usr/local/bin/cog
```

</details>

<details markdown>
<summary>Windows</summary>

Cog does not natively support Windows, but you can run it on Windows 11 using [WSL 2](docs/wsl2/wsl2.md). Once WSL 2 is set up, follow the Linux installation instructions above.
Cog does not natively support Windows, but you can run it on Windows 11 using [WSL 2](docs/wsl2/wsl2.md). Once WSL 2 is set up, follow the Linux installation instructions above.

</details>

<details>
<summary>Docker</summary>

To install Cog inside a Docker image:
To install Cog inside a Docker image:

```dockerfile
RUN sh -c "INSTALL_DIR=\"/usr/local/bin\" SUDO=\"\" $(curl -fsSL https://cog.run/install.sh)"
```
```dockerfile
RUN sh -c "INSTALL_DIR=\"/usr/local/bin\" SUDO=\"\" $(curl -fsSL https://cog.run/install.sh)"
```

</details>

Expand Down
35 changes: 26 additions & 9 deletions architecture/06-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,16 @@ The Cog CLI is a Go binary that provides commands for the full model lifecycle:

## Commands Overview

| Command | Job To Be Done |
| ----------- | ------------------------------------- |
| `cog init` | Bootstrap a new model project |
| `cog build` | Create a container image |
| `cog run` | Run a prediction in a container |
| `cog exec` | Run arbitrary commands in a container |
| `cog serve` | Start HTTP server in a container |
| `cog push` | Deploy to Replicate |
| `cog login` | Authenticate with Replicate |
| Command | Job To Be Done |
| ---------------- | ------------------------------------- |
| `cog init` | Bootstrap a new model project |
| `cog build` | Create a container image |
| `cog run` | Run a prediction in a container |
| `cog exec` | Run arbitrary commands in a container |
| `cog serve` | Start HTTP server in a container |
| `cog playground` | Open a local UI for a model API |
| `cog push` | Deploy to Replicate |
| `cog login` | Authenticate with Replicate |

## Development Commands

Expand Down Expand Up @@ -98,6 +99,21 @@ Builds the image (if needed) and starts a container running the [Container Runti

**Code**: `pkg/cli/serve.go`

### cog playground

**Job**: Explore and call a running Cog HTTP API from a browser.

```bash
cog serve -p 8393
cog playground --target http://localhost:8393
```

The command serves an embedded browser-native application and reverse-proxies its requests to the selected model API. Each browser tab is an independent workspace: every request carries that tab's target, and the proxy keeps no shared current-target state, so tabs can use the same or different models concurrently. The UI and proxy accept only loopback connections, even when `--host 0.0.0.0` is used so a container can deliver webhooks. The proxy snapshots upstream response headers into encoded metadata so the request inspector can show model values without including or merging playground security and transport headers. Webhook URLs contain an opaque per-prediction token, which also isolates concurrent tab subscriptions, and payloads are relayed to the browser over server-sent events.

The proxy is intentionally user-directed: this is a local development tool for APIs selected by the user, not a remotely hosted gateway. The checked-in HTML, CSS, and JavaScript under `pkg/cli/playground/` are embedded directly in every Go binary. There is no frontend build in local or release workflows. Browser code uses checked JavaScript and framework-independent core tests; frozen CodeMirror, AJV, and Kumo stylesheet assets keep the application offline and reproducible. AJV's dynamic schema compilation is confined to a worker with a narrower content security policy than the page.

**Code**: `pkg/cli/` owns the server, proxy, and embedded browser application; `playground-tests/` owns Node-only checks.

## Build Commands

### cog build
Expand Down Expand Up @@ -219,6 +235,7 @@ pkg/cli/
├── predict.go # prediction execution and legacy cog predict
├── exec.go # cog exec
├── serve.go # cog serve
├── playground.go # cog playground and local proxy
├── push.go # cog push
├── login.go # cog login
└── init.go # cog init
Expand Down
43 changes: 43 additions & 0 deletions docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,49 @@ cog login [flags]
--token-stdin Pass login token on stdin instead of opening a browser. You can find your Replicate login token at https://replicate.com/auth/token
```

## `cog playground`

Open a browser playground for talking to a running model.

Starts a local web server that serves a schema-driven UI (a Postman-like tool
for Cog models). Point it at any running Cog HTTP API -- for example one started
with 'cog serve' -- and the playground reflects that model's inputs and outputs
from its OpenAPI schema in real time.

Requests are reverse-proxied through this server, so the target API does not
need to set CORS headers. The server also hosts a webhook sink so async
predictions can be observed in the browser.

Async/webhook testing against a containerized model requires the webhook URL to
be reachable from inside the container. On Docker Desktop the default
'host.docker.internal' works once the server listens on a reachable interface
(e.g. --host 0.0.0.0).

```
cog playground [flags]
```

**Examples**

```
# Start a model API in one terminal
cog serve -p 8393

# Open the playground pointing at it
cog playground --target http://localhost:8393
```

**Options**

```
-h, --help help for playground
--host string Address to bind (use 0.0.0.0 to receive webhooks from containers) (default "127.0.0.1")
--no-open Do not open the browser automatically
-p, --port int Port to listen on (0 picks a free port)
--target string Default target model API URL (default "http://localhost:8393")
--webhook-host string Hostname the model uses to reach this server for webhooks (default "host.docker.internal")
```

## `cog push`

Build a Docker image from cog.yaml and push it to a container registry.
Expand Down
Loading
Loading