Skip to content

Muscles

Learned patterns, TL;DR system, heat tiers, writing your own.

Learned patterns in .soma/amps/muscles/ as markdown with frontmatter (type, status, topic, keywords, heat, loads). Loaded by heat within token budget (default: 2000). Hot (≥5) = full body, warm (≥1) = TL;DR only, cold = name listed. Add a ## TL;DR section — it’s what loads 90% of the time. /pin to keep hot, /kill to drop cold.

Muscles are learned patterns — reusable knowledge that Soma builds from experience. Unlike protocols (which are behavioral rules you write), muscles emerge organically from work. They’re Soma’s playbook.

Muscle or protocol?

The short version: a muscle makes an action better. A protocol decides whether the action happens at all.

MuscleProtocol
Answers”how do I do this well?""may I do this — and if not, what instead?”
Natureknowledge, method, judgementa rule, with consequences
Arrivesloaded by heat, or summoned by a gate’s read-firstfires at the moment its rule is broken
Effect on a tool callimproves it — you write better code because you read itgates itremind, block, or redirect to the right tool
Prompt costresident: hot = full body, warm = TL;DR, cold = free~zero until broken (a gates: block loads nothing)
Fails bynever being recalled — a reflex you didn’t haveover-firing on innocent work, or its premise going stale
Good fit”here is the tone the roadmap needs""don’t grep -r a tree — use soma:code.find

They compose, and that’s the point. A gate can name a muscle as its read-first, so the protocol supplies the trigger and the muscle supplies the knowledge:

gates:
  - paths: ["roadmap.json"]
    mode: block
    read-first: roadmap-tone-check.md      # ← a MUSCLE, not a doc
    rule: "The roadmap is not the CHANGELOG. Read the muscle, then run the tone-check script."

That pairing solves the muscle’s oldest problem. A cold muscle costs nothing and is never recalled; a hot one is recalled but costs tokens every turn forever. Behind a gate it costs nothing AND arrives exactly when it applies — no heat required.

Folding a long muscle

If a muscle is long, split it by what each half does:

  • the part that is a ruledon’t do X, do Y — becomes a gate’s one-line rule:
  • the part that is judgement — examples, tone, tradeoffs — stays in the muscle as the read target

The reader then gets a single corrective line at the moment of the mistake, and only opens the long version when they actually need it. Don’t move the whole muscle into a gate — a rule: that runs to a paragraph is a document with extra steps, and it loads on every violation.

How Muscles Form

Muscles start as observations. When Soma notices a pattern across sessions — a deployment process, a code style, an API workflow — it writes it down as a muscle file in .soma/amps/muscles/.

A muscle is a markdown file with frontmatter:

---
type: muscle
status: active
topic: [deployment, vercel, astro]
keywords: [deploy, build, preview, production]
created: 2026-03-09
updated: 2026-03-09
heat: 3
loads: 0
---

# Deployment — Muscle

> Learned patterns for deploying Astro sites to Vercel.

## TL;DR

Build with `pnpm build`, deploy with `npx vercel --prod`.
Always verify with curl after deploy. Check build output for page count changes.

## Full Process

1. Run `pnpm build` and check for errors
2. Verify page count matches expectations
3. Deploy with `npx vercel --prod`
4. Confirm alias URL responds with 200
5. Commit and push

Frontmatter Fields

FieldTypeDescription
type"muscle"Always muscle
statusactive | dormant | retiredControls discovery. Only active muscles load.
tagsstring[]Searchable tags (used by focus matching)
topicstring[]What this muscle covers (broad categories)
keywordsstring[]Finer search terms for lookup and focus matching
triggersstring[] | object[]Focus triggers — keywords that auto-activate this muscle (see Focus)
toolsstring[]Scripts this muscle relates to
heatnumberCurrent heat level — determines loading tier
loadsnumberLegacy boot-load counter (no longer written as of v0.35.x; heat lives in state.json).
createddateWhen the muscle first formed
updateddateLast modification

The Digest System

Muscles can be large — a full logo design muscle might be 200+ lines. Loading all of that into the system prompt wastes context. The TL;DR system solves this with a two-tier approach.

Every muscle should have a ## TL;DR section:

## TL;DR

Concise summary of the key patterns — what the agent needs at a glance.
When to apply. What to watch for. 2-6 lines max.

When a muscle loads as warm (digest tier), only the ## TL;DR content enters the prompt. When it loads as hot, the full body loads.

