An open API service indexing awesome lists of open source software.

https://github.com/wbnns/cx

[cx] Claude Extender
https://github.com/wbnns/cx

agent-management agentic-workflow claude claude-code

Last synced: 20 days ago
JSON representation

[cx] Claude Extender

Awesome Lists containing this project

README

          

# cx: Claude Extender

Autonomous agent management for [Claude Code](https://docs.anthropic.com/en/docs/claude-code). Create agents that run on schedules, watch for conditions, or maintain persistent sessions — all defined as markdown files in your **cx directory**.

## What It Does

cx runs a background daemon that manages your agents:

- **Scheduled agents** run on cron schedules (daily surf report, weekly digest, etc.)
- **Watcher agents** run lightweight check scripts and trigger Claude only when conditions are met (new emails, page changes, price alerts)
- **Persistent agents** maintain long-running sessions with heartbeats and checkpoints
- **Issue agents** receive issue links (Linear, GitHub Issues, etc.) via Telegram, spin up Claude in a git worktree, open PRs, and autonomously remediate reviewer feedback until the PR is clean

Every agent is a markdown file with YAML frontmatter. Instructions go in the body, configuration goes in the frontmatter. Run logs, memory, and costs are all stored as markdown — browsable as plain markdown with full backlinks and search.

## Quick Start

```bash
# Install from source
git clone https://github.com/wbnns/cx.git && cd cx
npm install && npm run build && sudo npm link

# Initialize from your cx directory
cd ~/my-project
cx init

# Configure secrets
cx secrets set global ANTHROPIC_API_KEY sk-ant-...

# Create your first agent
cx create surf-report --mode scheduled
cx edit surf-report # write instructions

# Start the daemon and trigger a manual run
cx daemon start
cx start surf-report
```

## Agent File Format

Agents are markdown files in `cx/agents/` with YAML frontmatter:

```yaml
---
name: gmail-watcher
type: agent
status: active
execution:
mode: scheduled
schedule:
expression: "0 6 * * *"
type: cron
timezone: Atlantic/Azores
tools:
- mcp__gmail__list_unread
- mcp__gmail__read_email
- mcp__gmail__archive
- mcp__gmail__mark_read
notifications:
- channel: telegram
events: [completion, failure]
memory:
enabled: true
env_ref: email
mcp_config: /home/deploy/nova/cx/tools/gmail-mcp-config.json
---

# Gmail Watcher

Check for new unread emails.
Summarize anything important and archive the rest.
```

The `name` field provides a human-readable identifier. The `mcp_config` field points to a JSON file that tells Claude Code which MCP tool servers to start. Tools prefixed with `mcp____` correspond to tools exposed by those servers — see [MCP Tools](#mcp-tools) below.

## Four Agent Modes

### Scheduled

Runs on a cron schedule. Good for daily reports, periodic checks, recurring tasks.

```yaml
execution:
mode: scheduled
schedule:
expression: "0 9 * * 1-5" # weekdays at 9am
timezone: America/New_York
```

### Watcher

Runs a cheap check script frequently; triggers Claude only when something happens. Good for email monitoring, page changes, price alerts.

```yaml
execution:
mode: watcher
watcher:
script: email-checker.js
poll_interval_seconds: 300
cooldown_seconds: 3600
pass_context: true
```

Watcher scripts are plain JS or Python in `cx/watchers/`:

```javascript
module.exports = async function check(config) {
const data = await fetchSomething();
return {
triggered: data.hasNewItems,
context: { items: data.items } // passed to Claude
};
};
```

### Persistent

Maintains a long-running Claude session with heartbeats and checkpoints. Good for ongoing research, monitoring dashboards, or tasks that build state over time.

```yaml
execution:
mode: persistent
persistent:
heartbeat_interval_seconds: 1800
checkpoint_interval_minutes: 60
restart_policy: on_failure
max_session_duration_hours: 24
```

### Issue (Linear Agent)

Triggered by sending an issue link (e.g., Linear, GitHub Issues) to the Telegram bot. A standalone service creates a git worktree, fetches the issue details, spawns Claude to implement the work, opens a PR, and then monitors for reviewer feedback — remediating comments and fixing CI failures in a loop until the PR is clean.

```
User sends Linear URL to Telegram


telegram-bot.js detects issue URL
│ POST to linear-agent service

linear-agent.mjs
├─ Create git worktree from main
├─ Fetch issue details via API
├─ Spawn Claude to implement the work
├─ Detect and report PR URL
├─ Monitor for review comments (every 10 min)
│ └─ Remediate feedback, re-request reviews
├─ Check CI after feedback is quiet
│ └─ Fix PR-related failures, re-request reviews
└─ Notify completion via Telegram
```

The service runs as a systemd unit (`cx-linear-agent.service`) and handles concurrent jobs. While this implementation uses Linear, the pattern works with any issue tracker — the issue-fetching function can be swapped for GitHub Issues, Jira, or any system with an API.

## MCP Tools

Agents can use custom tools via [MCP (Model Context Protocol)](https://modelcontextprotocol.io/) servers. An MCP server is a small program that exposes tools over stdio — Claude Code starts it automatically and calls its tools during a run.

### Wiring an MCP server to an agent

1. **Write the server** — a Node.js (or Python) script that implements `ListTools` and `CallTool` handlers using `@modelcontextprotocol/sdk`. Place it in `cx/tools/`.

2. **Create a config JSON** pointing to the server:

```json
{
"mcpServers": {
"gmail": {
"command": "node",
"args": ["/home/deploy/nova/cx/tools/gmail-mcp-server.js"]
}
}
}
```

3. **Reference it in the agent's frontmatter** with `mcp_config`:

```yaml
mcp_config: /home/deploy/nova/cx/tools/gmail-mcp-config.json
```

4. **List the tools** in the agent's `tools` array using the `mcp____` naming convention:

```yaml
tools:
- mcp__gmail__list_unread
- mcp__gmail__read_email
- mcp__gmail__archive
```

The server name (`gmail`) matches the key in the config JSON. The tool name (`list_unread`) matches what the server's `ListTools` handler returns.

MCP servers and their configs live in `cx/tools/` by convention, with a shared `package.json` for dependencies.

## CLI Commands

| Command | Description |
|---------|-------------|
| `cx init` | Initialize cx in current directory |
| `cx create ` | Create a new agent |
| `cx edit ` | Open agent file in `$EDITOR` |
| `cx list` | List all agents |
| `cx status` | Quick status overview |
| `cx start ` | Manually trigger an agent |
| `cx stop ` | Stop a running agent |
| `cx pause ` | Pause an agent |
| `cx resume ` | Resume a paused agent |
| `cx delete ` | Delete an agent (moves to `.trash/`) |
| `cx logs ` | View run logs |
| `cx memory ` | View agent memory |
| `cx compact ` | Trigger memory compaction |
| `cx costs` | View cost breakdown |
| `cx secrets` | Manage secret groups |
| `cx daemon` | Manage background daemon |
| `cx test-watcher ` | Test a watcher script |
| `cx install-deps` | Install watcher dependencies |

## Memory System

Each agent has persistent memory in `cx/memory//current.md`. After every run, the result is appended. This file is included in the next run's context, so agents remember what they've done.

When memory exceeds a token threshold, cx automatically compacts it — summarizing old entries into an archive and keeping `current.md` focused.

**Persistent Notes** at the top of `current.md` survive compaction. Use them for long-term facts the agent should always know.

## Secrets

Secrets are stored outside the cx directory at `~/.config/cx/secrets/` so they're never synced or committed:

```bash
cx secrets set global API_KEY sk-xxx
cx secrets set email GMAIL_USER you@gmail.com
cx secrets list
```

Reference a secret group in an agent's frontmatter with `env_ref: `. The secrets are injected as environment variables at runtime.

## Cost Management

cx tracks every API call:

```bash
cx costs # totals by agent
cx costs --period 2026-02 # filter by month
cx costs --by category # group by category
```

Set limits in `config.yaml` and per-agent in frontmatter:

```yaml
# config.yaml
cost_limits:
daily_usd: 25
monthly_budget_usd: 100

# agent frontmatter
resource_limits:
max_cost_usd: 0.15 # per run
max_cost_per_day_usd: 5.00 # persistent agents
```

## Directory Structure

```
my-project/
cx/
agents/ # Agent markdown files
services/ # Standalone agent services (e.g., linear-agent.mjs)
tools/ # MCP servers, bots, and supporting scripts
watchers/ # Watcher check scripts
memory/ # Agent memory (current + archives)
runs/ # Run logs organized by date
_templates/ # Templates for new agents
.trash/ # Deleted agents (recoverable)
costs.md # Cost ledger
dashboard.md # Dashboard
```

## Configuration

Global config lives at `~/.config/cx/config.yaml`:

```yaml
cx_path: ~/my-project
claude_path: claude
default_model: sonnet
default_permission_mode: dangerouslySkipPermissions
timezone: America/Los_Angeles
daemon:
tick_interval_seconds: 30
log_file: ~/.config/cx/daemon.log
notifications:
telegram:
bot_token: "YOUR_BOT_TOKEN"
default_chat_id: "YOUR_CHAT_ID"
cost_limits:
daily_usd: 25
monthly_budget_usd: 100
compaction:
default_model: haiku
```

## Requirements

- Node.js 20+
- Claude Code CLI (authenticated)

## Documentation

See the full [User Guide](docs/user-guide.md) for detailed documentation including watcher script examples, memory management, the complete configuration reference, and troubleshooting.

## Disclaimer

cx is an independent open-source project and is not affiliated with, endorsed by, or sponsored by Anthropic, PBC. Claude and Claude Code are trademarks of Anthropic, PBC.

## License

MIT