Skip to main content

Lightweight, git-native multi-agent orchestration framework for autonomous project execution

Project description

lindy-orchestrator

CI Config E2E PyPI Python 3.11+ License: MIT

The harness engineer for your AI coding agents.

lindy-orchestrator acts as the harness engineer of your codebase: it never writes code itself, but it wires everything together — decomposing goals into dependency-ordered task DAGs, dispatching AI coding agents to isolated module directories, validating their output through pluggable QA gates, and coordinating the whole pipeline via markdown and git.

Just as a harness engineer in a factory connects every subsystem without owning any of them, lindy-orchestrator sits above your agents and keeps them on track. No database, no shared memory — just git and your existing project.


Table of Contents


Install

pip install lindy-orchestrator            # PyPI
pip install lindy-orchestrator[api]       # with Anthropic API support
git clone https://github.com/eddieran/lindy-orchestrator.git && cd lindy-orchestrator
pip install -e ".[dev]"                   # from source

Requirements: Python 3.11+, Claude Code CLI (default provider) or OpenAI Codex CLI (alternative provider) in PATH.


Quick Start

# Choose your provider once, globally
lindy-orchestrate config set provider codex_cli        # or claude_cli (default)

lindy-orchestrate onboard                              # detect modules, generate config
lindy-orchestrate plan "Add user authentication"       # preview task plan
lindy-orchestrate run "Add user authentication"        # execute with full orchestration
lindy-orchestrate run "Add auth" --provider codex_cli  # per-command override

How It Works

1. Read module STATUS.md files (current state)
2. LLM decomposes goal into JSON task DAG with dependencies
3. Scheduler dispatches ready tasks in parallel
4. Each task: agent works in module dir -> commits -> pushes to task branch
5. QA gates validate (CI, shell commands, structural checks, agent review)
6. On failure: structured remediation feedback -> retry (up to N times)
7. Generate execution summary report with per-task metrics

CLI Reference

All commands accept -c path/to/orchestrator.yaml to specify a config file.

Command Description
run Execute a goal: plan, dispatch, QA, retry, report
plan Generate a task plan without executing
resume Resume a previous session from checkpoint
onboard Unified onboarding (scaffold / init+onboard / re-onboard)
init Quick scaffold: detect modules, generate config
config Manage global and project-local settings (provider, etc.)
status Module health, mailbox summary, recent logs
logs Alias for status --logs-only
validate Validate config, module paths, CLI availability
gc Clean stale branches, old sessions, oversized logs
scan Entropy scanner: drift, contracts, quality grades
issues List issues from configured tracker
run-issue Fetch issue and execute as orchestration goal
mailbox View or send inter-agent messages
version Print version (--json for JSON, -V flag also works)

run

lindy-orchestrate run "Add JWT auth"
lindy-orchestrate run --file goal.md              # goal from file (- for stdin)
lindy-orchestrate run --plan plan.json            # execute saved plan, skip planning
lindy-orchestrate run --dry-run --verbose         # analyze only, detailed output
lindy-orchestrate run --provider codex_cli        # use Codex CLI
Flag Short Description
--file -f Read goal from file; - for stdin
--plan -p Execute saved plan JSON (skip LLM planning)
--dry-run Analyze only, no agent dispatch
--verbose -v Show tool use events and detailed output
--provider Dispatch provider: claude_cli (default) or codex_cli

plan

lindy-orchestrate plan "Add JWT auth"
lindy-orchestrate plan --file goal.md -o plan.json

Plans auto-save to .orchestrator/plans/ and can be executed later with run --plan.

Flag Short Description
--file -f Read goal from file
--output -o Save plan JSON to specific path

resume

lindy-orchestrate resume                # resume latest session
lindy-orchestrate resume abc12345       # resume specific session ID

Skips completed tasks, resets failed tasks to pending, re-executes remaining.

onboard

Detects project state and adapts: empty project -> scaffold (LLM-driven, requires description); existing project without config -> init+onboard (detect, interview, generate); already onboarded -> re-onboard (update).