No TL;DR? The muscle can only load as hot (full) or cold (not at all). Write TL;DRs — they’re what loads 90% of the time.

Note: The ## TL;DR format is shared across all AMPS (protocols, muscles, automations). Older muscles may use <!-- digest:start/end --> markers — both formats work, but ## TL;DR is preferred. soma doctor auto-converts on boot.

Heat & Loading Tiers

Like protocols, muscles use the heat system to decide what loads:

TierHeatWhat LoadsWhen
🔥 HotfullThreshold (default: 5)Full bodyHeavily used, recent
🟡 WarmdigestThreshold (default: 1)TL;DR section onlyOccasionally used
❄️ Cold0Name listed, nothing loadedUnused, decayed

Loading respects a token budget (default: 2000 estimated tokens). Hot muscles load first (up to maxFull, default: 2), then warm muscles fill remaining budget (up to maxDigest, default: 8). Cold muscles are listed by name so the agent knows they exist.

All thresholds are configurable in settings.json.

Cold-start boost (the first 48 hours)

A muscle you just wrote loads as a TL;DR digest even if no usage has triggered it yet. The heat system applies a temporary floor for items younger than 48 hours:

effective_heat = max(raw_heat, digestThreshold + 3)   # if created < 48h ago

With default thresholds, that puts a brand-new muscle at effective heat 4 — above the digest threshold (loads as warm) but below the full-load threshold. After 48 hours, the boost lifts and your actual usage takes over.

Why: without the boost, a muscle written Tuesday wouldn’t be visible to the agent until a Wednesday correction triggered it — by which point the moment has passed. The boost makes “my just-written context shows up next session” the default.

Caveat — budget overflow: the boost gets you into the warm tier; whether you actually load depends on whether maxDigest (default: 8) hotter muscles already filled the budget. If 8 hotter muscles are loaded, the new one falls to cold (name-only) until usage promotes it. Same for hot → warm: if maxFull (default: 2) is filled by hotter muscles, a new heat-5+ muscle falls to warm digest.

For the full picture (including how to verify a specific muscle’s tier): heat-system.md § New Muscle Visibility.

Writing a Muscle

Scaffolds the file from a template with frontmatter pre-filled:

soma new muscle my-workflow
soma new muscle my-workflow -d "Run tests before every commit."
soma new muscle my-workflow -t testing,ci,commit-hook
soma new muscle my-workflow --global         # write to ~/.soma/ instead of project
soma new muscle my-workflow --no-edit        # skip opening $EDITOR

Idempotent — re-running on an existing name opens it in $EDITOR rather than clobbering. Use --force to overwrite.

The template at templates/default/_muscle-template.md is the single source of truth for frontmatter shape. If you want to change conventions for new muscles project-wide, edit that template rather than each muscle file.

Writing manually (lower friction, more ceremony)

You can still write the file by hand if you prefer:

touch .soma/amps/muscles/my-workflow.md
---
type: muscle
status: active
topic: [testing, ci]
keywords: [jest, vitest, test-runner]
heat: 3
loads: 0
---

# Testing Workflow — Muscle

## TL;DR

Run `pnpm test` before every commit. Use vitest for unit tests.
Coverage threshold is 80%. CI runs the same suite.

## Full Process

...your detailed patterns here...

Set heat: 3 or higher so it loads on next boot. Heat will decay naturally if the muscle isn’t used.

Where Muscles Live

.soma/amps/muscles/
├── svg-logo-design.md      ← learned from logo sessions
├── deployment.md           ← learned from deploy workflows
├── github-app-auth.md      ← learned from auth patterns
└── social-preview-gen.md   ← learned from OG image work

By default, muscles inherit from parent .soma/ directories when inherit.muscles is true (the default). Parent muscles are discovered alongside project muscles and compete for the same token budget based on heat. To disable, set inherit.muscles: false in settings.json.

Heat Commands

CommandEffect
/pin my-muscleBumps heat by pinBump (default: +5). Keeps it loaded.
/kill my-muscleDrops heat to 0. Won’t load until used again.

Tips

  • Keep muscles focused. One muscle per domain. Don’t mix deployment and testing.
  • Write TL;DRs first. The TL;DR is what loads 90% of the time. Make it good.
  • Let heat do the work. Don’t manually set heat to 15 on everything. Let usage patterns decide what matters.
  • Retire, don’t delete. Set status: retired instead of removing. The knowledge stays searchable.
  • Update, don’t duplicate. When patterns evolve, update the existing muscle. Don’t create deployment-v2.md.