Deploying Cursor¶
Cursor's CLI agent runs as the cursor runtime: its TUI inside tmux behind a browser terminal, installed by the language-operator-runtimes chart. The image is built in cursor-adapter on the shared coding-runtime base.
Cursor is a vendor-key runtime, like Claude Code: it authenticates to Cursor with your Cursor key and talks to Cursor directly, not through the cluster's model gateway. See What a vendor-key runtime means.
Prerequisites¶
- Language Operator installed, including the
language-operator-runtimeschart (provides thecursorruntime) - A
LanguageClusterto deploy into, with yourkubectlcontext set to its namespace (examples below assume a cluster nameddemo-cluster) - A Cursor account, and for headless or task-mode agents a Cursor API key
Instructions¶
Deploy Cursor¶
kubectl apply -f - <<EOF
apiVersion: langop.io/v1alpha1
kind: LanguageAgent
metadata:
name: cursor
spec:
runtime: cursor
instructions: |
You are an expert software engineer. Help with code review,
debugging, and implementation tasks.
networkPolicies:
egress:
- to:
- cidr: "0.0.0.0/0"
ports:
- port: 443
protocol: TCP
EOF
The egress rule lets the agent reach Cursor's API; without it, the agent's NetworkPolicy allows only in-cluster traffic.
Verify¶
Wait for PHASE to reach Running. The MODE column shows service: the TUI is long-lived and addressable. See
Execution Modes.
Connect¶
Access is gated by the cluster's OIDC proxy. If your LanguageCluster has a domain and auth enabled,
open https://cursor.demo-cluster.\<your-domain> and sign in through the cluster's OIDC provider.
For local access, port-forward the service (this bypasses the proxy, so no login is required):
Then open http://localhost:8080 in your browser. With no key configured, the terminal opens on Cursor's sign-in screen (see Authentication).
Warning
The terminal has no built-in authentication. When the cluster does not enable auth, it is exposed unauthenticated on its ingress. Enable cluster auth to protect it.
Authentication¶
Cursor reads its key from CURSOR_API_KEY. Give it one of three ways.
Interactive login (service mode only)¶
With no key set, the terminal opens on Cursor's sign-in screen. The login is kept on the workspace volume, so pod restarts do not ask again. Task-mode agents cannot do this — nobody is there to sign in — and need a key.
Per agent¶
Store the key in a Secret whose key is literally named CURSOR_API_KEY, and reference it from the agent's spec.credentials:
Always use valueFrom (or value): a credential declared by name alone is filled by the operator with a random value.
For every cursor agent¶
Set the runtime chart's credentials.apiKeySecret and every agent on the cursor runtime gets the key, with no per-agent configuration:
helm upgrade --install language-operator-runtimes \
language-operator/language-operator-runtimes \
--namespace language-operator \
--set cursor.credentials.apiKeySecret=cursor-credentials
The Secret must exist in each agent's namespace. It is off by default because an agent whose namespace lacks the Secret will not start.
What a vendor-key runtime means¶
Cursor has no custom base URL, so its traffic goes straight to Cursor under the key's account, not through the model gateway. As a result:
-
spec.modelsdoes not apply. Gateway model names are not Cursor model names. Cursor uses its default model unless you setCURSOR_MODEL, which is passed as--model; an unknown name fails the run: -
Gateway features do not cover it: gateway logging, per-model rate limits and per-agent key attribution see none of Cursor's requests.
- The agent needs egress to Cursor's API (port 443), as in the deploy example above.
Instructions, Persona and Tools¶
spec.instructionsis the opening message of a fresh service-mode session, and the prompt of a task run. A resumed session is not sent it again.- The persona becomes an always-applied Cursor rule,
/workspace/.cursor/rules/langop-persona.mdc. Cursor loads rules from the working directory and its parents, so it applies inside a cloned repository without touching the repository. LanguageTools become MCP servers in Cursor's global MCP file, so they need no per-project approval. Header values that reference a secret are written as${env:NAME}, which Cursor expands itself, so the secret is never written to disk. A tool whose headers cannot all be resolved is left out with a warning.
Task Mode¶
Cursor also runs headless as a task. Each run executes agent -p with spec.instructions as the prompt; when the run was started with an event, its payload is appended, labelled as data rather than instructions. The exit code is the run's result: 0 is Succeeded, anything else Failed.
apiVersion: langop.io/v1alpha1
kind: LanguageAgent
metadata:
name: changelog
spec:
runtime: cursor
credentials:
- name: CURSOR_API_KEY
valueFrom:
name: cursor-credentials
repository:
url: https://github.com/acme/api.git
instructions: |
Summarise the commits merged since the last tag into CHANGELOG.md.
execution:
mode: task
schedule: "0 6 * * 1"
networkPolicies:
egress:
- to:
- cidr: "0.0.0.0/0"
ports:
- port: 443
protocol: TCP
Warning
Task runs use --force: nobody is there to approve a tool call, so every tool the agent
chooses to run, runs. Scope what a task agent can reach — its repository, its tokens, its
tools — accordingly.
What the Operator Created¶
| Resource | Name | Purpose |
|---|---|---|
| WorkflowTemplate | cursor |
The agent's pod spec; also what argo submit --from targets |
| Workflow | cursor |
The long-lived run. Runs the Cursor WebSocket terminal container |
| Service | cursor |
ClusterIP on port 8080 |
| NetworkPolicy | cursor |
Allows inbound from other agents in this namespace, plus the egress you declare |
| PVC | cursor-workspace |
10Gi persistent workspace |
| ConfigMap | cursor-agent |
Injected at /etc/agent/config.yaml |
A task-mode agent gets a CronWorkflow (when it has a schedule) instead of the long-lived Workflow, and no Service.