lindy-orchestrate onboard                           # auto-detect mode
lindy-orchestrate onboard "A SaaS platform"         # scaffold empty project
lindy-orchestrate onboard --depth 2 -y --force      # deep scan, non-interactive
Flag Short Description
--file -f Project description from file (scaffold mode)
--depth Module scan depth (default: 1)
--non-interactive -y Skip prompts, use defaults
--force Overwrite existing files
--provider Override dispatch provider for this command

init

Quick scaffold: detect modules, generate orchestrator.yaml and STATUS.md files.

lindy-orchestrate init --modules backend,frontend --depth 2 --no-status
Flag Short Description
--modules -m Comma-separated module names (skip auto-detect)
--depth Scan depth (default: 1)
--no-status Skip STATUS.md creation
--force Overwrite existing files

status

lindy-orchestrate status                  # full overview
lindy-orchestrate status --json           # JSON output
lindy-orchestrate status -n 50            # last 50 log entries
lindy-orchestrate status --status-only    # health table only
lindy-orchestrate status --logs-only      # logs only
Flag Short Description
--json Machine-readable JSON
--last -n Recent log entries (default: 10)
--status-only Module status table only
--logs-only Recent logs only

logs / validate

logs is an alias for status --logs-only (accepts --json and -n). validate checks configuration, module paths, STATUS.md files, and CLI availability.

gc

Dry-run by default. Use --apply to execute cleanup.

lindy-orchestrate gc                                # dry run
lindy-orchestrate gc --apply --branch-age 7         # clean branches >7 days
Flag Description
--apply Execute cleanup (default: dry run)
--branch-age Max branch age in days (default: 14)
--session-age Max session age in days (default: 30)
--log-size Max log file size in MB (default: 10)
--status-stale STATUS.md stale threshold in days (default: 7)

scan

Scan for entropy. Use --module backend to scope, --grade-only for A-F grades only.

issues

List issues from configured tracker. Flags: --label, --status (default: open), -n limit (default: 20), --json.

run-issue

Fetch an issue, decompose as goal, execute. On completion, comments and optionally closes (tracker.sync_on_complete). Accepts --dry-run and --verbose.

mailbox

lindy-orchestrate mailbox                                              # summary
lindy-orchestrate mailbox frontend --json                              # module messages
lindy-orchestrate mailbox --send-to backend -m "Need API" -p high      # send message
Flag Short Description
--send-to Recipient module
--send-from Sender (default: cli)
--message -m Message content
--priority -p low, normal, high, urgent
--json JSON output

Configuration

orchestrator.yaml in project root. Only project and modules are required; all other sections have sensible defaults.

Section Key Fields
project name, branch_prefix (default: af)
modules[] name, path, status_md, claude_md, repo, ci_workflow, role
planner mode (cli/api), model, max_tokens, timeout_seconds, prompt_template
dispatcher provider (claude_cli/codex_cli), timeout_seconds, stall_escalation {warn_after_seconds, kill_after_seconds}, permission_mode, max_output_chars
qa_gates ci_check, structural {max_file_lines, enforce_module_boundary, sensitive_patterns}, layer_check {enabled, unknown_file_policy}, custom[] {name, command, cwd, timeout, modules}
safety dry_run, max_retries_per_task, max_parallel
mailbox enabled (default: true), dir, inject_on_dispatch
tracker enabled, provider (github), repo, labels[], sync_on_complete
logging dir, session_dir, log_file

See docs/REFERENCE.md for the complete annotated YAML schema with all defaults and module-scoped QA gate normalization.


Global Config

~/.lindy/config.yaml stores user-level defaults that apply across all projects. No LLM required — purely reads and writes YAML files.

Priority chain (highest → lowest):

CLI --provider flag  >  orchestrator.yaml dispatcher.provider  >  ~/.lindy/config.yaml  >  default (claude_cli)

config show

lindy-orchestrate config show

Displays both global (~/.lindy/config.yaml) and local (orchestrator.yaml) provider settings, plus the effective provider.

config set

# Set globally (all projects, persists in ~/.lindy/config.yaml)
lindy-orchestrate config set provider codex_cli
lindy-orchestrate config set provider claude_cli

# Set locally (this project only, writes to ./orchestrator.yaml)
lindy-orchestrate config set --local provider codex_cli
Flag Description
--local Write to ./orchestrator.yaml instead of ~/.lindy/config.yaml

