# Nyx Cli

> Nyx is an open-source agentic coding CLI that runs on pure Python stdlib. No npm, no pip, no cargo. Features MCP support, subagents, dynamic skills, web search, and hot-swappable LLM providers (OpenRouter, OpenAI, Anthropic).

- **Type:** MCP server
- **Install:** `agentstack add mcp-zolaski333-nyx-cli`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [zolaski333](https://agentstack.voostack.com/s/zolaski333)
- **Installs:** 0
- **Category:** [Developer Tools](https://agentstack.voostack.com/c/developer-tools)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [zolaski333](https://github.com/zolaski333)
- **Source:** https://github.com/zolaski333/nyx-cli

## Install

```sh
agentstack add mcp-zolaski333-nyx-cli
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Nyx

**A standard-library-first agentic coding CLI**

[](https://www.python.org/downloads/)
[](LICENSE)
[](CONTRIBUTING.md)
[](https://github.com/astral-sh/ruff)

**Multi-provider • guarded file edits • MCP stdio • skills • subagents • web search**

---

## Why Nyx?

Nyx is an **experimental agentic coding CLI** that keeps the runtime small and hackable: the core runs on Python 3.10+ standard library, with optional extras for developer tooling and a richer terminal UI.

Nyx is not yet a drop-in replacement for mature coding agents. Today it is best suited for trusted local projects, experimentation, provider flexibility, and workflows where you want to inspect and extend the agent internals.

Distribution note: the PyPI project name `nyx` is already used by another project. If this CLI is published to PyPI, install it as `nyx-cli`; the import package and console command remain `nyx`.

Current strengths:

- Small Python codebase with few runtime assumptions.
- Multi-provider support for OpenRouter, OpenAI-compatible APIs, and Anthropic.
- Guarded file editing through diff/patch previews, rollback history, and sandbox checks.
- Tooling for repo maps, code search, tests, shell commands, memory, MCP stdio servers, Python skills, and subagents.
- CI-friendly single-prompt JSON output.

Experimental areas:

- Shell execution and external tools require care. Nyx now prompts for structurally risky commands, but you should still use it on trusted repositories first.
- MCP servers and Python skills execute local code. Only enable servers and skills you trust.
- Parallel subagents are available and can run in isolated worker processes, but orchestration is still a young feature.

---

## 🚀 Quick Start

### 1. Prerequisites

- **Python 3.10+** ([download](https://www.python.org/downloads/))
- An API key from [OpenRouter](https://openrouter.ai/keys), [OpenAI](https://platform.openai.com/api-keys), or [Anthropic](https://console.anthropic.com/)

### 2. Installation

🐧 Linux / macOS

```bash
# Clone the repository
git clone https://github.com/zolaski333/nyx-cli.git
cd nyx-cli

# Configure your API key
export OPENROUTER_API_KEY="sk-or-..."
# or: export OPENAI_API_KEY="sk-..."
# or: export ANTHROPIC_API_KEY="sk-ant-..."

# Install globally (recommended)
pip install -e ".[tui]"

# Or install directly from Git without keeping a local clone
pipx install "nyx-cli[tui] @ git+https://github.com/zolaski333/nyx-cli.git"

# Run Nyx from any directory
cd /path/to/my/project
nyx
```

> **Note:** If `pip` reports an `externally-managed-environment` error on Ubuntu or Debian, use `pipx`:
> ```bash
> pipx install ".[tui]"
> nyx
> ```

🪟 Windows

```powershell
# Clone the repository
git clone https://github.com/zolaski333/nyx-cli.git
cd nyx-cli

# Configure your API key
$env:OPENROUTER_API_KEY = "sk-or-..."
# or: $env:OPENAI_API_KEY = "sk-..."
# or: $env:ANTHROPIC_API_KEY = "sk-ant-..."

# Install globally (recommended)
pip install -e ".[tui]"

# Or install directly from Git without keeping a local clone
pipx install "nyx-cli[tui] @ git+https://github.com/zolaski333/nyx-cli.git"

# Run Nyx from any directory
cd C:\path\to\my\project
nyx
```

🐳 Docker / no installation

```bash
# Run without installation from the repository directory
python -m nyx.cli
```

---

## 🎮 Usage

### Interactive REPL

```bash
# Go to the directory you want to work in
cd /path/to/my/project

# Start Nyx; it automatically detects the current directory
nyx
```

> **⚡ REPL input shortcuts:**
> - **Tab completion:** Press `Tab` to complete slash commands such as `/help`, `/model`, and `/tools`, as well as file and directory paths.
> - **Command history:** Use the up and down arrow keys to browse previous commands. History is saved automatically between sessions in `~/.nyx_history` (up to 1,000 entries).

### Single prompt

```bash
nyx -p "explain how this Python code works"
```

### Pipe mode

```bash
cat main.py | nyx -p "review this code for bugs"
```

### Custom config

```bash
nyx -c ./myconfig.json
```

### Installation doctor

```bash
nyx doctor
nyx doctor --dev
```

`doctor` checks Python, provider/model configuration, API key presence, Rich, git, pytest, and optional dev tools (`ruff`, `mypy`). It does not call an LLM and works without an API key.

### Override model/provider

```bash
nyx -m "openai/gpt-4o"
nyx --provider anthropic
```

### Working directory

```bash
# Nyx uses the current directory by default
cd /my/project
nyx

# You can also specify a different directory
nyx --dir /another/path
nyx --project /another/path
```

### Pipe mode (stdin)

Nyx supports pipe mode — when stdin is not a TTY (e.g., piped data), the piped content is
automatically prepended to your prompt context:

```bash
# Pipe file content as context
cat main.py | nyx -p "review this code for bugs"

# Pipe command output
git diff | nyx -p "summarise these changes"

# Multi-line pipe
curl -s https://api.example.com/data.json | nyx -p "explain this JSON structure"
```

> **Note**: Pipe mode works by reading all stdin into a context preamble. The `-p` flag is still
> required to specify the actual prompt. If no `-p` is given with piped input, Nyx falls back
> to interactive mode.

### 🚀 CI/CD Integration (`--json`)

For CI/CD pipelines, use `--json` mode to get structured output:

```bash
# JSON output with cost tracking, session ID, timing
nyx --json -p "lint all Python files"

# Example output:
# {
#   "status": "success",
#   "prompt": "lint all Python files",
#   "result": "Fixed 3 issues...",
#   "duration_seconds": 12.45,
#   "session_id": "a1b2c3d4e5f6",
#   "cost": 0.0023,
#   "llm_calls": 2,
#   "tool_calls": 5
# }
```

The `--json` flag requires `--prompt`/`-p` and outputs one JSON object with:
- `status`: `"success"` or `"error"`
- `result` / `error`: The output or error message
- `duration_seconds`: Wall-clock time
- `session_id`: Unique session identifier
- `cost`: Estimated USD cost
- `llm_calls`, `tool_calls`: Usage statistics

### Flags

| Flag | Description |
|------|-------------|
| `-p, --prompt` | Run a single prompt and exit |
| `-c, --config` | Path to custom config.json |
| `-m, --model` | Override model (e.g. `openai/gpt-4o`) |
| `--provider` | Override provider (`openrouter`, `openai`, `anthropic`) |
| `-d, --dir` | Working directory for the AI (default: current dir) |
| `--project` | Alias for `--dir` |
| `--json` | JSON output mode for CI/CD (requires `--prompt`) |
| `--no-stream` | Disable streaming output |
| `--no-color` | Disable ANSI color output |
| `--no-rich` | Force basic CLI even if Rich is installed |
| `--version` | Print the Nyx version |
| `-v, --verbose` | Enable verbose/debug logging |

### Interactive Commands

| Command | Description |
|---------|-------------|
| `/help` | Show available commands |
| `/model` | Show current model |
| `/model ` | Change model on the fly |
| `/mode [chat\|code\|architect\|debug]` | Show or change the agent mode |
| `/autonomy [ask\|auto\|yolo]` | Show or change approval behavior |
| `/config` | Show config status |
| `/config save [--global]` | Persist current provider/model/mode/autonomy |
| `/config set [--global]  ` | Set a config value |
| `/clear` | Clear conversation context |
| `/tools [N]` | List all available tools (paginated, optional page N) |
| `/memory [N]` | Show memory status with paginated entries |
| `/conversations [N]` | List saved conversations (paginated, optional page N) |
| `/switch ` | Switch to a saved conversation (supports partial ID) |
| `/reset` | Reset agent + disconnect MCP |
| `/exit` | Quit |

> **Tip**: `/tools 2`, `/memory 3`, `/conversations 2` navigate paginated views.
> `/switch abc` switches to conversation with ID starting with "abc".

---

## 🧠 Features

### 🔌 MCP Support

Connect [Model Context Protocol](https://modelcontextprotocol.io) stdio servers:

```json
{
  "mcp_servers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/dir"],
      "enabled": true
    },
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "enabled": true,
      "env": { "GITHUB_TOKEN": "ghp_..." }
    }
  }
}
```

Nyx supports stdio MCP servers. SSE/streamable HTTP transport is not currently implemented. Nyx does not pass the full parent environment to MCP servers by default. Put required tokens in the server's explicit `env` block, or list non-secret variables in `pass_env`.

MCP client robustness settings:

```json
{
  "mcp": {
    "request_timeout": 30,
    "connect_timeout": 30,
    "max_response_chars": 20000,
    "restart_on_failure": true,
    "sandbox_enabled": false,
    "sandbox_docker_image": "python:3.11-slim-buster",
    "sandbox_network": "none",
    "sandbox_read_only": false
  }
}
```

The stdio client drains stdout and stderr in background threads, serializes requests per server, validates server/tool names, limits tool output size, and can restart a failed server once before returning an error. MCP servers can also be launched through Docker/Podman by enabling the MCP sandbox globally or with a per-server `sandbox` block.

### 🎯 Skill System

Create Python skills in the `skills/` directory — their metadata is auto-discovered and exposed as tools:

```python
# skills/my_skill.py
name = "my_skill"
description = "Does something useful"
parameters = {
    "type": "object",
    "properties": {
        "input": {"type": "string", "description": "Some input"}
    },
    "required": ["input"],
}

