ActionD
Local CI/CD for agents: runs jobs on LGH git events in isolated checkouts, with failure diagnosis, approval gates, auto-rollback and a web console.
What can you do with ActionD?
- 🔌 Dynamic plugin discovery — plugins are discovered automatically via
manifest.json, no code changes required - 🤖 MCP integration — a built-in MCP server lets AI assistants query and control CI/CD directly
- 📡 Event-driven — reacts to
git.push,git.tag, and other LGH events - 🖥️ Web console — live monitoring dashboard at
http://localhost:3000 - 🔄 Real-time streaming output — live logs over SSE (Server-Sent Events)
- ⚡ Hot reload — reload plugins without a restart
- 🔄 End-to-end workflow —
dev_cycle_rundoes it all in one call: commit → CI → results - ⏮️ Rollback — automatically roll back to the previous commit on failure
Install
The installation steps are in the documentation below. Documentation
Documentation
From the project's README on GitHub, refreshed weekly. Links open on GitHub.
Contents
- ActionD
- Features
- Terminology
- Installation
- Quick Start
- CLI Commands
- Build Notes
- Dynamic Plugin Discovery (V1.0.7+)
- Structured Result Protocol — ActionResult (v1.2+)
- Failure Interpreter (v1.2+)
- Built-in Plugins
- MCP Server Integration
- Configuration
- Architecture
- API Endpoints
- Layered Logging (v1.2+)
- File Locations
- Development
- License
- Related Projects
ActionD
Local AI Action Execution Engine for LGH (Local Git Hub)
ActionD is a lightweight local CI/CD engine designed for AI agents. It listens to Git events from LGH and automatically triggers plugins to run code checks, tests, builds, and more.
Features
- 🔌 Dynamic plugin discovery — plugins are discovered automatically via
manifest.json, no code changes required - 🤖 MCP integration — a built-in MCP server lets AI assistants query and control CI/CD directly
- 📡 Event-driven — reacts to
git.push,git.tag, and other LGH events - 🖥️ Web console — live monitoring dashboard at
http://localhost:3000 - 🔄 Real-time streaming output — live logs over SSE (Server-Sent Events)
- ⚡ Hot reload — reload plugins without a restart
- 🔄 End-to-end workflow —
dev_cycle_rundoes it all in one call: commit → CI → results - ⏮️ Rollback — automatically roll back to the previous commit on failure
Terminology
- Job — one CI/CD execution record produced when a plugin reacts to a Git event. Some tool names (
actiond_action_get,actiond_actions_list) carry the legacy word action; it refers to the same object as theactiond_job_*tools. - Plugin — the executable unit registered via
manifest.jsonthat runs on trigger events (git.push,git.tag); one plugin run yields one job. - Profile — the CI scope preset (
fast/full/release) controlling which plugins run per push.
Installation
macOS / Linux (Homebrew)
brew install JoeGlenn1213/tap/actiond
Install LGH the same way (brew install JoeGlenn1213/tap/lgh) — ActionD listens to its git events.
The builtin plugin bundle (30+ check plugins) is embedded in the binary.
actiond setupmaterializes it into~/.localgithub/plugins, so a Homebrew or release-download install runs the same checks as a source checkout — no extra asset download needed. The web console is optional: without it the API still runs (see actiond-web or pass--web-dir).
Prerequisites
- Go 1.25+ (only when building from source)
- Python 3.8+ (used by plugins)
- LGH running locally
Build from source
git clone https://github.com/JoeGlenn1213/ActionD.git
cd ActionD
make build
Note: ActionD uses SQLite for storage (the pure-Go modernc.org/sqlite build) — no CGO is needed and
make buildcross-compiles freely.
Quick Start
1. One-command setup (recommended)
If this is your first run, use setup to install the builtin plugin bundle (embedded in the binary), check dependencies, create the directory layout, and verify the environment:
actiond setup
Re-running setup is safe: already-installed plugins and your local edits are never overwritten (use --force to reset them to the bundled version, --skip-plugins to skip installation entirely).
To also start the daemon in the background right after setup:
actiond setup --start
2. Start the service and check it
# 1. Make sure LGH is running
lgh serve -d
# 2. Start ActionD (daemon mode; reads LGH mappings automatically)
actiond start -d
# 3. Check status
actiond doctor
3. Open the web console
open http://localhost:3000
Default directories and auto-detection
- Plugin directories are probed in order:
<binary dir>/plugins→<working dir>/plugins→~/.localgithub/plugins - Web static assets are auto-detected in common locations; the recommended target is publishing
ActionD-Web'sout/to:~/.localgithub/actiond-web/out - Without an explicit
--repo-root, ActionD resolves repositories through LGH mappings first, then falls back to current-directory semantics.
CLI Commands
| Command | Description |
|---|---|
actiond setup | One-command environment initialization (v1.2+) |
actiond start | Start in the foreground |
actiond start -d | Start as a background daemon |
actiond stop | Stop the daemon |
actiond restart | Restart the service (v1.2+) |
actiond status | Show run status + directory info (v1.2+) |
actiond plugins restore-go | Re-enable the Go verification plugins |
actiond log | View server logs |
actiond doctor | Diagnose system dependencies (tiered checks) |
actiond version | Print version information |
actiond mcp | Start the MCP server |
One-command setup (v1.2+)
Recommended on first install:
actiond setup
This automatically:
- Creates the directory layout (
~/.localgithub/*) - Checks dependencies (Git, Python, Go, Node)
- Detects web assets and plugin directories
- Verifies the LGH connection
Doctor
actiond doctor
Runs 8 categories of tiered checks:
- 📦 System environment (home/base directories)
- 🔧 Dependencies (Git, Python, Go, Node, golangci-lint)
- 🔌 Service status (LGH, ActionD)
- 🌐 Ports (3000, 8080)
- 📁 Directories (repos, actions, plugins, web, artifacts)
- 💾 Storage (DB writability, config files)
- 🔌 Plugins (directories, core plugin status)
- 🌐 Web assets
Results come in three levels:
- FATAL — the system cannot work
- WARN — some functionality is affected
- INFO — informational only
If doctor reports that the Go plugins are disabled, restore them directly:
actiond plugins restore-go
Status (v1.2+)
actiond status
Shows:
- Service run status and PID
- All directory paths and their status
- LGH connection status
- Web assets and plugin directories
Build Notes
make build uses CGO_ENABLED=0 (SQLite is the pure-Go modernc.org/sqlite build), so binaries cross-compile freely.
make release defaults to the current host platform; override RELEASE_PLATFORMS="linux/amd64 linux/arm64 darwin/arm64" to build for other targets.
Start options
actiond start --help
Flags:
-d, --daemon run in the background
--repo-root string repository root directory (optional; LGH mappings take priority when omitted)
--web-dir string web console static file directory (optional; auto-detected by default)
Dynamic Plugin Discovery (V1.0.7+)
ActionD supports adding new plugins with zero code. Just create a manifest.json in a plugin directory:
Plugin directories
ActionD scans plugins in this order:
- System plugins:
./plugins/(next to the binary) - Development plugins:
./plugins/(current working directory) - User plugins:
~/.localgithub/plugins/
manifest.json format
{
"apiVersion": "actiond.dev/v1",
"name": "my-plugin",
"version": "1.0.0",
"description": "My custom plugin",
"command": "python3",
"args": ["run.py"],
"triggers": ["git.push"],
"languages": ["python"],
"timeout": "5m",
"artifacts": ["report.json"]
}
Field reference
| Field | Required | Description |
|---|---|---|
name | ✅ | Unique plugin identifier |
command | ✅ | Command to execute |
args | - | Command arguments |
triggers | ✅ | Trigger events: git.push, git.tag |
languages | - | Supported languages: go, java, python, web, node, typescript, javascript, nextjs, * |
timeout | - | Timeout: 5m, 30s |
refFilter | - | Ref matching: refs/tags/* |
Creating a custom plugin
plugins/
└── my-plugin/
├── manifest.json # plugin metadata
└── run.py # execution script
Example run.py:
#!/usr/bin/env python3
import json
import sys
# Read stdin input
input_data = json.load(sys.stdin)
event = input_data["event"]
repo_path = input_data["repo_path"]
artifact_dir = input_data.get("artifact_dir")
# Do the work...
print(f"Processing {event['type']} for {repo_path}", file=sys.stderr)
# Output the result (stdout)
result = {
"status": "success", # or "error"
"artifacts": ["report.json"]
}
print(json.dumps(result))
Structured Result Protocol — ActionResult (v1.2+)
Plugins can return a standardized ActionResult structure that enables deep AI understanding and downstream decision gating (for example, the Policy Gate plugin reads signals produced by other plugins):
{
"action_id": "act_8a9b2c1d",
"plugin_id": "go-test-fast",
"capability": "test",
"language": "go",
"status": "success",
"decision": "pass",
"timing": {
"started_at": "2025-03-16T10:30:00Z",
"finished_at": "2025-03-16T10:30:02Z",
"duration_ms": 2300
},
"summary": {
"message": "All 25 tests passed",
"counts": {
"tests_run": 25
}
},
"signals": {
"tests_passed": true
},
"hints": [],
"artifacts": [{"name": "test-report.xml", "path": "test-report.xml"}]
}
Result fields
| Field | Type | Description |
|---|---|---|
action_id | string | Unique execution ID |
status | string | success, failed, skipped |
decision | string | pass, deny (used for gating and AI decisions) |
summary.message | string | One-line summary |
signals | object | Core extracted features, e.g. tests_passed, lint_error_count |
hints | []string | AI/user-friendly fix suggestions |
artifacts | []object | Artifact file list |
Returning structured results from a plugin
A plugin can print JSON to stdout — ActionD parses and stores it automatically:
result = {
"status": "failure",
"summary": "Test suite failed",
"hints": ["Run tests locally to reproduce"]
}
print(json.dumps(result))
Alternatively, write to $ARTIFACT_DIR/result.json.
Failure Interpreter (v1.2+)
ActionD has built-in failure-pattern recognition that automatically analyzes common errors and suggests fixes:
Recognized error patterns
| Category | Pattern | Description |
|---|---|---|
| Dependencies | npm_install_failed | npm install failure |
npm_lockfile_mismatch | package-lock.json out of sync | |
npm_module_not_found | module not found | |
go_mod_tidy | go.mod needs tidying | |
python_module_not_found | missing Python module | |
maven_build_failed | Maven build failure | |
| Build | go_build_failed | Go compile error |
gradle_build_failed | Gradle build failure | |
| Tests | jest_test_failed | Jest test failure |
go_test_failed | Go test failure | |
pytest_failed | pytest failure | |
| Generic | permission_denied | permission error |
timeout | operation timed out | |
out_of_memory | out of memory | |
command_not_found | command not found |
Analysis API
Failure analysis is implemented on the Go side in internal/interpreter (failure.go) and produces the category/type classification shown above. There is no actiond Python package — use one of these real interfaces instead:
- AI side (recommended): the MCP tool
actiond_diagnose(job_id=...), which returns root cause and fix suggestions. - HTTP side: the REST API (see the "API endpoints" section below).
Hot-reloading plugins
# Option 1: API
curl -X POST http://localhost:3000/api/plugins/reload
# Option 2: MCP
# An AI assistant can call the actiond_plugins_reload tool
Built-in Plugins
| Plugin | Trigger | Language | Description |
|---|---|---|---|
echo | all | * | Debug plugin, echoes event info |
go-lint | git.push | Go | golangci-lint code checks |
go-test-fast | git.push | Go | Fast unit tests |
go-build | git.tag | Go | Cross-platform builds |
java-quicktest | git.push | Java | Smart test selection |
java-checkstyle | git.push | Java | Checkstyle code style |
python-pytest | git.push | Python | pytest + coverage |
web-lint | git.push | Web/Node | Frontend lint checks |
web-test | git.push | Web/Node | Frontend test script |
web-build | git.push | Web/Node | Frontend build validation |
MCP Server Integration
ActionD ships with an MCP (Model Context Protocol) server so AI assistants (such as Claude) can query and control CI/CD directly.
Starting the MCP server
actiond mcp
To let the AI start/stop/restart ActionD itself over MCP, set this before launching:
ACTIOND_MCP_ALLOW_LIFECYCLE=1 actiond mcp
Available tools
| Tool | Description |
|---|---|
actiond_status | Get server status and statistics |
actiond_plugins_list | List all plugins and their configuration |
actiond_actions_list | List recent CI/CD jobs |
actiond_action_get | Get details of a single job |
actiond_plugins_reload | Hot-reload plugins |
actiond_plugins_recommend | Recommend plugins by project profile (language/framework detection + confidence) |
actiond_plugin_enable | Enable a plugin for the current project |
actiond_plugin_disable | Disable a plugin for the current project |
actiond_log | View server logs, filterable by job_id and plugin_name |
actiond_profile_get | Get the current execution profile (fast/full/release) |
actiond_profile_set | Set the execution profile, controlling which plugins each push triggers |
actiond_server_start | Start the ActionD service (requires the lifecycle switch) |
actiond_server_stop | Stop the ActionD service (protects running jobs by default) |
actiond_server_restart | Restart the ActionD service (protects running jobs by default) |
actiond_job_wait | Block until a job finishes and return its result; supports a timeout parameter |
actiond_job_cancel | Cancel a job (validates state; terminal jobs are rejected) |
actiond_job_retry | Retry a failed job |
actiond_diagnose | AI failure diagnosis: root-cause analysis + classification + fix suggestions (the first tool to reach for when CI fails) |
actiond_cleanup | Delete old completed/failed jobs and their artifact directories (retention window or all terminal jobs) |
actiond_run_report | Goal run report: what changed / why / verified or not (pass-fail-unknown per job) / how trustworthy / handoff status / rollback evidence — one honest JSON, unknowns explicit |
actiond_handoff_pack | Handoff package: everything the next human or agent needs to continue (envelope + payload + self-contained Markdown) |
dev_cycle_run | End-to-end dev loop: commit → CI → results (V1.0.8+; tri-state verification since v1.3.0) |
To approve a blocked job, use the CLI
actiond approve <job_id>or RESTPOST /api/actions/{id}/approve(there is no MCP tool for this).
The dev_cycle_run end-to-end workflow (V1.0.8+)
dev_cycle_run is an aggregate tool that completes the full development loop in a single MCP call:
edit code → lgh up → wait for CI → return structured results
Parameters:
| Parameter | Required | Description |
|---|---|---|
message | ✅ | Git commit message |
path | - | Repository path (defaults to the current directory) |
timeout | - | Wait timeout in seconds (default 300 = 5 minutes) |
profile | - | fast/full/release for this run (restored afterwards) |
auto_rollback | - | On a confirmed failed verdict, reset to the recorded pre-push commit (default false). Never fires on unverified (unknown) runs, and is skipped if HEAD moved or the working tree changed while CI ran |
Returns:
{
"success": true,
"verification": "pass",
"commit": "abc123",
"jobs": [
{"id": "job-1", "plugin": "go-test-fast", "status": "done", "duration": "2.3s"}
],
"summary": "✅ 全部通过 (2 个插件)"
}
verification is tri-state and success is true only on pass — the same vocabulary and aggregation rule as actiond_run_report:
pass— at least one job ran and all of them passedfail— at least one job was observed failingunknown— zero jobs, a CI query error, or a timeout; never a pass
Jobs are associated to this run by LGH event id, or (fallback) by exact repo name plus commit sha — a green job from an older commit or a similarly named repo is never adopted as verification for the current change.
Typical usage:
User: AI, please fix the code and test it
AI: [edits the code...]
[calls dev_cycle_run(message="fix: address the failing case")]
Result: ✅ All passed (2 plugins)
- go-lint: ✅ 0.5s
- go-test-fast: ✅ 2.3s
Available resources
actiond://status— server statusactiond://plugins— plugin listactiond://actions— execution records
Connecting your AI client
ActionD speaks standard MCP over stdio, so any MCP-capable client works (Claude Desktop/Code, Cursor, ZCode, Windsurf, ...). For clients that take a stdio command, the server is simply:
actiond mcp
Example for Claude Code — add to ~/.claude/claude_desktop_config.json:
{
"mcpServers": {
"actiond": {
"command": "/path/to/actiond",
"args": ["mcp"],
"env": {
"ACTIOND_MCP_ALLOW_LIFECYCLE": "1"
}
}
}
}
AI usage example
User: Check the recent CI jobs
AI: [calls actiond_actions_list]
There are 3 recent jobs:
- test-python (python-pytest): ✅ success (1.3s)
- ActionD (go-lint): ⛔ disabled
- demo-app (java-quicktest): ✅ success (45s)
Configuration
Runtime config file: ~/.localgithub/actions/config.json
Disabling a plugin
{
"plugins": {
"java-quicktest": {
"enabled": false
}
}
}
The core Go verification chain can also be restored directly via CLI:
actiond plugins restore-go
Overriding triggers
{
"plugins": {
"go-lint": {
"triggers": ["git.tag"]
}
}
}
Adding a custom plugin (no manifest.json needed)
{
"plugins": {
"my-custom-plugin": {
"enabled": true,
"type": "exec",
"command": "/usr/local/bin/my-script",
"args": ["--verbose"],
"triggers": ["git.push"]
}
}
}
Architecture
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ LGH │────▶│ ActionD │────▶│ Plugins │
│ (Events) │ │ (Engine) │ │ (Actions) │
└─────────────┘ └─────────────┘ └─────────────┘
│
┌────────────────┼────────────────┐
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Web Console │ │ MCP Server │ │ API │
│ (Dashboard) │ │(AI-integration)│ │ (RESTful) │
└─────────────┘ └─────────────┘ └─────────────┘
API Endpoints
| Endpoint | Method | Description |
|---|---|---|
/api/plugins | GET | List all plugins |
/api/plugins | POST | Create a custom plugin |
/api/plugins/reload | POST | Hot-reload plugins |
/api/plugins/{name}/toggle | POST | Enable/disable a plugin |
/api/actions | GET | List execution records |
/api/actions/{id} | GET | Get job details |
/api/actions/{id}/stream | GET | SSE live log stream |
/api/actions/{id}/artifacts/{file} | GET | Download an artifact |
/api/actions/{id}/cancel | POST | Cancel a running job (V1.0.8+) |
/api/actions/{id}/retry | POST | Retry a failed job (V1.0.8+) |
/api/actions/{id}/approve | POST | Manually approve a blocked job |
Layered Logging (v1.2+)
ActionD uses a layered logging architecture that targets different audiences with different formats:
| Layer | Purpose | Example |
|---|---|---|
event | Event log | 📨 Received: git.push [my-repo] |
dispatch | Dispatch log | → Dispatching to: go-lint |
plugin | Plugin execution | plugin stdout/stderr output |
user | User summary | ✅ All 3 plugins passed (5.2s) |
ai | AI structured summary | JSON, consumed by AI |
AI summary format
{
"timestamp": "2025-03-16T10:30:00Z",
"layer": "ai",
"level": "info",
"job_id": "abc123",
"repo": "my-project",
"plugin": "go-test-fast",
"message": "Tests passed",
"data": {
"status": "success",
"summary": "All 25 tests passed in 2.3s",
"hints": [],
"artifacts": ["test-report.xml"]
}
}
File Locations
| Path | Description |
|---|---|
~/.localgithub/actions/ | Data directory |
~/.localgithub/actions/actiond.db | SQLite job database |
~/.localgithub/actions/actiond.pid | Daemon PID file |
~/.localgithub/actions/config.json | User configuration |
~/.localgithub/plugins/ | User-defined plugin directory |
~/.localgithub/actions/actiond.log | Daemon log |
Development
# Build
go build ./...
# Run tests
go test ./...
# Install to GOPATH
go install ./cmd/actiond
License
MIT License — see LICENSE
Related Projects
- LGH — Local Git Hub
- actiond-web — Web console UI
Frequently asked questions
What is ActionD?
Local CI/CD for agents: runs jobs on LGH git events in isolated checkouts, with failure diagnosis, approval gates, auto-rollback and a web console.
How do I install ActionD?
Follow the installation steps in its documentation, shown on this page and in its repository.
Is ActionD open source?
Yes. Its code is on GitHub under the MIT license.
Who maintains ActionD?
It is published by JoeGlenn1213. AI.tn lists it but does not maintain or endorse it.
From the community awesome-mcp-servers lists and the project's GitHub repository. Listing is not an endorsement: review a server's code and permissions before giving it access to your data.