Valid providers: claude_cli, codex_cli.

Tip: During onboard of an empty project, the tool picks up the global config automatically — no --provider flag needed if you've set it with config set.


Provider System

Pluggable dispatch via the DispatchProvider protocol (defined in providers/base.py). Two dispatch modes:

Mode Method Use Case
Streaming dispatch() Long tasks: real-time heartbeat, stall detection, event callbacks
Blocking dispatch_simple() Short tasks: plan generation, reports
Provider Binary Flag Description
claude_cli claude --provider claude_cli Claude Code CLI (default)
codex_cli codex --provider codex_cli OpenAI Codex CLI

Stall escalation: warn after silence threshold, kill after kill threshold. 10-minute minimum floor applies. Bash-tool-aware: long-running commands get 50% extra time. To add a custom provider, implement DispatchProvider in providers/ and register in providers/__init__.py.


QA Gates

Pluggable validation runs after each task dispatch, sequentially per task.

Gate Description
ci_check Poll GitHub Actions workflow via gh CLI
command_check Run shell commands (exit 0 = pass)
agent_check Dispatch separate QA agent for semantic validation
structural_check File size limits, module boundary enforcement, sensitive file detection
layer_check Intra-module layer ordering based on ARCHITECTURE.md

Custom command-based gates are defined under qa_gates.custom in config. The {module_path} placeholder resolves to the module's absolute path. On failure, the orchestrator builds structured remediation feedback and retries up to safety.max_retries_per_task times.


Hook / Event System

The HookRegistry provides a thread-safe, synchronous event system. Events: TASK_STARTED, TASK_COMPLETED, TASK_FAILED, TASK_RETRYING, TASK_SKIPPED, QA_PASSED, QA_FAILED, STALL_WARNING, STALL_KILLED, TASK_HEARTBEAT, CHECKPOINT_SAVED, MAILBOX_MESSAGE, SESSION_START, SESSION_END.

Register with hooks.on(EventType, handler) or hooks.on_any(handler). Each Event carries type, timestamp, data, task_id, module. The dashboard, progress reporting, and checkpoint system all subscribe. See docs/REFERENCE.md for the full API.


Live DAG Dashboard

When running in a terminal, run and resume display a live-updating ASCII DAG tree powered by Rich Live panels, subscribing to hook events:

+--------------------------- Executing ----------------------------+
| DAG: Add user authentication with JWT                            |
| +-- * 1 backend: Add JWT auth endpoint         <- tool: Edit    |
| +-- * 2 frontend: Add login page               <- starting...   |
| +-- o 3 backend: Add auth middleware (depends: 1)                |
|                                                                  |
|   V 1 completed  X 0 failed  * 1 running  o 1 pending    2:34   |
+------------------------------------------------------------------+

Icons: V completed, X failed, * running, o pending, - skipped. --verbose shows tool use annotations. Falls back to text progress on non-TTY (CI, piped output).


Inter-Agent Mailbox

JSONL-based, file-backed messaging for near-real-time inter-module communication. Each module has an inbox at .orchestrator/mailbox/{module}.jsonl. Messages are appended atomically with thread-safe locking. When mailbox.inject_on_dispatch is true (default), pending messages are injected into agent prompts before dispatch.

Messages carry: id (UUID), from_module, to_module, content, message_type (request/response/notification), priority (low/normal/high/urgent), status (pending/read/acknowledged), optional in_reply_to and task_id.


Entropy Scanner

Scans for architecture drift, contract violations, STATUS.md inconsistency, and code quality decay.

Check Description
Architecture drift ARCHITECTURE.md declarations vs actual filesystem
Contract compliance CONTRACTS.md completeness for multi-module projects
STATUS.md consistency Health values, freshness, stale in-progress tasks
Quality metrics Oversized files (>500 lines), missing test directories

Each module receives a grade (A-F) based on weighted severity (error > warning > info).


Garbage Collection

The gc command cleans up entropy from agent-generated artifacts. Dry-run by default.

Category Description
Stale branches Task branches ({prefix}/task-*) older than threshold
Old sessions Session JSON files archived past threshold
Log rotation Action logs exceeding size limit (rotated with timestamp)
STATUS.md drift Stale STATUS.md files not updated within threshold
Orphan plans Plan files >30 days old with no session reference