def execute(arguments: dict) -> str:
    return f"Processed: {arguments['input']}"
```

Skill discovery reads static metadata and does not import the skill module. The Python code runs only when the skill is called. By default, execution happens in a worker process with a hard timeout and bounded output:

```json
{
  "skills_enabled": true,
  "skills": {
    "process_isolation": true,
    "default_timeout_seconds": 30,
    "max_output_chars": 20000
  }
}
```

Packages can also define an explicit `skill.json` manifest:

```json
{
  "name": "my_skill",
  "description": "Does something useful",
  "parameters": {"type": "object", "properties": {}},
  "file": "runner.py",
  "entrypoint": "execute"
}
```

Skills are still trusted local Python code: isolated workers use the same OS user and filesystem permissions as Nyx. Only load skills from directories you trust. Set `"skills_enabled": false` in config to disable skill discovery.

### 👥 Subagents

Spawn child agents for complex tasks. Parallel subagent orchestration is experimental but now uses a more explicit execution contract:

```
You> analyse the codebase and generate a refactoring plan

Agent> I'll spawn a subagent for code analysis...
[Subagent:code-analysis] Analysing...
```

Subagents now use a structured task/result contract internally:

- per-task `max_steps` budget;
- explicit `status`, `error_type`, token count, step count, tool-call trace and duration;
- validation that model-requested tools are present in the subagent's allowed tool set;
- propagation of updated tool/context settings to already-spawned subagents;
- optional process isolation with hard worker termination on timeout;
- parallel results returned in input order with completed/failed/timed-out counts.

Process isolation is enabled by default for subagents that can be recreated from config. Custom in-memory providers or custom tool executors fall back to in-process execution so tests and embedded integrations keep working.

```json
{
  "subagents": {
    "process_isolation": true,
    "default_timeout_seconds": 120
  }
}
```

### 🌐 Web Search

Built-in SearXNG JSON search is the default, with DuckDuckGo available as a legacy fallback. No API key is required. The agent can search the web and fetch pages.

### 💾 Persistent Memory

Conversations are saved to disk with persistent memory and basic summarisation support. Context compression in the live agent history is intentionally conservative; do not treat memory as perfect recall.

### 🔧 Built-in Tools

| Tool | Description |
|------|-------------|
| `web_search` | Search the internet (SearXNG JSON by default, no API key) |
| `web_fetch` | Fetch and extract text from any URL |
| `subagent_run` | Spawn a subagent for a subtask |
| `parallel_subagents` | Run multiple subagents in parallel |
| `memory_save` | Save notes to persistent memory |
| `memory_recall` | Search past conversations |
| `execute_command` | Run bounded shell commands with permission checks and explicit timeout termination |
| `start_process` | Start a long-running process such as a dev server or simple REPL |
| `read_process_output` | Read buffered stdout/stderr from a started process |
| `write_process_input` | Send stdin to a started process |
| `stop_process` | Stop a started process |
| `read_file` | Read files inside the sandbox/allowlist |
| `write_file` | Write/create files through the patch workflow; supports `dry_run` previews |
| `append_file` | Append to existing files |
| `list_files` | List directory contents |
| `apply_diff` | Apply unified diff or SEARCH/REPLACE patches; supports `dry_run`; full-file fallback requires `allow_write_fallback` |
| `rollback_file` | Roll back the most recent file change |
| `patch_history` | Show recent patch history |
| `repo_map` | Summarise repository structure, Git status and tests |
| `search_code` | Search code with ripgrep/fallback search |
| `run_tests` | Discover and run project tests |
| `auto_correct_tests` | Structured test-fixing loop with subagent, progress checks and rollback |
| `find_references` | Find references to a symbol |
| `finish` | Signal task completion |

### Agent modes and autonomy

Modes:

- `chat`: default conversational mode with the full configured tool set.
- `code`: coding-oriented prompt and full configured tool set.
- `architect`: read-only planning mode; only read/search/context tools are exposed.
- `debug`: debugging-oriented prompt and full configured tool set.

Autonomy:

- `ask`: approval prompts are used for risky commands and guarded file operations.
- `auto`: file changes may be auto-approved, while risky shell commands still require approval.
- `yolo`: approval prompts are bypassed except for hard-deny permission rules. Use only in disposable or fully trusted projects.

---

## ⚙️ Configuration

### Environment Variables (recommended)

```bash
export OPENROUTER_API_KEY="sk-or-..."
export OPENAI_API_KEY="sk-..."
export ANTHROPIC_API_KEY="sk-ant-..."
export NYX_MODEL="openai/gpt-4o"       # Override default model
export NYX_PROVIDER="anthropic"         # Override default provider
```

### config.json

See [`config.example.json`](config.example.json) for all available options.

Priority chain: **Environment variables > trusted config.json > Defaults**

Workspace-local configs (`./config.json` and `./.nyx/config.json`) are loaded only after the current folder is trusted. Trusted folders are stored in `~/.nyx/trusted_workspaces.json`. In non-interactive runs, untrusted local configs are skipped and Nyx falls back to global/default configuration.

### Security model

- File reads and writes are restricted to the project sandbox unless an explicit allow path is configured.
- File modifications are guarded by sandbox checks and approval prompts, but the project is still experimental.
- Workspace-local config files are gated by Workspace Trust so a cloned repository cannot silently override Nyx settings before approval.
- Simple shell commands run without a shell where practical. Composite commands and shell-control operators such as `&&`, `|`, redirection and command substitution require approval.
- Dangerous-command keyword checks are only advisory UX guardrails. They are not a security boundary and can be bypassed with shell syntax, wrapper scripts, aliases, or platform-specific behavior. Use Docker/Podman sandbox isolation for real containment.
- MCP servers receive a minimal environment by default; secrets are not inh

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [zolaski333](https://github.com/zolaski333)
- **Source:** [zolaski333/nyx-cli](https://github.com/zolaski333/nyx-cli)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-zolaski333-nyx-cli
- Seller: https://agentstack.voostack.com/s/zolaski333
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
