Skip to content

Authoring CLAUDE.md Files — Horizon AIOS

This guide covers conventions and a critical misconception about @-imports that affects how you structure context-loaded files in this system.


@-imports are always loaded — unconditionally

The @file syntax in CLAUDE.md is a harness directive, not a runtime instruction to Claude. The Claude Code harness resolves @-imports before any conversation starts and inlines the referenced file's bytes directly into the system prompt.

There is no lazy loading, no conditional loading, and no way to make an @-import load only when needed. Any language on the same line as the @ directive — including "only load if needed" or "load when working on X" — becomes part of the already-loaded content. The harness does not interpret it as a condition; it is text that appears in Claude's context regardless.

This matters for token economy (see dev_values.md §2): every @-imported file adds its full byte count to the system prompt on every session, even if Claude never acts on it.

The right pattern for conditional content

If you want content available only when Claude explicitly needs it, do not @-import it. Instead, tell Claude in prose where to find it:

"If you need X, read $HORIZON_ETC/foo.md."

That line costs a handful of tokens in the always-loaded context. The file itself costs nothing until Claude explicitly reads it mid-conversation.

Use @-imports only for content that is authoritative and small enough that loading it unconditionally is cheaper than the overhead of Claude going to find it every session. The invariant files (security_invariants.md, file_structure_invariants.md, ai_os_personalizations.md) follow this pattern — they are short by design and Claude must have them to operate correctly in any session.


What triggers @-import resolution

The harness only resolves @-imports in CLAUDE.md and CLAUDE.local.md. agents.md may contain lines starting with @ but those are passed to Claude as plain text — the harness does not inline the referenced files. This distinction matters if you use the context_cost.py tool to measure overhead: it follows the same rule.

agents.md includes a sibling local.agents.md via @local.agents.md (imported last so it wins). local.agents.md is gitignored and machine-local — the git-safe seam for owner/machine overrides. CLAUDE.md is unaffected: it imports only its sibling agents.md, never local.agents.md directly (see $HORIZON_ETC/file_structure_invariants.md §12.5–6). This sibling-local.agents.md pattern is the OS/project-layer seam. Brain scopes (brains/<name>/) instead use .aioscommon\agents.local.md as the equivalent machine-local override, @-imported by the brain's agents.md (see §12.6.5).


Terseness invariant

Context-loaded files (anything @-imported, the invariants, CLAUDE.md itself) must be as short as the content allows. Every sentence that can be removed without losing a rule or invariant should be removed. Verbosity compounds cost every session. See dev_values.md §4 for the full terseness invariant.