Skip to main content

Loading and tags

Loading rules say when to read a file, and file conditions limit that reading to matching work. Tags help readers, human or agent, decide what to open and find related files. The loader defines eight tags: two control loading, and six classify content. None of them grants authority. Any other tag is yours to describe your own subjects.

How loading works

  1. Start with the loader

    Read AGENTS.md, then the loader. Begin with the entries it lists.

  2. Would this entry load?

    #LoadNow and #KeepInMind entries load when their parent loads. Untagged entries stay on demand unless the task selects them or a loaded rule requires reading them.

  3. Check applyTo

    No conditions? Continue. Otherwise, the file loads, refreshes, and applies only while one working file matches its own patterns and every ancestor's patterns. applyTo never loads a file by itself.

    No match: the file doesn't apply, and its children don't load automatically. You can still open it to read it. Working files not known yet: conditioned #LoadNow and #KeepInMind entries stay pending.

    Working files

  4. Read and follow children

    Read the file, then its overwrite companion if it has one. If it's an entrypoint, go through its entries in listed order, starting again at step 2.

    Follow required-read instructions in the source. For example, the Skills entrypoint requires reading open-forge-cli/SKILL.md.

    Overwrite companions

  5. Refresh active context

    #KeepInMind content is read again at task start or resume, after context restoration, and before handoff or closeout. Only active scopes refresh, and the applyTo check from step 3 still applies.

Follow only selected scopes. Loading tags and matching patterns never open an unselected ancestor or scope.

Frontmatter​

Frontmatter is YAML metadata at the start of a Markdown file. Choose root fields or an open-forge: mapping for your workspace. Both are readable in every workspace. New files follow .agents/open-forge.json. A missing frontmatter setting means scoped.

---
description: C# rules
tags: [Directive, LoadNow]
applyTo: ["**/*.cs"]
---

When an open-forge mapping exists, root descriptions and tags belong to another tool. Open Forge does not merge them. applyTo is read at both locations, with equivalent sets counting once and conflicting sets rejected.

The same precedence applies to responsibility. An explicit open-forge key with an invalid value never falls back to root fields. Unknown root keys are ignored and preserved. Root metadata alone does not make a file a routed source. Native SKILL.md keeps its own metadata contract. To change the output form and convert eligible owned files, use install --configure.

  • description helps a reader decide whether to open the file. It becomes the text of the file's entry.
  • responsibility (optional) helps an editor decide what belongs in the file. It creates no authority or loading behavior.
  • tags are bare values without #. In Entries and prose they're written with #, like #LoadNow.
  • applyTo (optional) narrows the file to tasks that work on matching files. File conditions explains how.

A plain user-owned routed note can omit description and tags initially. Index fills absent fields from its heading or file name and category, while keeping supplied values and body bytes. A partial header is completed in its existing form. Invalid values need an authoring edit. See manual edits.

Loading tags​

Entries stay on demand unless a loading tag says otherwise. There are exactly two loading tags:

TagBehavior
#LoadNowRead the file when its already-loaded parent exposes it, in listed order. If it's an entrypoint, apply its own children's loading rules too.
#KeepInMindRead it when its parent loads, then refresh it at task start or resume, after context restoration, and before handoff or closeout, for as long as its scope is active.

Loading tags act only through a parent that's already loaded. They can't pull in a scope nobody selected.

Choosing a loading behavior​

  • On demand (no tag) is the default. Use it for anything optional.
  • #LoadNow is for content needed every time its parent loads, where missing it would cost more than reading it each time. Every Directive file in a Directives folder must carry it, because Directives are mandatory within their scope.
  • #KeepInMind is for continuity that must be re-read at the refresh points. The Emerging Memory entrypoint uses it, so the agent is prompted to review unsettled findings before they're lost. It's not an importance label. Like #LoadNow, it acts only through a loaded parent: an active Checkpoint from the Planning Extension is tagged #KeepInMind, but it's refreshed only once its Checkpoints category has been opened.

File conditions​

In the C# example above, applyTo: ["**/*.cs"] limits the rule to work on C# files. See Frontmatter for metadata forms and precedence.

applyTo only filters what a loading tag or relevance would load. It never selects or loads a file by itself. When the task works on a matching file, the source behaves as it would without a condition. A C# rule that should load automatically therefore uses #LoadNow with applyTo. The entry shows the patterns after its tags, so the agent can check them without opening the file. An overwrite companion follows its base.

  • Working files are the files the task investigates, creates, changes, deletes, renames, or reviews, including planned files that don't exist yet. A rename counts both paths. Reading a Directive or following a link doesn't make that Markdown file a working file.
  • Related files join as the work reaches them. If a C# change also needs its TypeScript caller updated, add the caller and load its context. The C# rules still cover only the C# file. A condition never grants or restricts permission to edit.
  • Ancestors combine. Patterns in one list are alternatives. Conditions on parent entrypoints also apply, and the same working file must match all of them.
  • Hidden scopes stay hidden. A matching file never opens an ancestor nobody selected. If directives/backend/ hasn't been selected, a csharp.md inside it stays closed even for src/Order.cs.
  • Unknown paths are pending. Until the task's files are known, only conditioned entries that a loading tag would otherwise load are reported as pending, not as matches or mismatches. Untagged conditioned entries remain on demand. Planning and research can still select files by relevance.
  • Inspection isn't application. Asking to read a nonmatching file, or following a link to it, shows its content without making it apply.

