{
  "markdown": "[![Tests](https://github.com/jarmstrong158/Conductor/actions/workflows/tests.yml/badge.svg)](https://github.com/jarmstrong158/Conductor/actions/workflows/tests.yml)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)\n\n<!-- mcp-name: io.github.jarmstrong158/Conductor -->\n\n# Conductor\n\n**Claude's hands for local automation — with a web dashboard for the humans who watch it.**\n\nConductor gives Claude direct, persistent control of a local task runner. Tell Claude what you want automated; it creates the scheduled workers, builds multi-step pipelines, wires up email reports, fires test runs, and reads back the logs when something fails — all through conversation. A web dashboard at `127.0.0.1:5000` runs alongside it for humans who want to peek at status, click pause, or hand-edit a worker.\n\nOriginally built to automate warehouse reporting workflows (the daily ShipExec metrics pull) and now general-purpose: any Python / batch / shell script, any schedule, any chain.\n\n> **The MCP server lives in this repo** (`server.py`) — the thin layer that exposes Conductor's REST API as Claude tools. It's bundled and auto-registered on install, so most users won't need to touch it directly. The separate [conductor-mcp](https://github.com/jarmstrong158/conductor-mcp) repo is **deprecated** — it holds an older copy without the auto-launch race protection.\n\n![Conductor Dashboard](Readmejpegs/Screenshot%202026-04-01%20210159.png)\n\n## Claude Integration\n\nConductor registers itself as an MCP server in Claude Desktop on first launch. After restarting Claude Desktop once, Claude has 21 tools for full control:\n\n**Example conversation:**\n\n> **You:** Run my metrics script every night at 8:30 PM and email me the report\n>\n> **Claude:** I'll set that up using the Run + Email template.\n> *(creates the worker, configures the schedule, wires up Gmail, fires it to test)*\n> Done — worker \"Daily Metrics Report\" is live. Check your email for the test run.\n\n> **You:** That uptime check keeps failing. What's going on?\n>\n> **Claude:** *(pulls the last 10 runs, reads the error logs)*\n> The site returned a 503 three times in the last hour. The SSL certificate expired yesterday. Here's the full error from the last run...\n\n> **You:** Chain my backup script and cleanup script together. Run backup first, then cleanup after it finishes. Every day at 2 AM.\n>\n> **Claude:** *(creates a chain with stage 0 = backup, stage 1 = cleanup, cron schedule \"0 2 * * *\")*\n> Chain \"Nightly Maintenance\" created with 2 steps. Backup runs first, cleanup runs after it succeeds.\n\n**How it works:**\n1. Install Conductor (Windows installer or from source)\n2. Conductor writes its MCP entry to Claude Desktop's config on first launch\n3. Restart Claude Desktop once\n4. Claude now controls Conductor through natural language — create workers, build chains, fire tasks, check logs, send emails\n\n## Features\n\n- **Claude-Controlled** — 21 MCP tools let Claude create workers, chains, groups, templates, and more. Non-technical users can automate anything through conversation.\n- **Flexible Scheduling** — Fixed times (`09:00, 14:30`), intervals (`2h 30m`), or cron expressions (`0 9 * * 1-5` with plain-English preview).\n- **Task Support** — Python (`.py`), batch (`.bat`, `.cmd`), and shell (`.sh`) scripts. Selenium and GUI scripts run in a visible terminal window via `new_console`.\n- **Built-in Email** — configure Gmail once, then any template or worker can send emails. Run + Email template for automated reports. Folder Watcher emails files on arrival. Uptime Check sends DOWN alerts. Worker notifications on success/failure.\n- **Task Chains** — multi-step pipelines with parallel execution. Same stage number = run in parallel. Stop-on-failure toggle.\n- **Worker Groups** — collapsible named groups for organization. Bulk pause/delete per group.\n- **Run History** — per-worker/chain history with status, duration, and error details. Colored dots show last run status at a glance.\n- **Built-in Templates** — Folder Backup, File Cleanup, Folder Watcher, Uptime Check, Open URL, Run + Email. Generated scripts are stdlib-only and self-contained.\n- **Per-worker Environment Variables** — inject `KEY=VALUE` pairs into subprocess environments.\n- **Worker Timeout** — kill and log workers that run over a set number of minutes.\n- **Email Notifications** — per-worker/chain email alerts: Always, On Failure, or On Success.\n- **Import / Export** — portable JSON snapshot of all workers, chains, and groups.\n- **Saved Profiles** — save and load named worker configurations.\n- **Auto-start on Login** — one-click Registry Run key install. No admin required.\n- **Auto-update Check** — modal dialog when a newer release is available.\n- **System Tray Icon** — right-click for Open Dashboard or Stop.\n- **AI Error Analysis** — send error logs to Claude for diagnosis directly in the dashboard.\n- **Persistent State** — SQLite database. Workers and chains restore on restart.\n\n### Add Workers Form\n\n![Add Workers form](Readmejpegs/Screenshot%202026-04-01%20210231.png)\n\n### Built-in Templates\n\n![Template picker modal](Readmejpegs/Screenshot%202026-04-01%20210243.png)\n\n### Task Chains\n\n![New Task Chain modal](Readmejpegs/Screenshot%202026-04-01%20210257.png)\n\n### Debug Log\n\n![Debug log panel](Readmejpegs/Screenshot%202026-04-01%20210327.png)\n\n## Installation (Windows)\n\nDownload and run **`Conductor_Setup.exe`** from the [latest release](https://github.com/jarmstrong158/conductor/releases/latest).\n\n- Requires Python 3 on the machine (see note below) — Conductor runs your `.py` workers with it\n- Installs to `%AppData%\\Conductor` — no admin/UAC required\n- Adds Start Menu shortcut and optional desktop shortcut\n- Optional auto-start at login\n- Uninstaller included\n\n> **Python is required for Python workers.** Conductor itself ships as a self-contained\n> executable, but it runs your `.py` scripts with a real interpreter found on your system\n> (the `py` launcher, `PATH`, or the Windows registry). If none is found, workers fail\n> loudly with instructions — they are never reported as successful.\n> Set `CONDUCTOR_PYTHON` to a full path to pin a specific interpreter.\n> `.bat` / `.cmd` / `.sh` workers do not need Python.\n\n## Setup from Source\n\n### Requirements\n\n- Python 3.10+\n\n```bash\ngit clone https://github.com/jarmstrong158/conductor.git\ncd conductor\npip install -r requirements.txt\npython launch.py\n```\n\nThe dashboard opens at [http://127.0.0.1:5000](http://127.0.0.1:5000). Press `Ctrl+C` to stop.\n\n## Building the Installer\n\n```\n.\\build.bat\n```\n\nForces a full rebuild:\n```\n.\\build.bat --rebuild\n```\n\nOutput: `Output\\Conductor_Setup.exe`. Requires [Inno Setup](https://jrsoftware.org/isdl.php).\n\n## Task File Format\n\n### Python (`.py`)\n\nScripts run as subprocesses:\n\n```python\nif __name__ == \"__main__\":\n    print(\"Task executed!\")\n```\n\n### Batch / Shell (`.bat`, `.sh`, `.cmd`)\n\nExecuted as subprocesses. The worker's output directory (if set) is used as the working directory.\n\n## Schedule Formats\n\n| Type | Format | Example |\n|------|--------|---------|\n| Fixed | `HH:MM` or `HH:MM,HH:MM` | `09:00, 14:30, 17:00` |\n| Interval | `Xh Ym` | `2h 30m`, `1h`, `45m` |\n| Cron | 5-field crontab | `0 9 * * 1-5` (weekdays at 9am) |\n\n## Task Chains\n\nChains run multiple scripts in sequence. Each step has a **stage** number — steps with the same stage run in parallel, stages execute in order. **Stop on failure** halts the chain when any step fails.\n\n```\nStage 0: backup.py  ──┐\nStage 0: cleanup.py ──┤  (both run at once)\n                      ↓\nStage 1: report.py    (runs after both finish)\n```\n\n## Templates\n\n| Template | What it does | Email capability |\n|----------|-------------|-----------------|\n| Folder Backup | Copy folder, keep N backups | Summary email |\n| File Cleanup | Delete old files by pattern | Summary email |\n| Folder Watcher | Move/email files by extension | Per-rule: move, email, or both |\n| Uptime Check | Monitor URL, log status | Alert email on DOWN |\n| Open URL | Open URL in browser | — |\n| Run + Email | Run script, email output file | Sends output as attachment |\n\nAll generated scripts use Python stdlib only.\n\n## Architecture\n\n```\nconductor/\n├── launch.py          # Entry point — Flask, browser, tray, MCP registration\n├── app.py             # Flask backend + APScheduler + SQLite\n├── server.py          # MCP server for Claude Desktop\n├── CLAUDE.md          # Context file for Claude Code / Desktop\n├── static/\n│   └── index.html     # Frontend — HTML + CSS + JS (no frameworks)\n├── tasks/\n│   └── example_task.py\n├── templates/\n│   └── generated/     # Auto-generated template scripts\n├── build.bat          # One-click installer build\n├── build_icon.py      # Generates conductor.ico\n├── conductor.spec     # PyInstaller spec\n├── installer.iss      # Inno Setup script\n└── conductor.db       # SQLite database (auto-created)\n```\n\n| Layer | Technology |\n|-------|-----------|\n| Backend | Python 3, Flask |\n| Scheduling | APScheduler (BackgroundScheduler + MemoryJobStore) |\n| Persistence | SQLite (WAL mode) |\n| Frontend | Vanilla JS, single HTML file |\n| AI Integration | Claude via MCP (21 tools) + Anthropic API (error analysis) |\n\n## AI Error Analysis\n\nThe debug log includes an **Analyze Errors** button. When ERROR entries are present, click it to send them to Claude for diagnosis. Requires an Anthropic API key in `.env`:\n\n```\nANTHROPIC_API_KEY=sk-ant-...\n```\n\n**Example — before / after:**\n\nRaw error in the debug log:\n\n```\n[ERROR] worker \"Daily Metrics Report\" exit code 1\nTraceback (most recent call last):\n  File \"C:\\scripts\\metrics.py\", line 142, in <module>\n    driver.find_element(By.ID, \"report-table\").click()\n  File \".../selenium/.../webdriver.py\", line 830, in find_element\n    raise NoSuchElementException(message)\nselenium.common.exceptions.NoSuchElementException: Message: no such element:\nUnable to locate element: {\"method\":\"css selector\",\"selector\":\"[id=\"report-table\"]\"}\n```\n\nClaude's diagnosis (one click later):\n\n> The script is failing on a `find_element` call before the page has finished loading — Selenium is racing the DOM. The element `#report-table` is rendered after an XHR completes. Two fixes, in order of preference:\n> 1. Wrap the lookup in a `WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, \"report-table\")))` so it polls until the element exists.\n> 2. If you don't want to import the wait helpers, a `time.sleep(2)` before the click will work but is brittle.\n> The traceback shows this happened on the first run after a ShipExec UI change yesterday — they may have also renamed the element. Verify the ID is still `report-table` in DevTools before adding the wait.\n\n## Email Setup\n\nClick **📧 Email** in the header to configure Gmail credentials. Requires a [Gmail App Password](https://myaccount.google.com/apppasswords) (2-Step Verification must be enabled first). Credentials are stored locally in `.env` and never transmitted except to Gmail's SMTP server.\n\nOnce configured, all templates and worker notifications can send email.\n\n## API\n\n| Method | Path | Purpose |\n|--------|------|---------|\n| `GET` | `/api/workers` | List all workers |\n| `POST` | `/api/workers` | Register worker(s) |\n| `PUT` | `/api/workers/<id>` | Update worker |\n| `POST` | `/api/workers/<id>/pause` | Toggle pause/resume |\n| `POST` | `/api/workers/<id>/run-now` | Fire immediately |\n| `GET` | `/api/workers/<id>/history` | Run history |\n| `POST` | `/api/workers/<id>/assign-group` | Assign to group |\n| `DELETE` | `/api/workers/<id>` | Delete worker |\n| `POST` | `/api/workers/pause-all` | Pause all workers |\n| `DELETE` | `/api/workers/all` | Delete all workers |\n| `GET` | `/api/chains` | List all chains |\n| `POST` | `/api/chains` | Create chain |\n| `PUT` | `/api/chains/<id>` | Update chain |\n| `POST` | `/api/chains/<id>/pause` | Toggle pause/resume |\n| `POST` | `/api/chains/<id>/run-now` | Fire immediately |\n| `GET` | `/api/chains/<id>/history` | Run history |\n| `DELETE` | `/api/chains/<id>` | Delete chain |\n| `GET` | `/api/groups` | List groups |\n| `POST` | `/api/groups` | Create group |\n| `DELETE` | `/api/groups/<id>` | Delete group |\n| `GET` | `/api/profiles` | List profiles |\n| `POST` | `/api/profiles` | Save profile |\n| `GET` | `/api/profiles/<id>` | Load profile |\n| `DELETE` | `/api/profiles/<id>` | Delete profile |\n| `POST` | `/api/templates` | Create from template |\n| `GET` | `/api/export` | Export all as JSON |\n| `POST` | `/api/import` | Import from JSON |\n| `GET/POST` | `/api/email-settings` | Email configuration |\n| `GET` | `/api/service/status` | Auto-start status |\n| `POST` | `/api/service/install` | Install auto-start |\n| `POST` | `/api/service/uninstall` | Remove auto-start |\n| `GET` | `/api/update-check` | Check for updates |\n| `GET` | `/api/logs?since=N` | Log entries |\n| `GET` | `/api/status` | Scheduler + database status |\n| `GET` | `/api/browse?mode=file\\|dir` | Native file picker |\n\n## License\n\nMIT\n",
  "bytes": 12925,
  "sha": "d9486fed2af3f208ff1f925c97fa47bd573c6d7d70633dad33e294bc22d8c91c",
  "repo_slug": "jarmstrong158/conductor",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_jarmstrong158_conductor_44c72def/readme"
}