Issue Tracker Integration

Connect to GitHub Issues via gh CLI. Requires gh auth login.

tracker:
  enabled: true
  provider: github
  repo: "owner/repo"           # empty = current repo
  labels: [orchestrator]
  sync_on_complete: true

Workflow: lindy-orchestrate issues lists matching issues -> run-issue 42 fetches issue #42, decomposes as goal, executes -> on completion, comments with task summary and closes (if all tasks pass and sync_on_complete is true).


Structured QA Feedback

On QA failure, gate-specific parsers extract actionable remediation instead of passing raw output:

Parser Triggered By Extracts
pytest pytest, py.test Failed test paths, assertion details, fix guidance
ruff ruff, eslint, flake8 File:line violations, rule codes, auto-fix commands
tsc tsc, typescript File:line type errors, TS error codes
generic All other gates Truncated output with run-locally guidance

Retry prompts are progressively focused: retry 1 includes the full original prompt plus structured feedback; retry 2+ uses a simplified prompt targeting only failing files and specific errors. See docs/REFERENCE.md for the StructuredFeedback model.


Execution Summary Reports

After every run or resume, the orchestrator generates:

  1. Console summary — Rich panel with per-task status table, timing, retries, QA results, and output previews
  2. Markdown report — Saved to .orchestrator/reports/{session_id}_summary.md

Reports include: goal status, per-task metrics (module, status, duration, retries, QA), and aggregate counts (total, pass, fail, skip, duration, estimated cost).


Key Concepts

Harness Engineer — lindy-orchestrator's core philosophy. It never writes production code directly; it harnesses AI coding agents (Claude Code, Codex) by: (1) decomposing goals into precise task DAGs, (2) dispatching agents to isolated module directories, (3) validating their output through QA gates, and (4) retrying with structured remediation feedback on failure. Think of it as the conductor who keeps every instrument playing in time without picking up an instrument itself.

Modules — Independent directories (services, packages). Auto-detected by markers: pyproject.toml, package.json, Cargo.toml, go.mod, pom.xml, build.gradle, CMakeLists.txt, Makefile. Special names root and * refer to the project root.

STATUS.md — Human-readable, git-diffable state per module. Tracks active work, completed tasks, backlogs, cross-module requests, metrics, and blockers.

CONTRACTS.md — Cross-module interface definitions. Generated by onboard when coupling is moderate or higher.

Sessions — JSON state in .orchestrator/sessions/. Supports pause/resume, mid-execution checkpoints, and history.

Branch delivery — Each task gets branch {branch_prefix}/task-{id}. Agents create, commit, push. Delivery check verifies branch exists.


Architecture

