Skip to content
Development
Skill

/cursor-sdk-e2e-dev

Spin up a live local Omnigent server and exercise the Cursor SDK harness end-to-end — build cursor agents, run real turns, smoke-test, and bug-bash. Load when developing, testing, or debugging the cursor harness (omnigent/inner/cursor_executor.py, cursor_harness.py,

From plugin
omnigent
8.4k12 skills
Install
$ npx -y skills add omnigent-ai/omnigent --skill cursor-sdk-e2e-dev --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/cursor-sdk-e2e-dev

Context preview

The summary Claude sees to decide when to auto-load this skill.

Spin up a live local Omnigent server and exercise the Cursor SDK harness end-to-end — build cursor agents, run real turns, smoke-test, and bug-bash. Load when developing, testing, or debugging the cursor harness (omnigent/inner/cursor_executor.py, cursor_harness.py,

SKILL.md

cursor-sdk-e2e-dev.SKILL.md
name: cursor-sdk-e2e-dev
description: Spin up a live local Omnigent server and exercise the Cursor SDK harness end-to-end — build cursor agents, run real turns, smoke-test, and bug-bash. Load when developing, testing, or debugging the cursor harness (omnigent/inner/cursor_executor.py, cursor_harness.py, cursor_auth.py) or its auth / model / tool-bridge behavior.

Cursor SDK harness: end-to-end dev & testing

The `cursor` harness drives the **Cursor Python SDK** (`cursor_sdk`, an `AsyncAgent` over a local bridge) and bridges Omnigent's `sys_*` tools into Cursor as SDK `custom_tools`. This skill is the proven recipe for running it **for real** against a live local server — not just the unit tests.

> The harness runs as a **local runner** from your current checkout, so > `omni run <bundle> --server <url>` exercises exactly the code you're on.

Prerequisites (check these first)

1. **You're on the branch you want to test.** The cursor harness merged to `main` (#203/#204). Test on `main` unless validating a specific branch. 2. **A Cursor API key is configured.** The SDK *requires* an API key (`crsr_…`); there is no `cursor-agent login` path. Verify (booleans only — never print the key):

   .venv/bin/python -c "from omnigent.onboarding.cursor_auth import cursor_api_key_configured; import os; print('config:', cursor_api_key_configured(), 'env:', bool(os.environ.get('CURSOR_API_KEY')))"

If both are `False`, run `omni setup` and register a Cursor key, or `export CURSOR_API_KEY=crsr_…`. 3. **`cursor-sdk` is installed** (a baseline dependency): `.venv/bin/python -c "import cursor_sdk; print(cursor_sdk.__file__)"`. 4. **Network egress to Cursor's backend.** The bridge subprocess talks to Cursor's own API; a turn that hangs or fails to connect on a locked-down host is usually an egress problem, not a harness bug.

Step 1 — start a local server

cd /path/to/omnigent
.venv/bin/omni server --background          # spawns a detached server on a free loopback port
.venv/bin/omni server status         # prints the URL, e.g. http://127.0.0.1:6767

Use the **printed URL** below as `$SERVER`. (You can also run a foreground server on a fixed port with `omnigent server --port 7777 --no-open`.)

Step 2 — build a cursor agent bundle

A spec with `spec_version` **must be a directory containing `config.yaml`** — not a single `.yaml` file. Minimal cursor agent:

mkdir -p /tmp/cursor-dev
cat > /tmp/cursor-dev/config.yaml <<'YAML'
spec_version: 1
name: cursor-dev
description: Cursor SDK dev/test agent.
executor:
  type: omnigent
  config:
    harness: cursor
    # model: gpt-5            # optional; omit for cursor "auto"
prompt: |
  You are a terse test agent. Answer in as few words as possible.
YAML

For sub-agents, tools, guardrails/policies, copy the field shapes from `examples/polly/config.yaml` and `examples/debby/config.yaml`.

Step 3 — run a turn (and smoke-test)

SERVER=http://127.0.0.1:6767   # the URL from `omni server status`
timeout 280 .venv/bin/omni run /tmp/cursor-dev \
  -p "Reply with exactly the single word: PONG" \
  --server "$SERVER" 2>&1

A healthy run prints connection lines then the assistant reply (`PONG`). If that works, the full stack is good: key, egress, bridge, harness.

  • **Shell / file tools:** add `--tools coding`.
  • **Specific model:** add `--model gpt-5` (or `composer-1`, `auto`,

`databricks-claude-opus-4-8`, …).

Targeted scenarios

| Goal | How | |------|-----| | Native tools (shell/edit/read) | `--tools coding`, prompt to create→read→edit a file and run a shell command; confirm it actually touches disk | | Bridged `sys_*` / sub-agent dispatch | declare a sub-agent (`tools.agents`/`spawn`), prompt the cursor agent to delegate — exercises the `custom_tools` daemon-thread bridge (`run_coroutine_threadsafe`) | | Model routing | run the same bundle with several `--model` values; note which actually runs | | Policy / guardrail | add a guardrail that denies a keyword; confirm `PHASE_LLM_REQUEST`/`PHASE_LLM_RESPONSE` blocks it | | Concurrency / leaks | fire several `omni run … &` at once; then `pgrep -af "cursor-sdk-bridge|cursor_sdk"` to check for orphaned bridge subprocesses |

Gotchas (these cost real time)

1. **`config.yaml`'s `server:` defaults to a *remote* server** (e.g. a Databricks Apps URL). Omitting `--server` sends your turn to that remote deploy — which may be **stale** and reject the cursor harness with `executor.config.harness: must be one of […], got 'cursor'`. **Always pass `--server http://127.0.0.1:<port>`** for local testing. (That allowlist is `omnigent/spec/_omnigent_compat.py`; if a *local* server rejects `cursor`, it's running stale code — restart it from your checkout.) 2. **A spec with `spec_version` must be a directory + `config.yaml`**, never a single `.yaml` file. 3. **Cursor needs a `crsr_` API key** (no CLI login). Resolution precedence: spec `executor.auth` (api_key) > stored `cursor:` config block (`omni setup`) > ambient `CURSOR_API_KEY`. 4. **No Databricks gateway.** Cursor talks only to Cursor's backend, so a `databricks-*` model is silently resolved to cursor `auto` — it will *not* route through the AI Gateway like claude-sdk/codex/pi. 5. **Use a model id from the account's catalog.** Bare `gpt-5` is **not** valid; the SDK rejects unknown ids. Valid examples seen live: `default`, `composer-2.5`, `claude-opus-4-8`, `gpt-5.5`. Run with `--model` and read the SDK's `Available models:` list to discover the live set. 5. **Turns take 30–90s** — always wrap in `timeout 280`. 6. **Local-runner topology:** `omni run <bundle> --server <url>` runs the harness from your **current checkout**; the server only holds state. The managed `omni server --background` server runs from whatever venv launched it. 7. **Never print/echo the Cursor key** in logs or commands.

Code & tests

  • **Executor (SDK bridge):** `o
Read more
Ships withomnigent

Omnigent is an open-source AI agent framework and meta-harness: orchestrate Claude Code, Codex, Cursor, Pi, and custom agents — swap harnesses without rewriting, enforce policies and sandboxing, and collaborate in real time from any device.

Get the whole plugin

Other skills on omnigent.