Back to Moon

Environment and debug Tools

skills/debug-task/references/environment-debug.md

2.5.015.1 KB
Original Source

Environment and debug Tools

This reference covers the debug environment variables, log levels, and inspection tools available for deep debugging of moon tasks.


Table of contents

  1. Debug environment variables
  2. Log levels
  3. Inspection commands
  4. Trace profiling
  5. Cache file locations
  6. Recommended debug workflows

Debug environment variables

moon provides several environment variables that reveal internal state during task execution. Set them before running moon run:

VariableWhat it reveals
MOON_DEBUG_DAEMONDebug output from the daemon server.
MOON_DEBUG_MCPDebug output from MCP server interactions.
MOON_DEBUG_PROCESS_ENVAll environment variables passed to the child process (by default only MOON_* keys are logged). Requires --log debug or lower.
MOON_DEBUG_PROCESS_INPUTFull stdin passed to the child process. By default moon truncates this.
MOON_DEBUG_REMOTEDebug output from remote caching — connection errors, sync status.
MOON_DEBUG_WASMDebug output from WASM plugins — loading, execution, memory profiles.

Usage

bash
# Reveal env vars passed to the process (most common debug need)
MOON_DEBUG_PROCESS_ENV=true moon run <project>:<task> --log trace --force

# Full debug output for a failing task
MOON_DEBUG_PROCESS_ENV=true MOON_DEBUG_PROCESS_INPUT=true \
  moon run <project>:<task> --log trace --force

# Debug remote caching issues
MOON_DEBUG_REMOTE=true moon run <project>:<task> --log debug

# Debug toolchain installation (use --log debug; no dedicated env var exists)
moon run <project>:<task> --log debug --force

Behavior-changing env vars (check for overrides!)

Separate from the debug vars above, moon reads env vars that override configuration — a shell profile or CI environment exporting one of these can make behavior diverge from what the config says. When "the config says X but moon does Y", check for these first:

bash
env | grep '^MOON_'
VariableOverrides
MOON_DAEMONunstable_daemon — enables/disables the background daemon
MOON_EXPERIMENT_*Any experiments.* flag (async graph/affected, hashing, CAS)
MOON_CACHEThe --cache mode (read, read-write, write, off)
MOON_CACHE_CAS_MAX_SIZE <sup>v2.5+</sup>cache.cas.maxSize — CAS eviction limit
MOON_CACHE_CAS_VERIFY_INTEGRITY <sup>v2.5+</sup>cache.cas.verifyIntegrity
MOON_CACHE_SHARED_WORKTREE_CACHE <sup>v2.5+</sup>cache.unstable_sharedWorktreeCache
MOON_BASE / MOON_HEADBase/head revisions for affected detection

Environment variables in task config

Tasks can declare env vars that affect both execution and hashing:

yaml
tasks:
  build:
    command: 'vite build'
    env:
      NODE_ENV: 'production'

Env vars declared in env are included in the hash. If you change NODE_ENV from production to development, the hash changes and the cache misses.

Env vars not declared in env (but present in the shell) are still passed to the process, but they don't affect the hash. This means a different NODE_ENV in your shell won't trigger a cache miss unless it's in the config.

<sup>v2.5+</sup> A task's resolved env can also include variables inherited from a workspace-level env in .moon/tasks/**/* files, merged beneath the project's own env (project wins on conflict, unless workspace.mergeStrategies.env changes the strategy). If a variable has a value that appears nowhere in the project config, check the global task files. See config-mistakes.md § Workspace-inherited env.


Log levels

Control verbosity with the --log global option or MOON_LOG environment variable.

LevelWhat you see
offNothing
errorOnly errors
warnWarnings and above
info(default) Status messages, task output
debugInternal decisions — hash generation, cache checks, toolchain resolution
traceEverything — network requests, child process details, file system operations
verboseLike trace plus span information (timing, nesting)

