Ludwig is an AI-powered task orchestrator that automates project work through integrated AI clients (Gemini, Ollama, or GitHub Copilot CLI). It manages task execution, git workflows, and human review cycles through a command-line interface. Works online with Gemini/Copilot or completely offline with Ollama.
Copy and paste this command into your terminal:
curl -fsSL https://raw.githubusercontent.com/AlexanderHeffernan/Ludwig-AI/main/install.sh | bashRun this command in PowerShell (as Administrator for system-wide install):
powershell -Command "& {[ScriptBlock]::Create((New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/AlexanderHeffernan/Ludwig-AI/main/install.ps1')).Invoke()}"That's it! Ludwig will be installed to /usr/local/bin/ (macOS/Linux) or C:\Program Files\Ludwig (Windows) and ready to use globally.
git clone https://github.com/AlexanderHeffernan/Ludwig-AI.git
cd Ludwig-AI
go build -o ludwig ./cmd/main.go
sudo mv ludwig /usr/local/bin/Ludwig includes automatic updates. To check for and install a new version:
ludwig --updateThen restart Ludwig to apply the update.
ludwig/
├── cmd/ # Command-line entry point
│ └── main.go # Application initialization
├── internal/
│ ├── cli/ # CLI interface and display
│ │ ├── cli.go # Main CLI loop
│ │ ├── commandPallete.go # Command definitions
│ │ └── kanban.go # Kanban board display
│ ├── config/ # Configuration management
│ │ └── config.json # Config location: .ludwig/config.json
│ ├── mcp/ # Model context protocol (future enhancement)
│ ├── orchestrator/ # Core orchestration logic
│ │ ├── orchestrator.go # Main orchestrator loop
│ │ ├── prompts.go # System prompts for AI agents
│ │ ├── git.go # Git operations
│ │ └── clients/
│ │ ├── aiclient.go # AIClient interface
│ │ ├── gemini.go # Gemini AI client
│ │ ├── ollama.go # Ollama AI client
│ │ └── copilot.go # GitHub Copilot CLI client
│ ├── storage/ # Data persistence
│ │ ├── taskStorage.go # Task file storage
│ │ ├── responseStorage.go # AI response streaming
│ │ └── streamingWriter.go # Stream writing utilities
│ ├── types/ # Core data types
│ │ └── task.go # Task definition
│ └── utils/ # Utility functions
│ ├── cliUtils.go # CLI input/output utilities
│ └── mapUtils.go # Data transformation utilities
├── test/ # Test suite (136+ tests)
│ ├── cli/
│ ├── config/
│ ├── orchestrator/
│ ├── storage/
│ ├── types/
│ └── utils/
├── go.mod # Go module definition
├── go.sum # Dependency checksums
└── readme.md # This file
- Go 1.25.5 or later
- Git (for version control and branch operations)
# Build the Ludwig binary
go build -o ludwig ./cmd/main.go
# Or use the standard Go build
go build ./cmd/main.goLudwig has comprehensive test coverage with 136+ tests across all modules.
# Run all tests
go test ./...
# Run tests with verbose output
go test ./... -v
# Run specific test package
go test ./test/storage -v
go test ./test/orchestrator -v
go test ./test/types -v
# Run a specific test
go test ./test/types -run TestStatusString -v
# Run tests with coverage
go test ./... -cover# Start the CLI application
./ludwig
# Or directly with go run
go run ./cmd/main.go-
Create a feature branch
git checkout -b feature/your-feature-name
-
Check the test suite status
go test ./...
-
Make incremental changes with focused commits
git add <modified files> git commit -m "Clear, descriptive commit message"
-
Run tests frequently to catch issues early
go test ./...
-
Run full test suite
go test ./... -
Ensure all tests pass - if tests fail:
- First: Understand the root cause
- Investigate: Does the source code need fixing, or do the tests need updating?
- Fix source code first if the implementation is wrong
- Only update tests if the behavior change is intentional and correct
-
Add tests for new features (if test files already exist in the codebase)
- Add tests alongside your implementation
- Use the existing test patterns as reference
- Ensure new tests pass before committing
-
Build before pushing
go build ./cmd/main.go
- Pending: Waiting to be processed by the orchestrator
- In Progress: Currently being processed by an AI agent
- Needs Review: Waiting for human feedback on a design decision
- Completed: Task finished successfully
type Task struct {
ID string // Unique identifier
Name string // Task description
Status Status // Current status
BranchName string // Associated git branch
WorktreePath string // Path to git worktree directory
WorkInProgress string // Intermediate work progress
Review *ReviewRequest // Design decision request
ReviewResponse *ReviewResponse // Human response to review
ResponseFile string // Path to AI response file
}| Command | Usage | Description |
|---|---|---|
add |
add <task description> |
Add a new task (multiple words, no quotes needed) |
start |
start |
Start the AI orchestrator to process tasks |
stop |
stop |
Stop the orchestrator |
clear |
clear |
Clear the screen |
help |
help |
Show available commands |
exit |
exit |
Exit the application |
- Initialization: Loads tasks from storage and creates task branches
- Polling: Checks for pending tasks and processes them in order
- AI Processing: Sends tasks to AI client with system prompt and task description
- Review Detection: Parses responses for
---NEEDS_REVIEW---markers - Review Handling: If review needed, waits for human decision
- Completion: Marks tasks complete, auto-commits any uncommitted changes, and removes worktree
Pending Task
↓
Create Git Worktree
↓
Send to AI (with SystemPrompt + Task)
↓
Does response contain ---NEEDS_REVIEW---?
├─ Yes: Needs Review
│ ↓
│ Human provides decision
│ ↓
│ Resume with user feedback in Worktree
│ ↓
│ Completed → Remove Worktree
└─ No: Completed → Remove Worktree
- Each task gets its own git worktree with an isolated branch:
ludwig/<task-name> - Worktrees are stored in
.worktrees/<task-id>/directory - AI agents work in their own worktree, allowing parallel task execution
- User can continue working in the main branch while AI works on other tasks
- After task completion:
- Any uncommitted changes are automatically staged and committed to preserve work
- Worktree is removed, leaving the task branch for user review
- User can then review the branch and decide to merge, rebase, or discard
- This design allows multiple tasks to be processed simultaneously without blocking the user's workflow
When adding new functionality:
- Check if tests already exist in the codebase (they do - 136+ tests)
- Add tests alongside your implementation
- Use existing test patterns from the
test/directory - Follow Go testing conventions (function names start with
Test) - Include both happy path and error cases
Tests mirror the package structure:
internal/storage/taskStorage.go → test/storage/taskStorage_test.go
internal/types/task.go → test/types/task_test.go
internal/orchestrator/prompts.go → test/orchestrator/prompts_test.go
Table-driven tests (for multiple scenarios):
tests := []struct {
name string
input string
expected string
}{
{"case 1", "input1", "expected1"},
{"case 2", "input2", "expected2"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// test code
})
}Cleanup/Setup:
func TestSomething(t *testing.T) {
defer cleanupTestStorage(t)
// test code
}- Total Tests: 136+
- Modules Covered:
storage/: 45 testsorchestrator/: 38 teststypes/: 28 testsutils/: 15 testscli/: 14 testsconfig/: 3 tests
For detailed coverage information, see TEST_COVERAGE_IMPROVEMENTS.md.
- Edit
internal/cli/commandPallete.go - Add new command struct to
PalleteCommands() - Add tests in
test/cli/
- Extend
internal/storage/taskStorage.go - Add tests in
test/storage/ - Run tests:
go test ./test/storage -v
- Update
internal/types/task.go - Add/update tests in
test/types/ - Update related storage and orchestrator logic
- Edit
internal/orchestrator/prompts.go - Update tests in
test/orchestrator/ - Test with actual tasks to verify AI understanding
Ludwig supports multiple AI providers for offline capability and flexibility:
Requires Google Gemini API access via the gemini CLI tool.
# Install gemini CLI (requires authentication with Google account)
# See: https://github.com/google/generative-ai-cli
# Gemini is the default provider, no configuration neededUse your GitHub Copilot subscription with free education credits.
-
Install GitHub Copilot CLI:
# Via Homebrew (macOS/Linux) brew install --cask github-copilot-cli # Or download from: https://github.com/github/gh-copilot
-
Authenticate with GitHub:
copilot auth login
-
Configure Ludwig to use Copilot:
# Edit or create .ludwig/config.json (in your project root) { "aiProvider": "copilot", "copilotModel": "gpt-5" }
Supported models:
gpt-5,gpt-5-mini,claude-sonnet-4.5,claude-haiku-4.5,claude-opus-4.5, etc.Note: Ludwig uses
copilot --model <model> -p <prompt> --allow-all-toolsfor non-interactive automation.
Run completely offline using open-source models via Ollama.
-
Install Ollama: https://ollama.ai/
-
Start Ollama service:
ollama serve
-
Download a model (in another terminal):
# Recommended models (in order of capability/speed): ollama pull mistral # Fast, general purpose (~4GB) ollama pull neural-chat # Good quality (~4GB) ollama pull dolphin-mixtral # High quality (~26GB)
-
Configure Ludwig to use Ollama:
# Create/edit .ludwig/config.json (in your project root) { "aiProvider": "ollama", "ollamaBaseURL": "http://localhost:11434", "ollamaModel": "mistral" }
| Option | Description | Default |
|---|---|---|
aiProvider |
"gemini", "ollama", or "copilot" |
"gemini" |
ollamaBaseURL |
Base URL of Ollama server | http://localhost:11434 |
ollamaModel |
Model name to use with Ollama | mistral |
copilotModel |
Model name to use with Copilot (gpt-5, claude-sonnet-4.5, etc.) | gpt-5 |
delayMs |
Minimum delay between requests (optional) | - |
Create .ludwig/config.json in your project root:
{
"aiProvider": "ollama",
"ollamaBaseURL": "http://localhost:11434",
"ollamaModel": "mistral",
"delayMs": 1000
}- Run tests with verbose output:
go test ./... -v - Check if failure is in source code or test expectations
- For storage tests, ensure
~/.ai-orchestrator/directory is writable - Clean up:
rm -rf ~/.ai-orchestrator/tasks.json
- Check Go version:
go version(need 1.25.5+) - Get dependencies:
go mod download - Clean build:
go clean && go build ./cmd/main.go
- Check if Gemini API key is set in environment
- Verify
geminiCLI tool is installed and in PATH:which gemini - Verify git repository is initialized:
git status - Check task storage is accessible:
ls ~/.ai-orchestrator/
- Verify Ollama is running:
curl http://localhost:11434/api/tags - Check that a model is installed:
ollama list - Verify config file exists:
.ludwig/config.json - Verify config has
"aiProvider": "ollama" - Check config points to correct Ollama URL:
ollamaBaseURL - Verify git repository is initialized:
git status
golang.org/x/term v0.38.0 # Terminal control
github.com/google/uuid v1.6.0 # UUID generation
golang.org/x/sys v0.39.0 # System calls
When contributing:
- Follow the existing code structure and naming conventions
- Write tests for new functionality (tests exist in codebase)
- Run full test suite before committing
- Use clear, descriptive commit messages
- Create git branches for features
- Ensure all tests pass
MIT (adjust if needed)
- Support additional AI clients (Gemini + Ollama)
- Support additional AI clients (Claude, LLaMA, etc.)
- Model Context Protocol (MCP) integration
- Advanced task scheduling and prioritization
- Web UI for task management
- Webhook integration for automated task triggers
- Task templates and presets
- Performance metrics and analytics
- Local embedding support for better context