loading…
Search for a command to run...
loading…
A high-performance Rust reimplementation of WCGW for code agents, providing shell execution and advanced file management capabilities for LLMs via MCP.
A high-performance Rust reimplementation of WCGW for code agents, providing shell execution and advanced file management capabilities for LLMs via MCP.
🦀 Native Rust implementation inspired by WCGW, built for local code-agent workflows
A local MCP server you can hand to a coding agent and stop worrying about the shell.
Winx is the MCP server I wanted while running Claude, Codex, and friends against real repos: one process that handles the shell, file IO, and PTY-backed interactive sessions, written in Rust so it doesn't fight you on stdio.
It started as a Rust port of WCGW but isn't a Python wrapper. Everything runs on a
real PTY (via portable-pty), cd actually sticks, Ctrl+C actually interrupts, and background shells survive
long-running TUIs without leaking output buffers into your token budget.
command shorthand both work; NUL bytes are
rejected before they reach the shell.wcgw (full access), architect (read-only), code_writer (allowlist of commands and
write globs). The command allowlist is parsed with tree-sitter, so it checks every command on the line —
pipelines, &&/||/;, command substitution, subshells — not just the first word, and can't be bypassed with
ls && curl … | sh or ls $(rm …).PS1. Opt into zsh with WINX_SHELL=zsh.file.rs:10-40, file.rs:10-, file.rs:-40). Active files are tracked
and prioritized in the repository context across calls.ContextSave for handing a task summary plus its files to the next session — including workspace context, active
files, git status/diff, and terminal sharing for proper resumption. Resuming reopens the saved project root and
token-caps the restored memory so it never overflows the context window.ReadImage so multimodal clients can pull screenshots, mockups, error PNGs, etc.line [winx: ×N]) so build/install logs don't blow your context budget. Toggle the
collapsing with WINX_NO_COMPRESS.winx serve --http) for remote MCP clients like ChatGPT — see
Remote access.| Tool | What it does |
|---|---|
Initialize |
Boots the workspace, picks the mode, hands you a thread_id. Call this first or everything else errors out. With no workspace path it spins up a scratch playground; resuming a task (task_id_to_resume) reopens its saved project root. |
BashCommand |
Runs commands, polls long-running ones, sends Enter/Ctrl-C, drives TUIs. Supports is_background, status_check, send_text, send_specials, send_ascii, allow_multi for multi-statement scripts. |
ReadFiles |
One or many files, with line numbers. Append :10-40 to a path for a range. When the token budget is hit it tells you the exact line + file:N-M syntax to resume from instead of silently dropping the tail. |
FileWriteOrEdit |
Full overwrites or SEARCH/REPLACE blocks. Validates file read coverage and freshness before writing, then runs a tree-sitter syntax check (18+ languages) and points at the offending line with a snippet. |
ContextSave |
Dumps task description + file globs into a single text file with workspace context, active files, and git status/diff for clean handoff and task resumption. |
ReadImage |
Returns a native MCP image content block (not base64 as text), so multimodal models actually see the image. |
Standard block syntax:
<<<<<<< SEARCH
old content
=======
new content
>>>>>>> REPLACE
Things the matcher forgives so you don't have to babysit the model:
ReadFiles line numbers if they leak into a SEARCH block\" unescaped when the model over-escapes quotes in SEARCHcargo install winx-code-agent
Binary lands in ~/.cargo/bin — every config snippet below assumes that's on $PATH. If your MCP client launches with
a sterile env, swap winx-code-agent for the absolute path (which winx-code-agent).
Needs Rust 1.75+, Linux/macOS/WSL2, and a real terminal (any modern one — Winx spawns its own PTY).
One-liner via the CLI (stdio is the default transport):
claude mcp add winx -- winx-code-agent
Or drop a .mcp.json in your project root:
{
"mcpServers": {
"winx": {
"command": "winx-code-agent",
"env": { "RUST_LOG": "winx_code_agent=info" }
}
}
}
Add to your config file (~/Library/Application Support/Claude/claude_desktop_config.json on macOS, %APPDATA%\Claude\claude_desktop_config.json on Windows):
{
"mcpServers": {
"winx": {
"command": "winx-code-agent",
"env": { "RUST_LOG": "winx_code_agent=info" }
}
}
}
Restart Claude Desktop after saving.
One-liner:
codex mcp add winx -- winx-code-agent
Or edit ~/.codex/config.toml:
[mcp_servers.winx]
command = "winx-code-agent"
env = { RUST_LOG = "winx_code_agent=info" }
Add to ~/.cursor/mcp.json (or .cursor/mcp.json for project-local):
{
"mcpServers": {
"winx": {
"command": "winx-code-agent",
"env": { "RUST_LOG": "winx_code_agent=info" }
}
}
}
Add to .vscode/mcp.json:
{
"servers": {
"winx": {
"type": "stdio",
"command": "winx-code-agent"
}
}
}
Add to your Zed settings (~/.config/zed/settings.json):
{
"context_servers": {
"winx": {
"source": "custom",
"command": "winx-code-agent",
"args": [],
"env": { "RUST_LOG": "winx_code_agent=info" }
}
}
}
Add to ~/.codeium/windsurf/mcp_config.json:
{
"mcpServers": {
"winx": {
"command": "winx-code-agent",
"env": { "RUST_LOG": "winx_code_agent=info" }
}
}
}
Add to opencode.json:
{
"mcp": {
"winx": {
"type": "local",
"command": ["winx-code-agent"],
"enabled": true,
"environment": { "RUST_LOG": "winx_code_agent=info" }
}
}
}
Add to ~/.gemini/settings.json:
{
"mcpServers": {
"winx": {
"command": "winx-code-agent",
"args": [],
"env": { "RUST_LOG": "winx_code_agent=info" }
}
}
}
agy is Google's new Gemini-powered CLI (Go binary, usually at ~/.local/bin/agy). No mcp add subcommand yet — it
reads MCP servers from JSON.
Edit ~/.gemini/config/mcp_config.json (also ~/.gemini/antigravity/mcp_config.json if you run the Antigravity IDE
alongside):
{
"mcpServers": {
"winx": {
"command": "winx-code-agent",
"env": { "RUST_LOG": "winx_code_agent=info" }
}
}
}
If winx-code-agent is not on the agy process $PATH, swap command for the absolute path (~/.cargo/bin/winx-code-agent after cargo install winx-code-agent).
Add to your ~/.continue/config.yaml:
mcpServers:
- name: winx
command: winx-code-agent
env:
RUST_LOG: winx_code_agent=info
Add to ~/.kiro/settings/mcp.json:
{
"mcpServers": {
"winx": {
"command": "winx-code-agent",
"env": { "RUST_LOG": "winx_code_agent=info" }
}
}
}
Settings → MCP Servers → Add MCP Server:
{
"winx": {
"command": "winx-code-agent",
"env": { "RUST_LOG": "winx_code_agent=info" }
}
}
Add to your Roo Code MCP config:
{
"mcpServers": {
"winx": {
"type": "stdio",
"command": "winx-code-agent"
}
}
}
Any client that speaks stdio MCP works with this shape:
{
"mcpServers": {
"winx": {
"command": "winx-code-agent",
"args": [],
"env": { "RUST_LOG": "winx_code_agent=info" }
}
}
}
If your client launches Winx with an empty $PATH, swap command for the absolute path (
~/.cargo/bin/winx-code-agent).
For unreleased changes or a custom build:
git clone https://github.com/gabrielmaialva33/winx-code-agent.git
cd winx-code-agent
cargo install --path .
Or run it without installing:
cargo run --release
List MCP tools in your client. You should see six entries: Initialize, BashCommand, ReadFiles, FileWriteOrEdit,
ContextSave, ReadImage. The first call always has to be Initialize — Winx tracks workspace + mode per thread.
By default Winx speaks MCP over stdio — the local transport every desktop client (Claude Desktop, Cursor, VS Code) uses. For clients that live in the cloud and can't reach your machine over stdio — like ChatGPT's developer-mode custom connectors — Winx can also serve MCP over Streamable HTTP:
winx serve --http --bind 127.0.0.1:8000 --token "$(openssl rand -hex 24)"
The MCP protocol is served at /mcp. Every request must carry the token, either as Authorization: Bearer <token> or a
?token=<token> query parameter. Without a token the server refuses to start — serving a shell over the network without
auth is remote code execution waiting to happen.
| Flag | Purpose |
|---|---|
--http |
Serve over Streamable HTTP instead of stdio. |
--bind |
Listen address. Defaults to 127.0.0.1:8000. Keep it on loopback. |
--token |
Shared secret required on every request. Falls back to the WINX_HTTP_TOKEN env var. |
--allowed-host |
Extra Host authority to accept (your tunnel hostname). Repeatable. Loopback is always allowed. |
Remote clients run in the cloud, so the endpoint has to be reachable over HTTPS — put a tunnel in front of the loopback listener and allow its hostname through the built-in DNS-rebinding guard:
# 1. tunnel first, to learn the public hostname
cloudflared tunnel --url http://localhost:8000
# -> https://<random>.trycloudflare.com
# 2. start Winx, allowing that host
winx serve --http --bind 127.0.0.1:8000 \
--token "$(openssl rand -hex 24)" \
--allowed-host <random>.trycloudflare.com
In ChatGPT (Settings → Apps → Advanced → Developer mode), add a connector with:
https://<random>.trycloudflare.com/mcp?token=<your-token>Remote clients are effectively stateless — they don't reuse the MCP session between tool calls — so the HTTP
transport shares one shell session across all requests: the shell Initialize creates stays alive for the lifetime of
the server, and later BashCommand calls find it. Reuse the same thread_id across calls.
[!WARNING] The HTTP transport puts arbitrary shell and file access on the network. Anyone with the token (and URL) gets a shell on your machine as your user — and not just inside the workspace, since
BashCommandinwcgwmode isn't path-restricted. Bind to loopback, keep it behind an authenticated tunnel, preferarchitect/code_writermode or a container, and shut it down when you're done.
All optional — Winx works out of the box without any of these.
| Variable | Effect |
|---|---|
RUST_LOG |
Log verbosity, e.g. winx_code_agent=info. At info you get the per-call audit trail (tool name, arg summary, duration, ok/error). |
WINX_HTTP_TOKEN |
Shared secret for the HTTP transport, used if --token isn't passed (see Remote access). |
WINX_NO_COMPRESS |
Set to 1 to disable output compression and see raw, uncollapsed shell output (the [winx: ×N] collapsing is on by default). |
WINX_KEEP_TAIL_PIPE |
Set to 1 to keep a trailing | tail … instead of stripping it. Winx truncates output server-side, so by default it drops a redundant trailing tail (wcgw parity). |
WINX_USE_SCREEN / WINX_ATTACH_TERMINAL |
Run the shell inside screen/tmux so you can attach to the live session. Set to screen, tmux, or any truthy value; Winx prints an attach hint on Initialize. |
WINX_OPEN_CONTEXT |
Set to 1 to open the saved context file in your default app after ContextSave. |
WINX_SHELL |
Set to zsh to run the session under zsh instead of bash (opt-in; bash stays the default). Falls back to bash if zsh isn't on PATH or the mode is restricted. |
WINX_SERVER_INSTRUCTIONS |
Extra operator instructions appended to every Initialize response (e.g. house rules for the agent). |
cargo fmt --all
cargo clippy --all-targets --all-features -- -D warnings
cargo test --all-features
CI runs the same three. If you touch src/state/pty.rs or anything in src/tools/bash_command.rs, the regression suite
at tests/bash_pty_regression_test.rs is what protects against the usual TUI/PTY foot-guns — run it first.
By default this is a local (stdio) MCP server. Anything connected to it can read files, edit files, and run shell
commands inside the workspace — same blast radius as letting the model into your terminal. The optional HTTP transport
(--http) extends that reach to the network; see
Remote access for the extra precautions it demands.
If you want a tighter leash:
architect mode disables writes and most commands;code_writer mode lets you allowlist commands and write globs.SECURITY.md has the disclosure process and threat model.
MIT - Gabriel Maia (@gabrielmaialva33)
Выполни в терминале:
claude mcp add gabrielmaialva33-winx-code-agent -- npx pro-tip
Поставил gabrielmaialva33/winx-code-agent? Скажи Claude: «запомни почему я установил gabrielmaialva33/winx-code-agent и что хочу попробовать» — попадёт в твой Vault.
как это работает →CSA PROJECT - FZCO © 2026 IFZA Business Park, DDP, Premises Number 31174 - 001
Безопасность
Низкий рискАвтоматическая эвристика по публичным данным — не гарантия безопасности.