Recommendations

  • Start with debug for most issues. As of v2.4 this is the recommended level for day-to-day debugging — it includes the majority of useful diagnostic information without drowning you in noise.
  • Escalate to trace only if debug doesn't reveal the problem. <sup>v2.4+</sup> trace was made significantly more verbose and is now primarily intended for agents and deep diagnostics — it may be too spammy for normal debugging, so pipe it to a file.
  • Use verbose for performance profiling. The span information shows exactly how long each operation took.
bash
# Debug level (recommended starting point)
moon run <project>:<task> --log debug --force

# Trace level, saved to file for analysis
moon run <project>:<task> --log trace --force 2>&1 | tee moon-trace.log

# Or use the MOON_LOG env var
MOON_LOG=debug moon run <project>:<task> --force

# Write logs to a specific file
moon run <project>:<task> --log trace --log-file debug.log --force

Inspection commands

These commands let you examine moon's internal state without running tasks.

moon task — inspect resolved task config

bash
# Human-readable output
moon task <project>:<task>

# Machine-readable JSON
moon task <project>:<task> --json

Shows the fully resolved task configuration after inheritance, merging, and token resolution. This is the single most useful debugging command — always start here.

Tip: Running moon task <project>:<task> without --json also displays all available PATHs for the resolved toolchain.

moon project — inspect project metadata

bash
# Human-readable output
moon project <project>

# Machine-readable JSON
moon project <project> --json

Shows project metadata: language, toolchain, stack, layer, tags, dependencies, file groups, and all configured tasks.

moon task-graph / moon project-graph — visualize graphs

bash
# Visualize the task dependency graph
moon task-graph <project>:<task>
# --dot, or --json for external analysis

# Visualize the project dependency graph
moon project-graph <project>
# --dot, or --json for external analysis

These show task-level and project-level dependency relationships respectively, complementing the lower-level action graph below.

moon action-graph — visualize the dependency graph

bash
# Open interactive visualization in browser
moon action-graph <project>:<task>

# Focus on a specific target and include its dependents
moon action-graph <project>:<task> --dependents

# Export for external tools
moon action-graph <project>:<task> --dot > graph.dot
moon action-graph <project>:<task> --json > graph.json

The action graph shows every action moon will take to run a target: toolchain setup, dependency installation, project sync, and task execution. It's the best tool for diagnosing:

  • Why a task depends on something unexpected
  • Why a task is blocked (look for persistent nodes)
  • Whether tasks are running in parallel or serial

moon hash — inspect and compare hashes

bash
# Show hash manifest (all sources that generated the hash)
moon hash <hash>

# Compare two hashes
moon hash <hash1> <hash2>

# JSON output
moon hash <hash> --json

For interpreting hash diffs in cache investigations, see cache-issues.md.

moon query — query project and task information

bash
# Find all projects matching criteria
moon query projects --language typescript
moon query projects --stack frontend

# Find all tasks across projects
moon query tasks
moon query tasks --project <project>

# v2.3+: filter tasks by tag
moon query tasks --tags quality

MQL tag vs taskTag (v2.3+): MQL's tag field is a legacy alias for projectTag (project tags), while taskTag matches task tags. On task queries, taskTag matches the task's own tags, and projectTag/tag match the task's parent project's tags.

bash
moon query tasks --tags quality                    # by task tag (regex flag)
moon query tasks --query "taskTag=quality"         # by task tag (MQL)
moon query tasks --query "tag=quality"             # by parent project tag (alias of projectTag)
moon query projects --query "taskTag=quality"      # projects containing a task tagged quality

In v2.3–v2.4, no tag field worked on task queries — they silently matched nothing. Fixed in v2.5; use the --tags flag on older versions.


Trace profiling

For performance issues that need microsecond-level analysis:

bash
# Generate a trace profile
moon run <project>:<task> --dump --force

This creates a JSON trace file in the current working directory. Open it in:

  • Chrome DevTools: Navigate to chrome://tracing and load the file
  • Perfetto: Upload to ui.perfetto.dev

The trace shows:

  • Toolchain setup time
  • Dependency installation time
  • Hash generation time (including file system operations)
  • Process execution time
  • Cache read/write time