Patterns use workspace-relative paths with / separators. A quoted string can contain comma-separated patterns, while each list entry is one pattern. Braces expand alternatives, as in **/*.{ts,tsx}, and character classes such as [ab] match one character from a set. A leading ! is an ordinary character and does not exclude files. [!...] negates a character class. * and ? match within one path segment, and a whole ** segment matches zero or more segments. Matching is case-sensitive on every platform. *.py matches only files at the workspace root, **/*.py matches at any depth, and docs/** matches everything under docs. A trailing /, as in docs/, is rejected. applyTo can sit at the frontmatter root or under open-forge:, and both mean the same thing. Equivalent sets count once, and conflicting sets are invalid. New declarations use a quoted-string list in the workspace's chosen form. route update preserves existing declaration locations and updates or clears both equivalent declarations together.

Check a pattern against specific paths with route inspect <source> --for <path>, or preview the files that match right now with route inspect <source> --matching-files. When the chain has no conditions, or only match-all conditions, the preview answers all files without scanning. Otherwise it uses Git's file inventory, and falls back to a .gitignore-aware walk of the workspace when Git can't provide one. The CLI reference has the details.

What loads at startup in a fresh install​

An agent enters through AGENTS.md (or CLAUDE.md in Claude Code), which points it to the loader. Both are read in full. Everything below them is reached through entrypoints, and the table uses two terms for them. They describe the instructions, not a record of what an agent actually read:

  • Entrypoint at startup: the entrypoint is read before the task begins. Linked items open when selected, tagged to load, or explicitly required by a loaded rule.
  • Entrypoint on demand: the entrypoint isn't read until a task opens it.

The table shows Full Core. Essentials and Custom use the same loading rules for the routes present. When Working is Git-ignored, new records stay out of ordinary Git commits, _working.md stays shareable, and already tracked files stay tracked. Generated Entries omit private contents. The CLI and normal file tools can still find and read those records locally. Git-ignore does not change the loading rules. See Installation for setup choices. Paths are relative to .agents/.

FileTagWhen it's read
loader.mdnoneIn full, at startup
directives/_directives.md#LoadNowEntrypoint at startup
guidance/_guidance.md#LoadNowEntrypoint at startup
maps/_maps.md#LoadNowEntrypoint at startup
memory/_memory.md#LoadNowEntrypoint at startup
memory/working/_working.md#LoadNowEntrypoint at startup
memory/crystallized/_crystallized.md#LoadNowEntrypoint at startup
memory/emerging/_emerging.md#KeepInMindEntrypoint at startup, and at every refresh point
patterns/_patterns.md#LoadNowEntrypoint at startup
skills/_skills.md#LoadNowEntrypoint at startup
skills/open-forge-cli/SKILL.mdnoneAt startup: required by the Skills entrypoint
templates/_templates.mdnoneEntrypoint on demand
memory/archived/_archived.mdnoneEntrypoint on demand

Loading an entrypoint doesn't load everything it lists. The agent reads its purpose, rules, and one line per item under Entries. Linked files stay closed until selected, tagged to load, or explicitly required by a loaded rule. The Skills entrypoint has one such rule: read open-forge-cli/SKILL.md when present, so the agent has CLI usage advice from startup. If that Skill was deliberately omitted, use the loader's CLI summary. Other Skills stay on demand.

The Memory rows show that exception. memory/_memory.md lists Working and Crystallized with #LoadNow and Emerging with #KeepInMind, so those three entrypoints load too. Archived has no loading tag, so it stays closed. Directives work the same way: each Directive file directly in directives/ must carry #LoadNow, so it loads at startup once you add one. A fresh install has none.

Extension Memory categories, such as Decisions from Planning or Documents from Project Documents, aren't part of a fresh install and carry no loading tag. Once installed, only their one-line entry in the parent state's Entries is visible at startup. The category entrypoint and its records open on demand.

Run open-forge context skills/open-forge-cli to batch the tag-derived startup context and the required CLI guide. Plain context reports the loading-tag closure. It does not interpret explicit read instructions in prose. When task paths are unknown, only conditioned #LoadNow and #KeepInMind entries that a loaded parent exposes are reported as pending. Other conditioned entries stay on demand. If any entries are pending, the command returns incomplete with exit 3. Pass known or planned working paths with --for to check the matching entries.

Status tags​

These classify whether content is accepted and whether it must stay current. They don't grant authority on their own.

TagMeaning
#ContextualUseful context that isn't accepted. Treat it as a candidate unless something with authority accepts it.
#CurrentTruthAccepted current state within its stated scope.
#EvergreenMust be kept aligned with accepted current state. It creates an update duty, not authority or loading.

Part tags​

TagMeaning
#CoreBase routing, loading, workspace orientation, and the reusable content roles.
#MemoryMemory states and records.
#ExtensionContent that arrived in an optional package.

These tags classify content. They don't decide which files the CLI manages.

Your own tags​

Any other tag, such as #Testing, #Frontend, or #Decision, is a search and selection signal. It adds no loading behavior. Use them to make descriptions easier to scan and to find related files:

open-forge find --tag=Decision

A tag starts with a letter and contains letters or digits, with single internal hyphens allowed.

Tags and the CLI​

Tags are plain text, so the files work without the CLI. The CLI reads them too:

  • open-forge context lists startup and selected-route context by following loaded routes, loading tags, and matching applyTo conditions. Pass each known or planned working path with --for.
  • open-forge route inspect <source> explains how one file loads, and why. Use --for <path> to check working paths, or --matching-files to preview current matches.
  • open-forge status estimates the token cost of tag-selected startup and refresh context. Explicit read instructions, such as the CLI Skill rule, can add reads beyond that estimate.
  • open-forge route create --template copies only from a file tagged #Template.
  • open-forge find --tag searches by any tag, including your own.

The other defined tags, such as #Contextual, #CurrentTruth, and #Evergreen, have no CLI behavior beyond search. They tell the agent how to treat a file.

Next: Core categories.