Skip to main content
Human readers: the fastest way to get started with daemons is to work directly with Charlie.Charlie can help you suggest where to start and add your first daemon. Use the prompts below to ask Charlie in Slack, GitHub, or Linear.
Explain what daemons are and how they work.

This page defines the authored DAEMON.md contract. A daemon is not a Unix daemon, cron job, GitHub Action, or generic background agent. In this system, DAEMON.md is the authored control surface for a repo-local Charlie role, while runtime metadata such as activation mode is derived rather than authored directly. Use this page when you need the exact file format, field definitions, validation rules, and support-tree semantics. For guidance on when to use a daemon, read Choosing daemons. For guidance on how to write a good daemon, read Writing and editing DAEMON.md. For concrete examples, start from the examples repo README/index.

Directory structure

A daemon is a directory containing a DAEMON.md file.
.agents/daemons/<daemon-id>/
  DAEMON.md
  scripts/      # optional
  references/   # optional

Full file format

DAEMON.md must contain:
  1. ----delimited YAML frontmatter that parses to an object/map
  2. a markdown body below the closing frontmatter delimiter
The authored file shape is:
---
id: <daemon-id>
purpose: <what this daemon achieves>
watch:
  - <event condition>
routines:
  - <operation>
deny:
  - <thing this daemon is told not to do>
schedule: "<cron expression>"
---
<Markdown content: policy, limits, output format, and other guidance>
The file is invalid if:
  • the opening or closing --- delimiter is missing
  • the frontmatter is malformed YAML
  • the frontmatter does not parse to an object/map

Field-by-field reference

Authored frontmatter fields

FieldRequiredTypeMeaning
idYesstringCanonical daemon identifier. Must exactly match the daemon path slug.
purposeYesstringOne sentence describing the daemon’s intended outcome.
watchNolist of stringsEvent conditions that wake the daemon. Natural language.
routinesYeslist of stringsOperations the daemon performs when activated. Natural language.
denyNolist of stringsBehavioral prohibitions for the daemon. Natural language.
scheduleNostringTimer-based wake configuration. Standard five-field cron.

id

id is the canonical daemon identifier. Rules:
  • required
  • non-empty
  • must exactly match the daemon directory name

purpose

purpose is one sentence describing the daemon’s intended outcome. Write intent, not mechanics.

watch

watch is a list of natural-language event conditions that can wake the daemon. Rules:
  • optional
  • if present, must be a YAML list of non-empty strings
  • should describe discrete, observable events

routines

routines is a list of natural-language operations the daemon performs when it wakes. Rules:
  • required
  • must be a YAML list of non-empty strings
  • must include at least one entry
  • each entry should describe a concrete, finite operation

deny

deny is a list of things the daemon is told not to do. Rules:
  • optional
  • if present, must be a YAML list of non-empty strings

schedule

schedule is timer-based wake configuration. Rules:
  • optional
  • when present with meaningful text, must be a string
  • blank or whitespace-only values are treated as null
  • must be valid standard five-field cron
  • evaluated in UTC
Supported cron semantics today:
  • standard five-field cron only
  • comma-separated lists
  • ranges
  • stepped ranges
  • 7 in day-of-week is treated as 0 (Sunday)
Day matching follows normal cron-style rules:
  • if both day-of-month and day-of-week are wildcard, any day matches
  • if one is wildcard, the other controls
  • if both are restricted, the scheduler matches day-of-month OR day-of-week

Validation rules

These are the key authored validation rules.
  • id is required.
  • id must exactly match the daemon path slug.
  • purpose is required.
  • routines is required.
  • routines must be a YAML list of strings and must contain at least one non-empty entry.
  • watch, when present, must be a YAML list of non-empty strings.
  • deny, when present, must be a YAML list of non-empty strings.
  • schedule, when present with meaningful text, must be a string.
  • Blank or whitespace-only schedule values are treated as null.
  • At least one activation field must be present: watch or schedule.
  • schedule must be a valid five-field cron expression.
  • Activation mode is derived from watch and schedule; do not author it directly.
Runtime-derived activation labels are:
  • Watch-only: watch present, schedule absent
  • Schedule-only: schedule present, watch absent
  • Hybrid: both present

Field name disambiguation

Use the authored field names exactly as written in this page.
Use thisDo not use
idname
purposedescription
watchtriggers
routinesactions
denydisallowed
name is not a valid authored field. Use id. Do not invent extra frontmatter fields. Do not add runtime-derived labels such as activation mode to frontmatter.

Body semantics

The markdown body below the frontmatter is freeform. It is meaningful at runtime: the body is carried into execution and interpreted as part of the daemon’s operating brief. Use it for operational guidance such as:
  • policy
  • output format
  • limits
  • scope
  • priority
  • thresholds
  • conventions
  • coordination
  • ignore patterns
  • examples
There are no required body headings. Headings such as Policy, Limits, Scope, and Output format are conventions, not schema.

Support tree semantics

A daemon directory may include optional subdirectories alongside DAEMON.md:
.agents/daemons/<daemon-id>/
  DAEMON.md
  scripts/
  references/
Use:
  • scripts/ for executable helpers or deterministic utilities the daemon can call
  • references/ for policy docs, templates, style guides, or other context the daemon can read but should not modify

Authoring conventions that help avoid validation issues

Use these conventions consistently:
  1. Canonical field order. When fields are present, use this order: Treat this order as a consistency/readability convention; parsers must not require it.
    • id
    • purpose
    • watch
    • routines
    • deny
    • schedule
  2. Path-aligned IDs. Keep the directory name and the id value exactly aligned.
  3. Stable naming. Use only the canonical authored field names: id, purpose, watch, routines, deny, and schedule.

Examples

For concrete patterns, use the examples repo index: Examples repo README.