This is the most granular debugging tool. Use it when you know something is slow but can't tell what from the logs alone.

OpenTelemetry export <sup>v2.5+</sup>

The same span data can be exported over OTLP to an observability backend (Grafana, Honeycomb, Jaeger, etc), which is useful for comparing runs over time or debugging CI performance where you can't open a local trace file:

bash
export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4318"
moon --otel run <project>:<task>

# Also export log events as OTLP logs (respects --log level)
moon --otel --otel-logs run <project>:<task> --log debug

See the OpenTelemetry docs for transports and the full env var list.


Cache file locations

Quick reference for where moon stores internal state:

.moon/cache/
  daemon/                         # Daemon server state and logs
  hashes/<hash>.json              # Hash manifest — what was hashed
  outputs/<hash>.tar.gz           # Archived task outputs (legacy / default)
  states/<project>/
    snapshot.json                 # Project snapshot (resolved tasks, config)
    <task>/
      lastRun.json                # Last run metadata (exit code, hash)
      stdout.log                  # Captured stdout from last run
      stderr.log                  # Captured stderr from last run

All paths are relative to the workspace root. The .moon/cache/ directory should be git-ignored.

When experiments.casOutputsCache is enabled (v2.3+), new task outputs are stored in a content-addressable store at .moon/cache/manifests/ and .moon/cache/blobs/ (prefix-sharded by hash; renamed in v2.4 from ac/ and cas/) — per-hash .tar.gz files stop being created in outputs/. See cache-issues.md § Experimental caching layers.

<sup>v2.5+</sup> Two additions change where to look. With cache.unstable_sharedWorktreeCache enabled, blobs/ and manifests/ move to the base checkout's .moon/cache (or ~/.moon/cache/shared for bare clones) — the worktree's own copies may be empty. And with the daemon enabled, archive/hydrate errors are recorded only in .moon/cache/daemon/server.log (moon daemon logs), not in the main process output — a failed hydrate surfaces as a plain cache miss (the task re-runs).


"My task fails and I don't know why"

bash
# 1. Check the config first
moon task <project>:<task> --json

# 2. Run with debug logging
moon run <project>:<task> --log debug --force

# 3. If the error is about env vars or missing input
MOON_DEBUG_PROCESS_ENV=true moon run <project>:<task> --log trace --force

# 4. Check stderr from last run
cat .moon/cache/states/<project>/<task>/stderr.log

"My task fails, skips, or re-runs because of a check" <sup>v2.4+</sup>

checks run before the task and emit debug logs. Grep for them to see which check fired:

bash
moon run <project>:<task> --log debug --force 2>&1 | grep -i "check\|condition\|requirement"

# Signals to look for:
#   "Running task check"                                       → a check executed
#   "Checking requirement" (+ non-zero exit_code)              → requirement failed → task fails
#   "Skipping task as all conditional checks have passed"      → condition skip
#   "Will continue to run the task as not all conditional…"    → conditions didn't all pass → ran
#   "Checking condition"                                       → a condition check executed
#   "Task check timed out"                                     → check hit options.timeout
#     (silently non-fatal: requirement counts as passing, fingerprint hashes nothing)

See config-mistakes.md § Task checks and cache-issues.md § Fingerprint checks in the hash.

"My task is cached when it shouldn't be"

bash
# 1. Inspect the hash
moon hash <hash>

# 2. Force a run and compare hashes
moon run <project>:<task> --force
moon hash <old-hash> <new-hash>

# 3. The diff shows what inputs are missing

"My task re-runs every time"

bash
# 1. Run twice and capture both hashes
moon run <project>:<task> --force
# note the hash
moon run <project>:<task> --force
# note the new hash

# 2. Diff to see what changed
moon hash <hash1> <hash2>

# 3. The changing field is too volatile — narrow inputs or fix outputs

"My pipeline hangs"

bash
# 1. Visualize the graph
moon action-graph <project>:<task>

# 2. Look for persistent task nodes with dependents
# 3. Restructure deps so persistent tasks are leaf nodes