src/lindy_orchestrator/
|-- __init__.py                  # Package init, version
|-- cli.py                       # Typer CLI entry point (run, plan, resume, version)
|-- cli_ext.py                   # Extension commands (gc, scan, validate, issues, run-issue, mailbox)
|-- cli_status.py                # Status and logs commands
|-- cli_onboard.py               # Unified onboard command (scaffold/init/re-onboard)
|-- cli_init.py                  # Quick init + legacy onboard commands
|-- cli_config.py                # Config management commands (config show/set)
|-- cli_helpers.py               # Shared CLI utilities
|-- cli_onboard_helpers.py       # Onboard-specific helpers
|-- cli_scaffold.py              # Scaffold mode helpers
|-- config.py                    # YAML config loading + Pydantic models
|-- models.py                    # Core data models (TaskPlan, TaskItem, QACheck, DispatchResult)
|-- planner.py                   # Goal -> TaskPlan decomposition via LLM
|-- scheduler.py                 # DAG-based parallel execution with retry logic
|-- scheduler_helpers.py         # Scheduler utility functions
|-- dispatcher.py                # Claude CLI subprocess management (streaming + blocking)
|-- codex_dispatcher.py          # Codex CLI subprocess management (streaming + blocking)
|-- prompts.py                   # LLM prompt templates (Jinja2)
|-- session.py                   # Session state persistence and resume
|-- logger.py                    # Append-only JSONL audit trail
|-- reporter.py                  # Rich console output, execution summaries
|-- hooks.py                     # Event hook system (HookRegistry, EventType)
|-- dashboard.py                 # Live DAG dashboard (Rich Live panel)
|-- dag.py                       # DAG visualization (ASCII tree rendering)
|-- mailbox.py                   # JSONL-based inter-agent mailbox
|-- gc.py                        # Garbage collection (branches, sessions, logs)
|-- providers/
|   |-- __init__.py              # Provider registry and factory
|   |-- base.py                  # DispatchProvider protocol
|   |-- claude_cli.py            # Claude Code CLI provider
|   |-- codex_cli.py             # OpenAI Codex CLI provider
|-- qa/
|   |-- __init__.py              # Gate registry and runner
|   |-- ci_check.py              # GitHub Actions CI polling
|   |-- command_check.py         # Shell command execution
|   |-- agent_check.py           # Agent-based semantic validation
|   |-- structural_check.py      # File size, boundaries, sensitive files
|   |-- layer_check.py           # ARCHITECTURE.md layer ordering
|   |-- feedback.py              # Structured QA feedback and remediation
|-- entropy/
|   |-- __init__.py
|   |-- scanner.py               # Entropy scanner (drift, contracts, quality)
|   |-- scanner_helpers.py       # Grading and report formatting
|   |-- scanner_types.py         # ScanReport, ScanFinding, ModuleGrade
|-- trackers/
|   |-- __init__.py              # Tracker factory
|   |-- base.py                  # TrackerIssue dataclass
|   |-- factory.py               # Provider factory
|   |-- github_issues.py         # GitHub Issues provider (via gh CLI)
|-- status/
|   |-- __init__.py
|   |-- parser.py                # STATUS.md -> structured data
|   |-- templates.py             # STATUS.md generation
|   |-- writer.py                # Surgical markdown table updates
|-- discovery/
|   |-- __init__.py
|   |-- analyzer.py              # Static project analysis (tech stack, dependencies)
|   |-- analyzer_helpers.py      # Analysis utility functions
|   |-- interview.py             # Interactive and non-interactive onboarding Q&A
|   |-- generator.py             # Artifact generation (CLAUDE.md, CONTRACTS.md, ...)
|   |-- templates/
|       |-- __init__.py
|       |-- root_claude_md.py    # Root CLAUDE.md template
|       |-- module_claude_md.py  # Per-module CLAUDE.md template
|       |-- architecture_md.py   # ARCHITECTURE.md template
|       |-- contracts_md.py      # CONTRACTS.md template
|       |-- agent_docs.py        # Agent protocol docs template

Development

pip install -e ".[dev]"
pytest tests/ -v
pytest tests/ --cov=src/lindy_orchestrator --cov-report=term-missing
ruff check src/ tests/ && ruff format src/ tests/

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

lindy_orchestrator-0.13.3.tar.gz (287.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

lindy_orchestrator-0.13.3-py3-none-any.whl (146.9 kB view details)

Uploaded Python 3

File details

Details for the file lindy_orchestrator-0.13.3.tar.gz.

File metadata

  • Download URL: lindy_orchestrator-0.13.3.tar.gz
  • Upload date:
  • Size: 287.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for lindy_orchestrator-0.13.3.tar.gz
Algorithm Hash digest
SHA256 6d1df5ec0cc136d00986823ac7787c5ecd0e0c4b8dc01324ccc805f1f7712db4
MD5 392ea19de2576758c462d27fa677bdb3
BLAKE2b-256 c81598623985ff0ade84e076f21fd43fc1515fe201b62b273c311024c175ae48

See more details on using hashes here.

File details

Details for the file lindy_orchestrator-0.13.3-py3-none-any.whl.

File metadata

File hashes

Hashes for lindy_orchestrator-0.13.3-py3-none-any.whl
Algorithm Hash digest
SHA256 02191cd8b5a485814f370fd24cc8d243728c18fadcb8e621ed6ad3948eb6da17
MD5 8a419991b7b7c6e9f8205d4b523f616a
BLAKE2b-256 454549ebe022ed1792ada15cc68b5437d3050b37270912e1926438d6056dc6ae

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page