Moadim is a Rust daemon that treats agent scheduling as a cron problem. You install it on a machine, point it at a Git repository, and define routines (prompt, schedule, agent) in YAML. The daemon polls the repo, spawns agents in isolated tmux sessions, and kills hung runs. No cloud queue, no vendor API, no database. Just a local scheduler that reads configuration from Git and fires agents on a timer.
The project claims 1,000+ users in production and positions itself as "done" software. It supports Claude, Codex, Hermes, and Pi out of the box, with a pluggable agent interface. The architecture exposes three control surfaces: a REST API, an MCP tool server, and a web UI. All three share the same in-process scheduler, which means no hidden state synchronization and no queue drift.
Why Git as the Control Plane
Most agent schedulers store configuration in a database or a proprietary UI. Moadim uses Git as the source of truth. You define a routine in a YAML file, commit it, and push. The daemon pulls changes on a schedule (itself a routine) and reconciles the local state.
This design choice has consequences:
- Audit trail: Every schedule change is a commit with an author and timestamp.
- Rollback: Revert a commit to undo a bad routine.
- Multi-environment: Different branches for dev, staging, prod.
- Merge conflicts: If two operators add routines with the same name, Git surfaces the conflict before the daemon sees it.
The daemon does not write back to the repository. It reads configuration, executes routines, and logs results locally. This keeps the Git flow unidirectional and avoids the complexity of bidirectional sync.
Orchestration Flow
The daemon runs a single scheduler loop in Rust. On each tick:
- Poll Git: Fetch the latest configuration from the remote repository.
- Reconcile: Compare the new configuration with the in-memory state.
- Spawn: For each routine whose schedule matches the current time, fork a new tmux session.
- Execute: Run the agent (Claude, Codex, etc.) with the configured prompt and environment.
- Watchdog: Kill the session if it exceeds the timeout.
- Reap: Clean up the tmux session and log the result.
Each routine runs in isolation. The daemon does not share state between routines, and each agent invocation starts with a clean workbench. This prevents cross-contamination but also means routines cannot coordinate directly. If you need coordination, you model it explicitly (e.g., one routine writes a file, another reads it).
State Management and Persistence
Moadim does not persist execution history in a database. Logs go to the filesystem, and the daemon stores no memory of past runs beyond what the OS provides. This is a deliberate trade-off:
- Simplicity: No schema migrations, no backup strategy for a database.
- Observability gap: You cannot query "show me all failed runs in the last week" without parsing logs.
- Restart behavior: If the daemon crashes, it resumes from the current configuration. It does not replay missed ticks.
For teams that need durable execution history, you can layer a separate observability system on top (e.g., ship logs to Loki or Elasticsearch). The daemon itself stays minimal.
Multi-Runner Deployment
Moadim supports running the same daemon on multiple machines, each pulling from the same Git repository. This is not a distributed scheduler. Each daemon runs independently, and there is no leader election or coordination protocol.
If you deploy the same routine on two machines, both will fire at the scheduled time. This is useful for:
- Geographic distribution: Run the same routine on machines in different regions.
- Redundancy: If one machine goes down, the other keeps firing.
- Workload isolation: Run expensive routines on a dedicated box.
It is not useful for:
- Exactly-once execution: Both machines will run the routine. If you need deduplication, implement it in the agent or use a distributed lock.
- Load balancing: The daemon does not distribute work across runners.
Security Boundaries
The daemon runs on your machine with your user permissions. It does not sandbox agent execution beyond the tmux session. If an agent writes to the filesystem, it writes as your user. If it makes network requests, they originate from your machine.
Credential management is left to the operator. The recommended pattern:
- Store API keys in environment variables or a secrets manager.
- Reference them in the routine configuration.
- Use OS-level permissions to restrict access to the secrets file.
The Git repository should not contain secrets. If you commit an API key, it lives in the history forever. Use .gitignore for sensitive files and inject secrets at runtime.
Tool Integration: MCP, REST, and UI
Moadim exposes three interfaces:
| Interface | Use Case | Trade-Off |
|---|---|---|
| MCP | Agent-to-agent communication | Requires MCP-compatible client |
| REST | External automation, webhooks | No built-in auth, use reverse proxy |
| Web UI | Human operators | Read-only, no write operations |
The MCP server runs on /mcp and exposes each routine as a tool. An agent connected to Moadim can list routines, trigger them manually, or query their status. This is useful for meta-agents that orchestrate other agents.
The REST API provides the same operations over HTTP. Every routine becomes an endpoint with an OpenAPI schema. You can generate client libraries or call it from curl. The daemon does not enforce authentication. If you expose it to the network, put it behind a reverse proxy with auth.
The web UI is a static site served by the daemon. It shows the list of routines, their schedules, and recent logs. You cannot edit routines from the UI. All changes go through Git.
Failure Modes
The daemon is a single process with no high-availability story. If it crashes, routines stop firing. If the machine reboots, you need a systemd or launchd service to restart it.
Common failure modes:
- Git pull fails: The daemon logs the error and continues with the last known configuration. It does not retry indefinitely.
- Agent timeout: The watchdog kills the tmux session. The routine is marked as failed, and the next tick proceeds.
- Disk full: Logs stop writing. The daemon does not check disk space before spawning agents.
- Merge conflict: The daemon cannot reconcile the configuration. It logs the conflict and stops updating routines until you resolve it manually.
For production use, monitor the daemon process, disk space, and Git pull errors. Set up alerts for failed routines.
Code Example: Defining a Routine
# .moadim/routines/daily-summary.yaml
name: daily-summary
schedule: "0 9 * * *" # 9 AM daily
agent: claude
prompt: |
Review the logs in ~/projects/myapp/logs and summarize
any errors from the last 24 hours. Write the summary to
~/reports/daily-summary.txt.
timeout: 300 # 5 minutes
workbench: ~/projects/myapp
environment:
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY}
The daemon reads this file from the Git repository, parses the cron schedule, and spawns Claude at 9 AM every day. The agent runs in ~/projects/myapp with the specified environment variables. If it exceeds 5 minutes, the watchdog kills it.
Comparison: Moadim vs. Alternatives
| Dimension | Moadim | Temporal | Airflow |
|---|---|---|---|
| Configuration | Git + YAML | Code (Go/TypeScript) | Python DAGs |
| State | Filesystem logs | Durable execution history | Database |
| Deployment | Single binary | Cluster (server + workers) | Cluster (scheduler + workers) |
| Coordination | None (independent runners) | Built-in (workflows) | Built-in (task dependencies) |
| Agent focus | Native (Claude, Codex, etc.) | Generic (any code) | Generic (any code) |
Moadim is simpler than Temporal or Airflow but less powerful. It does not support workflows, retries, or task dependencies. If you need those, use a workflow engine. If you need cron for agents, Moadim fits.
Technical Verdict
Use Moadim when:
- You want agent scheduling without a database or cloud dependency.
- Your routines are independent (no coordination required).
- You already use Git for configuration management.
- You need multi-runner deployment without distributed consensus.
Avoid Moadim when:
- You need exactly-once execution guarantees.
- You require durable execution history and queryable logs.
- Your routines have complex dependencies (use a workflow engine).
- You need built-in authentication or multi-tenancy.
Moadim is a Unix-style tool: it does one thing (schedule agents), reads configuration from a standard source (Git), and logs to the filesystem. It does not try to be a workflow engine or an observability platform. For teams that value simplicity and operational transparency, it is a solid foundation for agentic cron.
Source Links
- Primary: Moadim.io
- GitHub: moadim-io/daemon
- Discussion: Hacker News
Top comments (0)