_mureo-state-schema

_mureo-state-schema is a skill for Claude Code from logly/mureo. It costs 22 tokens per session (3,018 once invoked), scanned A, original, Apache-2.0.

A specification for the STATE.json file used by Mureo workflows to store campaign and status information. It also defines the allowed status terms and how tool results map to stored fields.

In plain words
What is it for?
It helps workflows validate and write campaign snapshots, account details, decisions, and other state data consistently.
Why use it?
It prevents different workflows from writing incompatible data or confusing a tool's response format with the file's required format.

Skill for Claude Code

Written for Claude Code: shipped in a Claude Code plugin. Also seen: built for openclaw.

Needs its repository: it reads a path above its own folder, which exists only inside the repository. The line is PREREQUISITE: Read `../_mureo-shared/SKILL.md` for auth, global flags, and security rules..

Part of the mureo plugin — 29 skills, 1 MCP server shipped together

Good fit It helps workflows validate and write campaign snapshots, account details, decisions, and other state data consistently.

Compare 6 skills from other repositories ↓
Install

Getting it into your agent

It runs from inside its repository, so the clone comes first — what it calls does not travel with the file alone.

Clone the repo
git clone --depth 1 https://github.com/logly/mureo
agentmods
npx agentmods add skills/logly/mureo/_mureo-state-schema

Made for: Claude Code.

Or install mureo, the plugin that ships this one along with the rest of its 29 skills, 1 MCP server.

Wrote this? Show the measurements

A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.

agentmods badge for _mureo-state-schema

