/dΔ-skΓ»rβ²sΔv/ - proceeding coherently from topic to topic; marked by analytical reasoning
A gateway proxy that enables Cursor's full agentic workflow with alternative providers.
- π¦ Quickstart
- β‘ Subagent Routing
- βοΈ Setting up Cloudflare
- π Usage Dashboard
- πͺ Providers
- π Tech Stack
- π File Structure
- π₯ CLI Commands
- β¨οΈ Shell Completion
- π Environment Variables
- π CI / Release
- π Security
- π§ͺ Methodology
- π License
go install github.com/commoddity/discursive@latestOr download a release binary and put it on your PATH.
- Go 1.26.5+
- cloudflared
On first run, the interactive wizard also prompts for:
| Item | Required | Where to get / notes |
|---|---|---|
| Moonshot (Kimi) API key | β Yes | platform.kimi.ai |
| DeepSeek API key | β Yes | platform.deepseek.com |
| Cloudflare tunnel token | β Yes | See Setting up Cloudflare below |
| Public HTTPS URL | β Yes | Hostname from tunnel setup with /v1 appended |
| Thaura AI API key | No | thaura.ai |
| Z.AI API key | No | docs.z.ai |
discursive start --backgroundOn first run, the gateway auto-invokes the interactive wizard (see Prerequisites).
Keys are encrypted at rest. Secrets are never sent to Cursor or logged.
The gateway listens on localhost:4001. It logs the gateway_key and
public_url you'll need for the next step:
discursive status --show-key | jqGateway keys are masked by default. Pass --show-key to print the full
gateway_key for Cursor setup.
π‘ Subagent routing is on by default. The gateway inspects every request and, when the content indicates simple, cheap work (short lookups, code search, structured extraction, automation), routes it to a cheaper model β typically
deepseek-v4-flashβ to cut cost. Complex work (editing/refactoring, reasoning) keeps the original model. See Subagent Routing below, or disable it withdiscursive start --subagent-router=false.
Open Cursor Settings β Models and enter:
| Setting | Value |
|---|---|
| OpenAI API Key | gateway_key from discursive status --show-key |
| Override OpenAI Base URL | public_url from discursive status (ends in /v1) |
| Model | Pick an alias from the table below (e.g. gpt-4o) |
Reload Cursor: Cmd+Shift+P β Reload Window. You should see
Connection verified above the Base URL field.
π‘ Tip: You can also copy the Gateway Key and Tunnel URL directly from the Usage Dashboard at http://localhost:4002 β hover over the
?icons next to βοΈ Tunnel and π Gateway Key for field-specific setup instructions.
Change the model alias in Cursor's model picker β no restart needed:
| Cursor alias | Provider | Real model | Use |
|---|---|---|---|
gpt-4o |
Moonshot | kimi-k3 |
Planning / flagship |
gpt-4o-mini |
Moonshot | kimi-k2.7-code |
Coding; always thinks |
o1 |
DeepSeek | deepseek-v4-pro |
Harder execution |
o3-mini |
DeepSeek | deepseek-v4-flash |
Cheap execution |
gpt-5-nano |
Thaura | thaura |
Ethical AI; optional provider |
gpt-4.1-turbo |
Z.AI | glm-5.2 |
Planning; cheaper than K3 |
gpt-4.1 |
Z.AI | glm-4.7 |
Cheap execution |
gpt-4-turbo |
Z.AI | glm-5.2 |
Compat alias (Cursor may rewrite gpt-4.1-turbo to this) |
In Cursor Settings β Models: turn off "Override OpenAI API Key" and "Override OpenAI Base URL", then pick a Cursor-native model.
The gateway can automatically downgrade individual requests to a cheaper, faster model when the work is simple enough β cutting token cost and latency without changing what you pick in Cursor. Subagent routing is on by default and requires no configuration.
The router runs entirely inside the gateway. Cursor still sends every request to the gateway under whatever model alias you chose; the gateway inspects each request, may route it to a cheaper model, and proxies upstream. Cursor's model picker is unaware of the routing.
Each incoming request is classified by its content β the last user message determines whether the task is cheap enough for a flash model:
| Request type | Action | Model |
|---|---|---|
| Simple lookup / explanation | downgrade to flash | deepseek-v4-flash |
| Code search / exploration | downgrade to flash | deepseek-v4-flash |
Structured extraction (json_object / json_schema) |
downgrade to flash | deepseek-v4-flash |
| Automation / mechanical work (lint, git, scripts, PR) | downgrade to flash | deepseek-v4-flash |
| Editing / refactoring | keep model | original model |
| Complex reasoning / architecture | keep model | original model |
| Unknown / unclassified | keep model | original model |
| Flag | Default | Purpose |
|---|---|---|
--subagent-router |
true |
Enable the subagent router (content-based classification + flash downgrade). Set --subagent-router=false to run the gateway with no automatic model changes. |
--log-level |
info |
Log verbosity: debug, info, warn, error. Use debug to see per-request request_class and override lines from the router. Overrides DISCURSIVE_LOG_LEVEL. |
--background |
false |
Detach and run in the background. Logs to {dataRoot}/gateway.log. |
--tunnel |
(config) | Tunnel mode: named, none, or quick (persists to config). |
--public-url |
(config) | Public HTTPS base URL ending in /v1 (persists to config). |
Examples:
# Routing on (default) + debug logging
discursive start --subagent-router --log-level debug
# Disable routing entirely
discursive start --subagent-router=falseπ‘ Tip: At
--log-level debug, the router logs one line per request withrequest_class. This is the easiest way to see exactly what the router is doing and tune your expectations.
Tool-result compression reduces token cost during multi-turn agent sessions. It
is toggleable from the usage dashboard (http://127.0.0.1:4002 β Gateway Toggles,
no restart required):
- Tool-result compression: Tool output exceeding a character threshold is
summarized by a cheap model (
deepseek-v4-flash).
Compression is fail-open: if the summarizer model returns an empty or error
result, the original content is sent upstream unchanged β there is no quality
loss. Results are cached by content hash with singleflight deduplication, so
repeated tool results (e.g. ls output, test output) are compressed only once.
When to use: Multi-turn agent sessions with verbose tools (file reads, test runs, search results). In testing, compression saved ~42% of input tokens in a ~34-minute EPUB pipeline session with no observable quality degradation.
Cost: The summarizer model uses deepseek-v4-flash pricing (nearly free per
turn with prompt caching). The savings from reduced upstream tokens far outweigh
the compression cost.
Cursor's cloud cannot reach localhost. A Cloudflare tunnel gives the gateway
a public HTTPS URL.
- Go to Cloudflare Zero Trust β Tunnels
- Click Add a tunnel, choose Cloudflared, give it a name
- Copy the tunnel token β you'll paste it into the Discursive wizard
- Under Public Hostname, add a route:
- Subdomain: anything you like (e.g.
discursive) - Domain: choose from your Cloudflare zones
- Service:
http://localhost:4001
- The public URL you'll enter in the wizard is the hostname from step 4
with
/v1appended (e.g.https://discursive.yourdomain.com/v1)
Usage Dashboard
The gateway serves a local usage dashboard at http://localhost:4002
(loopback only). It starts automatically with discursive start β no extra
process or configuration.
- System health - health checks & system uptime
- Reasoning effort β per-model
low/high/max(and DeepSeekoff) saved to app settings - Output verbosity β per-model toggles (DeepSeek) that inject a terseness directive and cap output tokens to coerce terse replies (never trims responses)
- Provider balances & monthly spend projection β average daily spend, projected monthly total
- Month to date spending β requests, tokens, and estimated cost (USD, EUR, CNY)
- Spend by period, model, and provider β clear charts per time period, model, and provider
- Sessions β summary stats for the selected range; expand to browse individual sessions
π‘ Note: The Usage Dashboard is not exposed via the public tunnel. Only accessible locally on
localhost:4002.
Models that support configurable reasoning / thinking (kimi-k3,
deepseek-v4-pro, deepseek-v4-flash) can be tuned from the Usage Dashboard
(Reasoning Effort card at http://127.0.0.1:4002). Values are stored in app
settings and applied to new gateway requests immediately (no restart). Gateway
logs include an effort field on request/response/usage lines.
| Model | Options | Default |
|---|---|---|
kimi-k3 |
low, high, max |
low (API default is max; we default lower for cost) |
deepseek-v4-pro / deepseek-v4-flash |
off, high, max |
off (off β thinking: disabled; otherwise thinking: enabled + reasoning_effort) |
glm-5.2 |
off, high, max |
off (off β thinking: disabled; otherwise thinking: enabled + reasoning_effort) |
- Lower effort usually means fewer thinking tokens and lower cost.
thauradoes not expose this control. kimi-k2.7-codealways thinks β thinking is always on and there is no effort selector: Kimi K2.7 Code- DeepSeek only documents
high/maxfor effort: DeepSeek Thinking Mode).
DeepSeek models tend to emit verbose reasoning prose. The gateway can tighten
that per-model from the Output Verbosity card at the Usage Dashboard
(http://127.0.0.1:4002). When a model's toggle is on, the gateway applies
two controls to that model's requests:
- Terseness directive β a numbered, authority-marked system prompt appendix telling the model to lead with the solution and omit conversational filler.
- Output-token cap β a generous
max_tokensceiling (only ever lowers a request's existing value).
Verbosity only coerces/prompts the model to be less verbose. The gateway
never edits response content β both streaming and non-streaming replies pass
through byte-for-byte, so there is no trailing-β¦ response trimming.
Defaults: deepseek-v4-flash is on, deepseek-v4-pro is off. Changes
apply to new requests immediately (no restart). The --verbosity CLI flag has
been removed β verbosity is now managed entirely from the dashboard.
Moonshot provides frontier models with long-context windows and native reasoning capabilities.
| API model ID | Cache hit / MTok | Input / MTok | Output / MTok | Role |
|---|---|---|---|---|
kimi-k3 |
$0.30 | $3.00 | $15.00 | Flagship; 1M-token context, always thinks |
kimi-k2.7-code |
$0.19 | $0.95 | $4.00 | Coding model; always thinks |
- Pricing: https://platform.kimi.ai/docs/pricing/chat
- API docs: https://platform.kimi.ai/docs/
- K3 reasoning effort: Reasoning Effort
DeepSeek provides cost-efficient reasoning models at a fraction of the cost per token.
| API model ID | Cache hit / MTok | Cache miss / MTok | Output / MTok | Role |
|---|---|---|---|---|
deepseek-v4-pro |
$0.003625 | $0.435 | $0.87 | Harder reasoning / agentic execution |
deepseek-v4-flash |
$0.0028 | $0.14 | $0.28 | Cheap, high-volume execution |
- Pricing: https://api-docs.deepseek.com/quick_start/pricing
- API docs: https://api-docs.deepseek.com/
- Thinking mode: Thinking Mode
Z.AI provides GLM-series models with
thinking support and prompt caching. Z.AI is used via the GLM Coding Plan
(subscription, credits quota), which exposes the OpenAI-compatible base URL
https://api.z.ai/api/coding/paas/v4.
| API model ID | Cache hit / MTok | Input / MTok | Output / MTok | Role |
|---|---|---|---|---|
glm-5.2 |
$0.26 | $1.40 | $4.40 | Planning model; reasoning_effort + cache |
glm-4.7 |
$0.11 | $0.60 | $2.20 | Budget execution; thinking on/off |
glm-4.6v |
$0.05 | $0.30 | $0.90 | Vision worker β describes images for ALL providers (not user-selectable) |
Image routing: any request (any provider) that contains image content is intercepted by the gateway and each image is described by Z.AI
glm-4.6v(coding-plan endpoint) before the selected text model is called. A Z.AI API key is therefore required to send images. If it is missing or the vision model rejects the image, the request fails fast with a clearvision_errorrather than silently dropping the image.
- Pricing: https://docs.z.ai/guides/overview/pricing
- API docs: https://docs.z.ai/api-reference/introduction
- API key: https://z.ai/manage-apikey/apikey-list (GLM Coding Plan key)
| Parameter | glm-5.2 |
glm-4.7 |
|---|---|---|
thinking |
{type: "enabled"} when reasoning; else {type: "disabled"} |
`{type: "enabled" |
reasoning_effort |
Normalized β off/high/max |
Deleted (not supported) |
Thaura is an AI platform that combines technical excellence with ethical principles, designed to support Palestinian liberation and mission-aligned technology development.
| API model ID | Input / MTok | Output / MTok | Role |
|---|---|---|---|
thaura |
$0.50 | $2.00 | OpenAI-compatible chat and tool use |
- Pricing: https://thaura.ai/api-platform
- API docs: https://thaura.ai/api-platform
π΅πΈ Incubated by Tech for Palestine
Click to expand
Tech for Palestine (T4P) is a coalition of founders, engineers, product marketers, investors, and other professionals working in support of Palestinian liberation.
What is Tech for Palestine?
Tech for Palestine is first and foremost an incubator for advocacy projects. They rally volunteers from across the tech world β founders, engineers, marketers, investors, and more β all committed to Palestinian liberation.
The T4P Incubator helps pro-Palestine advocates build, grow, and scale their work towards a Free Palestine. They support projects β whether collections of individuals, registered non-profits, or even companies β whose mission helps Palestine, especially advocacy groups building technical products or in the tech space.
The Incubator is free and provides:
- π₯ Volunteers - Access to skilled professionals
- π’ Marketing Support - Help spreading your message
- π Mentorship - Guidance from experienced professionals
- π Connections - Links to the broader Palestinian advocacy ecosystem
Get Involved:
- Volunteer your skills
- Join their Discord
- Start a project of your own
- Be a mentor
- Hire Palestinians
Learn more at techforpalestine.org
| Component | Technology |
|---|---|
| Language | Go 1.26.5+ |
| CLI framework | Cobra |
| Tunnel | cloudflared named tunnel |
| Upstream APIs | OpenAI-compatible chat completions (Moonshot + DeepSeek + Thaura + Z.AI) |
main.go # Entry point
internal/
cli/ # Cobra command tree (start, stop, status, doctor, β¦)
start/ # Start gateway / background daemon / tunnel
setcmd/ # `set` command
wizard/ # Interactive init wizard
config/ # App settings, paths, upstream URL helpers
crypto/ # Encrypt upstream keys + gateway key gen
gateway/ # HTTP server, sanitizer, optimizer, proxy, auth
vision/ # Image description via glm-4.6v (fail-fast, content-hash cache)
tunnel/ # cloudflared supervisor
doctor/ # Health checks
usage/ # Pricing tables, token/cost store, slog helpers
usageui/ # Embedded usage dashboard (HTTP, Chart.js)
.cursor/rules/ # Agent conventions
.cursor/skills/ # Invocable workflows
planning/ # MVP task sequence (T01βT10)
All output is JSON on stdout. Pipe through jq for readability.
| Command | Description |
|---|---|
discursive start |
Start gateway on localhost:4001. --background forks to daemon. --log-level (debug/info/warn/error). --tunnel (named/none/quick), --public-url. --subagent-router (on by default). Runtime toggles managed from the usage dashboard. Auto-invokes init if config is incomplete on first run. See Subagent Routing and Compression. |
discursive stop |
Send SIGTERM via PID file. No-op if not running. |
discursive status |
Config dump + runtime state: PID alive? uptime? log file path/size, tunnel mode, model mapping. Gateway key masked by default; --show-key prints the full key. |
discursive logs |
Pretty-print gateway.log with colored level prefixes. --follow (-f) for live tail (uses fsnotify β no polling). -n N for last N lines. File auto-rotates at ~2 MB, keeps 2 backups. |
| `discursive log-level [debug | info |
discursive doctor |
Health checks: keys present, port available, local/public HTTP health, tunnel mode, cloudflared binary, logs writable. |
discursive usage |
Token + cost estimates per session/model. |
discursive set |
Configure settings via flags. --moonshot-key, --deepseek-key, --thaura-key, --zai-key, --tunnel-token, --public-url, --rotate-gateway-key, --model. Combine several in one call. --show-key prints the full gateway key. |
| `discursive completion [bash | zsh |
discursive version |
Print version. |
JSON slog on stdout, interactive prompts on stderr β pipe-friendly.
Cobra's built-in completion command generates scripts for bash, zsh, fish, and
PowerShell. After install, Tab completes subcommands, flags, log levels, tunnel
modes, and model aliases.
zsh (macOS default):
# Oh My Zsh
mkdir -p ~/.oh-my-zsh/completions
discursive completion zsh > ~/.oh-my-zsh/completions/_discursive
# Or any zsh with compinit (add to ~/.zshrc, then restart the shell):
discursive completion zsh > "${fpath[1]}/_discursive"bash (Linux / macOS with bash-completion):
# Linux (system-wide)
discursive completion bash | sudo tee /etc/bash_completion.d/discursive >/dev/null
# Or per-session / add to ~/.bashrc:
source <(discursive completion bash)fish:
discursive completion fish > ~/.config/fish/completions/discursive.fishVerify: type discursive then Tab β you should see subcommands.
| Variable | Purpose | Default |
|---|---|---|
DISCURSIVE_LOG_LEVEL |
Log verbosity: debug, info, warn, error |
info |
DISCURSIVE_USAGE_IDLE |
Idle window before emitting a usage summary (Go duration) | 30s |
| Trigger | Job | What runs |
|---|---|---|
Push to main / PR |
Verify (lint + test + build) | golangci-lint + go test ./... + go build ./... |
Tag v* (e.g. v0.1.0) |
Release (GoReleaser) | Cross-compile + publish binaries to GitHub Releases |
The verify job must pass before release runs. Releases use the built-in
secrets.GITHUB_TOKEN (no custom PAT needed).
Binaries are built via GoReleaser and published at https://github.com/commoddity/discursive/releases.
- Upstream Moonshot, DeepSeek, Thaura, and Z.AI keys are encrypted at rest and never sent to Cursor, never appear in logs
- Cursor receives only the generated gateway key (
sk-...) - Gateway key is masked by default in
status/rotate-gateway-key; pass--show-keywhen you need the full value for Cursor setup - Gateway binds to loopback (
localhost); the Cloudflare tunnel is the only public surface - All output is JSON on stdout β never emit upstream secrets or raw headers
Discursive was developed using Turboplan, a methodology for AI-assisted software delivery. Turboplan structures work into sequenced phases, enforces layered verification ("don't advance until the layer below passes"), and maintains self-evolving agent rules that capture failure patterns. Every feature in this project was planned, executed, and verified through Turboplan's task lifecycle.
MIT

