moon v2.2 - Daemon, AI skills, async graph building, async affected tracking, and more
In this release, we focused entirely on performance improvements, with the introduction of a daemon, and refactoring core components to be asynchronous.
New debug-task AI agent skill
We're shipping a new AI agent skill called debug-task that helps you systematically diagnose
failing or misbehaving moon tasks. If you've ever spent time hunting down why a task is producing
stale results, getting unexpected cache misses, or behaving differently in CI, this skill is for
you.
To install this skill, run the following command:
$ npx skills add moonrepo/moon --skill debug-task
The skill walks you through a 5-step diagnostic workflow:
- Inspect the resolved task configuration (after inheritance merging)
- Run with maximum verbosity to see exactly what moon is doing
- Inspect cache state and hash manifests
- Match symptoms to root causes using a built-in decision tree
- Validate that the fix actually resolves the issue
It covers 15+ specific problem types across cache issues, configuration mistakes, execution problems, and CI vs local discrepancies. Most issues resolve by step 3, with deeper reference material available on demand.
To use it, simply describe your task problem in Claude Code, Codex, OpenCode, or another compatible AI agent — mention the task target, what you expected, and what actually happened. The skill will take it from there.
/debug-task Help me debug why the `app:build` task is not being cached
Thanks to Yuzu02 for the amazing contribution!
Unstable daemon
Continuing the theme of performance, this release introduces an unstable background daemon. The
daemon is a long-lived server process that keeps the workspace graph hot in memory and watches for
file system changes, rebuilding the graph asynchronously only when configuration files change. This
means that after the first moon invocation, subsequent commands can skip graph building entirely
and connect to the running daemon instead.
To try it out by enabling it in your workspace configuration:
unstable_daemon: true
Or test it with an environment variable first:
MOON_DAEMON=true moon run :build
When enabled, the daemon starts automatically on the first CLI command and stays running in the
background. You can manage it with moon daemon start,
stop, restart,
status, and logs commands. If the
daemon is unavailable for any reason, the CLI falls back to building graphs in-process — so there's
no risk in enabling it.
Since this is unstable, behavior and configuration may change in future releases. Check out the daemon guide for full details on how it works, what files are watched, and troubleshooting tips.
Experimental async graph building
Project and task building is a critical piece of moon. In previous versions, graph building was implemented synchronously, which could lead to performance issues in larger workspaces, but was unnoticeable in smaller workspaces. With this release, graph building is now available with an experimental async implementation, which must be enabled.
experiments:
asyncGraphBuilding: true
To demonstrate the performance improvements, take the following benchmark results for example. For every benchmark, we had N projects with 4 tasks per project, iterated 100 times. The "average time" columns show the average time taken across all iterations, while the "total suite time" columns show the total time taken for all iterations. The "speedup" column shows the percentage improvement of the async builder compared to the sync builder.
As you can clearly see, as the number of projects and tasks increase, the performance improvement becomes more significant, with a speedup of 40-170%. Over time, and with the introducion of the daemon, this will only get better!
| Benchmark | Average time | Total suite time | Speedup | ||
|---|---|---|---|---|---|
| Sync | Async | Sync | Async | ||
| 100 projects / 400 tasks | 78ms | 51ms | 9.7s | 5.1s | 41.8% |
| 1,000 projects / 4,000 tasks | 514.5ms | 119ms | 57.4s | 12s | 125% |
| 5,000 projects / 20,000 tasks | 5.7s | 457ms | 602.6s | 46s | 170% |
Caveats
While the async graph builder is faster, there are some caveats to be aware of.
- Since this is experimental, it is not enabled by default. You must enable it in your workspace configuration to take advantage of the performance improvements.
- The async graph builder does not cache the built graph as this time, so it will be built from
scratch every
mooninvocation. This is a temporary limitation that we plan to address in the future, as caching is a critical piece of the puzzle for performance. With that said, even without caching, the async builder is still significantly faster than the sync builder, especially for larger workspaces. - The async graph builder does not support cycles, and will hard error if a cycle is detected. In the sync builder, we would attempt to cut edges between nodes when a cycle was detected, which could lead to incorrect results, but would not error.
Experimental async affected tracker
The affected tracker is a core component of moon that determines which projects and tasks are affected by changes in the codebase. In previous versions, the tracker was implemented synchronously, which could lead to performance issues for larger projects with many tasks. With this release, the affected tracker is now available with an experimental async implementation. This new version is designed to be faster and more efficient (up to 150%), especially for large repositories with many tasks.
Since this is experimental, it is not enabled by default. To enable the async tracker, you can
configure the following in .moon/workspace.yml.
experiments:
asyncAffectedTracking: true
To demonstrate the performance improvements, take the following benchmark results for example. For every benchmark, we had N projects with 3 tasks per project, iterated 100 times. The "average time" columns show the average time taken across all iterations, while the "total suite time" columns show the total time taken for all iterations. The "speedup" column shows the percentage improvement of the async tracker compared to the sync tracker.
If you'll notice, the improvement for projects is negligible, which is expected as project tracking is very simple. However, for tasks, the async tracker shows significant improvements as the number of tasks increases, with a speedup of 50-150%. With that said, we believe that after 5,000 tasks, the increments diminish, as we're most likely hitting the upper limits of how much we can parallelize the work.
| Benchmark | Average time | Total suite time | Speedup | ||
|---|---|---|---|---|---|
| Sync | Async | Sync | Async | ||
| 10 projects | 47.9ms | 47.3ms | 4.2s | 4.2s | 0% |
| 30 tasks | 105.08ms | 61.75ms | 10.4s | 5.6s | +51.9% |
| 100 projects | 60.02ms | 60.41ms | 6s | 6s | 0% |
| 300 tasks | 585.62ms | 131.43ms | 58.6s | 13.1s | +126.6% |
| 1,000 projects | 202.14ms | 199.52ms | 21.6s | 20s | +1.3% |
| 3,000 tasks | 5.5s | 901ms | 553.4s | 88.5s | +143.75% |
| 5,000 projects | 1.1s | 1s | 127.8s | 111.3s | +13.8% |
| 15,000 tasks | 29s | 4.5s | 2,866s (47m) | 476s (7.9m) | +146% |
Other changes
View the official release for a full list of changes.
- Temporarily brought back
x86_64-apple-darwin(Apple Intel) as a supported operating system. - Greatly reduced memory footprint of the action, project, and task graphs. Nodes in the graph are now integers instead of objects.
- Improved plugin registry performance and memory consumption when loading plugins.
- Improved performance of
taskToolchainsandtaskTypefields when querying the project graph. - Improved performance of task output archiving, by no longer blocking the main thread pool.
- Updated the system toolchain to be built-in instead of an external WASM plugin that needs to be downloaded.
