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
- Host: GitHub
- URL: https://github.com/wbnns/cx
- Owner: wbnns
- License: mit
- Created: 2026-02-12T10:49:13.000Z (4 months ago)
- Default Branch: main
- Last Pushed: 2026-03-05T13:22:53.000Z (4 months ago)
- Last Synced: 2026-03-05T17:22:22.995Z (4 months ago)
- Topics: agent-management, agentic-workflow, claude, claude-code
- Language: TypeScript
- Homepage: https://cx.wbnns.com/
- Size: 320 KB
- Stars: 8
- Watchers: 0
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
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