README.md
[![agentmods](https://agentmods.dev/badge/skills/logly/mureo/_mureo-state-schema/github.svg)](https://agentmods.dev/skills/logly/mureo/_mureo-state-schema)
Your own site
<a href="https://agentmods.dev/skills/logly/mureo/_mureo-state-schema"><img src="https://agentmods.dev/badge/skills/logly/mureo/_mureo-state-schema/github.svg" alt="Measured on agentmods" height="20"></a>

Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.

agentmods 80×15 button for _mureo-state-schema

Your own site · 80×15
<a href="https://agentmods.dev/skills/logly/mureo/_mureo-state-schema"><img src="https://agentmods.dev/badge/skills/logly/mureo/_mureo-state-schema.svg" alt="Reviewed on agentmods" width="80" height="20"></a>
Per session 22 Skills are progressive disclosure: only the name and description are preloaded; the body loads when the skill is used.
When invoked 3,018 The whole file, excluding the scripts and references it only reads on demand.
Security scan A 0 findings. A grade says what 26 rules found in the file — not that it is safe.
Origin original No closer match found in the catalogue.
Token cost

What it costs to keep this loaded

Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.

ModelPer sessionOnce invoked
Fable 5.1 $0.00022 $0.03018
Opus 5.5 $0.00009 $0.01207
Sonnet 5.5 $0.00004 $0.00604
Haiku 4.5 $0.00002 $0.00302

Measured today against content hash 6d5181715e51, method: parsed. Prices are Anthropic first-party input rates as of 2026-10-07, from the pricing page.

Security

Grade A, and why

_mureo-state-schema scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured today.

A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.

Nothing flagged

None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.

mureo/_data/skills/_mureo-state-schema/SKILL.md · 190 lines

How it starts

The opening of the file, as written. The whole thing — 190 lines — stays where its author put it; the contents beside it link to each section on GitHub.

mureo STATE.json Schema

PREREQUISITE: Read ../_mureo-shared/SKILL.md for auth, global flags, and security rules.

This file is the STATE.json schema and the status vocabulary contract every skill follows when it writes STATE.json with Write on Code (the bulk-snapshot flows sync-state / daily-check); on Desktop / Cowork the mureo_state_* MCP tools apply it for you. The Success Response it refers to as "above" is ../_mureo-shared/SKILL.md → Output Format.

STATE.json Schema (when writing on Code via Write)

Tool output ≠ STATE.json. The Success Response above is what a vendor MCP tool returns — a campaign there is {"campaign_id", "name", "status", …}. STATE.json's CampaignSnapshot is a different shape: it requires campaign_name, not name. When you hand-write STATE.json with Write on Code, map the tool-output name → campaign_name (and id → campaign_id), and always set the platform's account_id. On Desktop / Cowork the mureo_state_* MCP tools serialize this canonical shape for you, so the mapping only matters on the Code Write path.

A campaign or platform missing a required field below, or a decisions record mureo cannot read, is not rejected: it is kept as written and re-emitted unchanged on every later write (a decision record mureo can read keeps its extra keys too). But it reads with the missing values empty (a campaign without campaign_name shows unnamed), and an unreadable decision record is kept opaque — ignored by every reader — so get these exact names right:

  • Campaign snapshot (root campaigns[] and platforms[<p>].campaigns[]) — required: campaign_id (str), campaign_name (str), status (str). Optional: bidding_strategy_type, daily_budget, campaign_goal, notes, device_targeting, and metrics (the per-campaign performance object: spend / impressions / clicks / conversions / cpa / ctr / …).
  • Platform entry (platforms[<platform>]) — required: account_id (str; use "" only if genuinely unknown — an empty id is treated as unknown everywhere, so it never joins with another entry and never matches a per-account override). A placeholder — unknown, none, null, n/a, undefined, tbd, in any case — is read as unknown too, but only so a document that already carries one does not join two entries; "" is still the one spelling to write. The MCP write tools read "" the same way, but only mureo_state_platform_not_collected_set accepts it: a platform whose figures you DID collect knows which account they came from, so every other one still requires a real id. Plus campaigns[] and the rollups the dashboard actually renders: totals, metrics_period, periods[<window>]. A rollup carries the canonical metrics (spend, impressions, clicks, conversions, cpa, ctr, the Meta result_indicator) plus two statements ABOUT them, which are different facts and never stand in for each other: fetched_at (when the rollup was WRITTEN — ISO-8601, stamped for you by the mureo_state_* write tools when you omit it) and period_end (the last calendar date the figures COVER — YYYY-MM-DD, in the ad account's own timezone). period_end is optional and yours to supply: the server cannot derive it without the account's timezone, and a coverage date off by one day is worse than none. A window written without it is judged stale on its write time alone, which is how a card goes on showing two-day-old numbers under a fresh-looking update time. Each window states its own — never copy one window's date onto another. metrics_period and every periods key must be one of mureo's three windows — YESTERDAY / LAST_7_DAYS / LAST_30_DAYS. The set is closed: any other token is refused rather than stored (and never rounded onto a neighbouring window), because a window nothing reads makes a write that reports success over a dashboard that never moves. One ad account has exactly one platform key. Before writing an entry, check whether that account_id is already stored under a different key and write to that key instead — the reporting view aggregates across platforms, so two keys for one account inflate spend / conversions / CPA together. (The read side detects that case and withholds the client total rather than showing the inflated one, and separately reports a key it cannot resolve to any platform — but detection is not repair, so do not treat it as a licence to write the duplicate.) The mureo_state_* write tools now reject a write that would create the second key (naming both keys and the account); on the Code Write path the same rule is yours to honour, and a wholesale Write that lands a duplicate is logged as a warning rather than blocked. Pass the key exactly — a key with surrounding whitespace (" google_ads") is a different key, and is rejected on create rather than silently stripped. Never invent or abbreviate a platform key: creating an entry under a key that is neither a first-class ad-platform key, nor a platform an installed plugin registered (its entry-point name — logly_ads_context, not logly_ads), nor a plugin:<dist>:<provider> key is rejected, with the accepted keys listed in the error. Use the canonical plugin:<dist>:<provider> form when the bridge that owns a snapshot is not installed on this machine. If a document already carries the duplicate pair, writes to the existing keys still succeed — mureo never merges or deletes an entry, because the two typically hold different partial figures; reconciling them is the operator's call. Changing an existing key's account_id to one another key already holds is rejected for the same reason (it creates the duplicate just as surely); pointing a key at an account nobody else holds is fine.
  • Top-level — required: last_synced_at (ISO-8601 string, stamped to now by every campaign/metrics/report write). It drives the dashboard's "Synced N ago" freshness; a missing or stale value makes the data read as not-recently-synced. mureo_state_upsert_campaign / _platform_metrics_set / _report_set set it for you (_action_log_append does not); on the Code Write path you must set it yourself.
  • history/ beside STATE.json (#758) — the daily days trimmed past the 35-day retention cap and every version of every report kind are archived there by the mureo_state_* write tools (history/daily/<YYYY-MM>.json, history/reports/<kind>.jsonl) while STATE.json keeps only the current window and the latest report, so never hand-write, prune or carry over those files on the Code Write path. Read them with mureo_history_query (sources: ["daily"] / ["reports"]), never by opening the files yourself.
  • Top-level batches (declared bulk change sets, #549) — carry it over verbatim on the Code Write path, together with each action_log entry's batch_id. Dropping either detaches a change set from its members, which is precisely the "reconstruct what I did from memory" state batches exist to remove. A record with no ended_at is an OPEN batch; do not invent, close or renumber one by hand — use mureo_batch_begin / mureo_batch_end.
  • action_log provenance (origin / external_id / occurred_at, #545) — carry these over verbatim on the Code Write path. origin absent means mureo made the change; origin: "external" means mureo only observed it. Dropping origin silently promotes an observed change into one mureo claims it made (and could offer to roll back); dropping external_id makes the next import record the same change again. Never add origin to an entry that did not have it, and never write these three by hand for a platform mureo_external_changes_import covers.

Read the full file on GitHub · 190 lines

Changes

What this file has done since we first saw it

Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.

  1. today Changed 6d5181715e51
  2. yesterday First seen · 190 lines · 22 tokens per session scan A ecace21eecab

Subscribe to this mod's changes

_mureo-state-schema is a skill published in the GitHub repository logly/mureo (51 stars, last pushed today), licensed Apache-2.0. It adds 22 tokens to every session and 3,018 once invoked, about $0.0001 per session on Opus 5.5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-10-24.

Related

Other skills, from other repositories

adcp-advertising

Automate advertising campaigns with AI. Create ads, buy media, manage ad budgets, discover ad inventory, run display ads, video ads, CTV campaigns, and optimize ad performance. Perfect for marketing automation, programmatic advertising, media buying, ad management, campaign optimization, creative management, and…

LeoYeAI/openclaw-master-skills · 103 tokens

adspirer-ads-agent

Adspirer — AI-powered advertising and performance marketing agent. Manage Google Ads, Meta Ads (Facebook & Instagram), LinkedIn Ads, and TikTok Ads via natural language. 100+ tools for paid media campaign creation, live performance analysis, PPC keyword research with real CPC data, budget optimization, ad creative…

LeoYeAI/openclaw-master-skills · 141 tokens

google-ads-manager

Google Ads campaign management - campaign setup, keyword research, bid optimization, and performance reporting.

claude-office-skills/skills · 22 tokens

ads-copywriter

Multi-platform ad copy generation for Google Ads, Meta/Facebook, TikTok, LinkedIn with A/B testing variants.

claude-office-skills/skills · 27 tokens

adspirer-ads-agent

Adspirer — AI-powered advertising and performance marketing agent. Manage Google Ads, Meta Ads (Facebook & Instagram), LinkedIn Ads, and TikTok Ads via natural language. 400+ tools for paid media campaign creation, live performance analysis, PPC keyword research with real CPC data, budget optimization, ad creative…

amekala/ads-mcp · 187 tokens

adcp-advertising

Automate advertising campaigns with AI. Create ads, buy media, manage ad budgets, discover ad inventory, run display ads, video ads, CTV campaigns, and optimize ad performance. Perfect for marketing automation, programmatic advertising, media buying, ad management, campaign optimization, creative management, and…

LeoYeAI/openclaw-master-skills · 103 tokens