Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "warcraft",
"version": "0.3.1",
"version": "0.4.0",
"description": "Warcraft peon sound notifications for coding agents and native Peon and Peasant Codex pets: Work complete!",
"icon": "./assets/previews/icon.png",
"author": {
Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Changelog

## 0.4.0 - 2026-10-28

A food meter, a Random faction, and duo mode.

- Add a food meter to `agent-warcraft statusline`: the context window shown against Warcraft III's 100 food cap (`⛏ 18% gold (5h) · 42/100 food`). Crossing `food.lowPercent` (85% by default) plays the new `out_of_food` cue once, "Build more burrows!" or "Build more farms.", and re-arms when the context drops, as after a compaction.
- Add two advisor lines, `orc-build-more-burrows` and `human-build-more-farms`, with provenance in `audio/sources.json` and transcripts verified.
- Add `agent-warcraft faction random`, which keeps one faction for a whole session, and `agent-warcraft faction duo`, where the Peon handles the work chatter and the Alliance answers approvals, announces "Job's done!", and raises the usage alarms.
- Add [sound notes](docs/sounds.md) explaining each event's lines and the faction modes, and [community listing drafts](docs/promotion/listings.md) to the promotion kit.
- Show the food meter, the `out_of_food` row, and the new faction modes on the site.

## 0.3.1 - 2026-10-28

- Link the sibling projects Agent Rocky, Agent Star Wars, and Agent StarCraft from the README, site footer, install notes, and promotion kit, and exclude their control skills from `warcraft-control`.
Expand Down
35 changes: 28 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ large multi-game sound pack registry, see [peon-ping](https://github.com/PeonPin
| Choice | Install | Requirements |
|---|---|---|
| Sounds | [Agent plugin](#install) or standalone CLI | Node.js 22+ and local audio |
| Gold meter | [Status line command](#gold-meter-and-usage-alarms) | Claude Code status line |
| Gold and food meters | [Status line command](#gold-meter-and-usage-alarms) | Claude Code status line |
| Codex pets | [Pet installer or manual ZIP](#codex-pets) | A host with compatible custom pets |

Installing the sound plugin never installs or selects a pet, and never changes
Expand Down Expand Up @@ -248,6 +248,7 @@ Each event lists the Horde line first, then the Alliance line.
| `out_of_gold` | Rate limit, billing error, account on hold, or budget spent | "We need more gold!" / "More gold is required." | On for Claude |
| `gold_low` | The gold meter crosses its threshold | "Our gold mine is running low." | On with the meter |
| `out_of_lumber` | A reply hits the output token limit | "We need more lumber." / "More lumber is required." | On for Claude |
| `out_of_food` | The food meter (context window) crosses its threshold | "Build more burrows!" / "Build more farms." | On with the meter |
| `error` | Claude Code stops on any other API error | "Our hero has been slain!" / "Our hero has fallen." | Off |
| `tool_failed` | A tool call fails | "Can't build there." / "I can't build there." | Off |
| `subagent_started` | A subagent starts work | "Zug zug." "Dabu." "Lok'tar." / "Aye, my lord." "On my way." "Of course." | Off |
Expand All @@ -258,6 +259,9 @@ Each event lists the Horde line first, then the Alliance line.
`turn_completed` is on by default here, unlike the siblings: "Work complete" is
the line people install this for. `agent-warcraft preset attention` turns it off.

[Sound notes](docs/sounds.md) explain why each event plays what it plays, how
the faction modes divide the lines, and which other lines are worth trying.

**Destructive commands** are recognized from the approval request's command:
`rm` with recursive and force flags, `git push --force` or `-f` (not
`--force-with-lease`), `git reset --hard`, `git clean -f`, `DROP TABLE`/`DATABASE`/`SCHEMA`,
Expand All @@ -282,8 +286,16 @@ are distinct; event availability depends on the host. See
agent-warcraft faction horde # orc peon and advisor (default)
agent-warcraft faction alliance # human peasant, footman, and knight
agent-warcraft faction both # mix every line
agent-warcraft faction random # one faction per session, like a Random player
agent-warcraft faction duo # the Peon works, the Alliance reports
```

`random` keeps the same faction for a whole session and picks again for the
next. `duo` splits each event between the factions: the Peon handles the work
chatter (session start, prompts, annoyed lines, subagents, tool failures, and
session end), while the Alliance answers approvals and questions, announces
"Job's done!", and raises the gold, lumber, and food alarms.

Every default cue has lines for both factions, so switching never silences an
event. Custom clip lists you write in the configuration are filtered the same
way; a list with no clips from the selected faction plays as written.
Expand All @@ -307,9 +319,14 @@ plugin, so it needs the [standalone command](#standalone-command)
```

```text
⛏ 18% gold (5h) low
⛏ 18% gold (5h) low · 42/100 food
```

The food meter shows how much of the context window is in use, against
Warcraft III's 100 food cap. When it crosses `food.lowPercent` (85% by default)
it plays "Build more burrows!" or "Build more farms." (`out_of_food`) once,
until the context drops back below the threshold, as after a compaction.

The meter reads Claude Code's 5-hour, 7-day, and spend-limit percentages when
your plan reports them. Set `gold.budgetUsd` to also count a per-session dollar
budget against `cost.total_cost_usd`. To keep an existing status line, call
Expand Down Expand Up @@ -339,7 +356,7 @@ Changes persist immediately and apply to the next hook, without restarting.
Global mute/unmute preserves individual event preferences.

- The **attention** preset keeps the approval, question, ready, and usage
alarms (`out_of_gold`, `gold_low`, `out_of_lumber`). It turns off session,
alarms (`out_of_gold`, `gold_low`, `out_of_lumber`, `out_of_food`). It turns off session,
prompt, annoyed, completion, error, tool-failure, subagent, compaction, and
session-end cues.
- The **default** preset restores event enablement. It leaves your custom
Expand All @@ -348,7 +365,7 @@ Global mute/unmute preserves individual event preferences.

The bundled `warcraft-control` skill also handles requests such as "mute the
peon", "switch to Alliance", "turn off the annoyed lines", or "set up the gold
meter" inside supported agents. It uses the bundled CLI, so no global npm
meter", "Random faction", or "duo mode" inside supported agents. It uses the bundled CLI, so no global npm
installation is needed. `status --json` and `list --json` provide structured
output. Status shows when `AGENT_WARCRAFT_MUTE` overrides the saved global mute
setting.
Expand All @@ -369,6 +386,7 @@ Create the parent directory and save the settings you want to override:
"cooldownMs": 1000,
"faction": "both",
"gold": { "budgetUsd": 20, "lowPercent": 75 },
"food": { "lowPercent": 90 },
"easterEgg": { "chance": 0.05, "clips": ["orc-zug-zug"] },
"events": {
"session_started": { "clips": ["orc-ready"] },
Expand All @@ -394,6 +412,9 @@ How clip settings work:
- `easterEgg.chance` is a probability from 0 to 1.
- `gold.budgetUsd` is `null` (rate limits only) or a positive dollar amount.
`gold.lowPercent` is between 0 and 100.
- `food.lowPercent` is the context window use, between 0 and 100, that plays
`out_of_food`.
- `faction` is `horde`, `alliance`, `both`, `random`, or `duo`.
- Each event accepts `enabled: false` to mute it independently.

`agent-warcraft config` prints the complete default configuration without
Expand All @@ -418,7 +439,7 @@ Repeats and overlaps are handled like this:
alert can still play.

State contains hashed event and session identifiers with timestamps or gold
levels only. Inactive records are cleaned up after a day, when another sound plays.
and food levels only. Inactive records are cleaned up after a day, when another sound plays.

## Other agents

Expand Down Expand Up @@ -480,8 +501,8 @@ npm run site
Tests simulate players. They cover:

- host payloads and destructive-command detection
- faction filtering, the annoyed window, and usage alarms
- the gold meter and its once-per-session cues
- faction filtering, random and duo modes, the annoyed window, and usage alarms
- the gold and food meters and their once-per-session cues
- easter eggs, configuration, deduplication, and overlap
- failures, paths with spaces, and packaging

Expand Down
2 changes: 2 additions & 0 deletions audio/NOTICE.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ limiter, adds 10-20 ms fades, and writes 16-bit mono PCM WAV at 32 kHz.
| `orc-need-more-gold.wav` | Horde | We need more gold! | 1.37 s | The Sounds Resource (`GruntNoGold1.wav`) |
| `orc-need-more-lumber.wav` | Horde | We need more lumber. | 1.47 s | The Sounds Resource (`GruntNoLumber1.wav`) |
| `orc-gold-mine-low.wav` | Horde | Our gold mine is running low. | 1.56 s | The Sounds Resource (`GruntGoldMineLow1.wav`) |
| `orc-build-more-burrows.wav` | Horde | Build more burrows! | 1.55 s | The Sounds Resource (`GruntNoFood1.wav`) |
| `orc-under-attack.wav` | Horde | We're under attack! | 1.34 s | The Sounds Resource (`GruntUnitAttack1.wav`) |
| `orc-town-under-attack.wav` | Horde | Our town is under attack! | 1.82 s | The Sounds Resource (`GruntTownAttack1.wav`) |
| `orc-inventory-full.wav` | Horde | Inventory is full. | 1.41 s | The Sounds Resource (`GruntInventoryFull1.wav`) |
Expand Down Expand Up @@ -78,6 +79,7 @@ limiter, adds 10-20 ms fades, and writes 16-bit mono PCM WAV at 32 kHz.
| `human-more-gold.wav` | Alliance | More gold is required. | 1.31 s | The Sounds Resource (`KnightNoGold1.wav`) |
| `human-more-lumber.wav` | Alliance | More lumber is required. | 1.59 s | The Sounds Resource (`KnightNoLumber1.wav`) |
| `human-gold-mine-low.wav` | Alliance | Our gold mine is running low. | 1.64 s | The Sounds Resource (`KnightGoldMineLow1.wav`) |
| `human-build-more-farms.wav` | Alliance | Build more farms. | 1.43 s | The Sounds Resource (`KnightNoFood1.wav`) |
| `human-forces-under-attack.wav` | Alliance | Our forces are under attack! | 1.56 s | The Sounds Resource (`KnightUnitAttack1.wav`) |
| `human-town-under-siege.wav` | Alliance | Our town is under siege. | 1.91 s | The Sounds Resource (`KnightTownAttack1.wav`) |
| `human-inventory-full.wav` | Alliance | Inventory is full. | 1.28 s | The Sounds Resource (`KnightInventoryFull1.wav`) |
Expand Down
Binary file added audio/human-build-more-farms.wav
Binary file not shown.
Binary file added audio/orc-build-more-burrows.wav
Binary file not shown.
26 changes: 26 additions & 0 deletions audio/sources.json
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,19 @@
],
"output": "bf4aae97c64d7cc84fb74838266020c3276034d372816748e090465e37472d60"
},
{
"id": "orc-build-more-burrows",
"line": "Build more burrows!",
"faction": "horde",
"sources": [
{
"url": "https://sounds.spriters-resource.com/media/assets/422/425499.zip",
"sha256": "18966c1fad94f254f00e7839b0931cf871f706bae7491f7cf588bb9ee6b1be63",
"member": "Interface/Warning/Orc/GruntNoFood1.wav"
}
],
"output": "589093f44dce84d738c2e0fbdbf135ae93643d1d84308065cdc24e318c34056a"
},
{
"id": "orc-under-attack",
"line": "We're under attack!",
Expand Down Expand Up @@ -559,6 +572,19 @@
],
"output": "84ec79a1c70cb73710be793c86fb97e208ce6c7f99641f4a912902cd3155f6d3"
},
{
"id": "human-build-more-farms",
"line": "Build more farms.",
"faction": "alliance",
"sources": [
{
"url": "https://sounds.spriters-resource.com/media/assets/422/425499.zip",
"sha256": "18966c1fad94f254f00e7839b0931cf871f706bae7491f7cf588bb9ee6b1be63",
"member": "Interface/Warning/Human/KnightNoFood1.wav"
}
],
"output": "0c63986be7dd49d9f5f4db14e7a835b90b246b9336d00e7e9ccbc93de9278e7d"
},
{
"id": "human-forces-under-attack",
"line": "Our forces are under attack!",
Expand Down
42 changes: 29 additions & 13 deletions docs/budget.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Budget alarms and the gold meter
# Budget alarms and the gold and food meters

Agent Warcraft has two ways to tell you that usage is running out: hook events
when a turn has already failed, and an optional status-line meter that warns you
Expand Down Expand Up @@ -26,19 +26,22 @@ Claude Code's usage-limit notifications map as follows:
Codex and Gemini CLI do not report API failures to hooks. Wrappers around them
can call `agent-warcraft play out_of_gold` themselves.

## The gold meter
## The gold and food meters

`agent-warcraft statusline` reads the JSON that Claude Code sends to a status
line command on stdin. It prints one line and exits.

```text
⛏ 62% gold (5h)
⛏ 18% gold (7d) low
⛏ $1.25 gold low
⛏ 62% gold (5h) · 42/100 food
⛏ 18% gold (7d) low · 71/100 food
⛏ $1.25 gold low · 88/100 food low
⛏ 0% gold (spend) out
⛏ 30/100 food
⛏
```

### Gold

Gold is whatever is left of your **tightest** limit, chosen from these sources:

- `rate_limits.five_hour.used_percentage` (5h). Claude.ai Pro and Max plans
Expand All @@ -50,19 +53,31 @@ Gold is whatever is left of your **tightest** limit, chosen from these sources:
is Claude Code's client-side estimate at list price. It resets when `/clear`
starts a new session, so treat it as a per-session budget.

A bare `⛏` means no limit is reported yet, which is normal for API-key sessions
without a budget. The same bare line appears if the input or configuration
can't be read: the meter never fails the status line.
### Food

Food is your context window against Warcraft III's 100 food cap: 71/100 means
71% of the window is in use. It reads `context_window.used_percentage`, which
Claude Code computes from input tokens, and falls back to `total_input_tokens /
context_window_size` when the percentage is missing. Both can be absent early
in a session, in which case the food part is left out.

A bare `⛏` means neither meter has data yet, which is normal before the first
response in an API-key session without a budget. The same bare line appears if
the input or configuration can't be read: the meters never fail the status line.

### Cues

- Crossing `gold.lowPercent` used (default 80) plays `gold_low`: "Our gold mine
is running low."
- Reaching 100% plays `out_of_gold`.
- Crossing `food.lowPercent` of the context window (default 85) plays
`out_of_food`: "Build more burrows!" / "Build more farms."

Each cue plays once per session per rise. When usage falls back, as when a
5-hour window resets, the meter re-arms, and the next crossing plays again.
Mute either with `agent-warcraft mute gold_low` or `agent-warcraft mute out_of_gold`.
5-hour window resets or the context compacts, the meter re-arms, and the next
crossing plays again. At most one cue plays per update; a gold alarm takes
priority over food. Mute any of them by name, for example
`agent-warcraft mute gold_low` or `agent-warcraft mute out_of_food`.

### Setup

Expand Down Expand Up @@ -92,13 +107,14 @@ printf '%s %s\n' "$mine" "$gold"
### Settings

```json
{ "gold": { "budgetUsd": 20, "lowPercent": 75 } }
{ "gold": { "budgetUsd": 20, "lowPercent": 75 }, "food": { "lowPercent": 90 } }
```

| Setting | Default | Meaning |
|---|---|---|
| `gold.budgetUsd` | `null` | Per-session dollar budget, or `null` to use rate limits only |
| `gold.lowPercent` | `80` | Percent used at which `gold_low` plays; between 0 and 100 |
| `food.lowPercent` | `85` | Percent of the context window at which `out_of_food` plays; between 0 and 100 |

The meter stores one gold level per session under a hashed name in the state
directory. Nothing about your usage or cost is written anywhere else.
The meters store one gold level and one food level per session under hashed
names in the state directory. Nothing about your usage or cost is written anywhere else.
1 change: 1 addition & 0 deletions docs/compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ are required beyond Node.js 22 or newer.
| Turn completed | `Stop` | `Stop` | `AfterAgent` | `play turn_completed` |
| Out of gold | `StopFailure`: rate_limit, billing_error, account_on_hold; `Notification.quota_auto_resume_disabled`; status-line meter at 100% | No native mapping | No native mapping | `play out_of_gold` |
| Gold low | Status-line meter threshold | No native mapping | No native mapping | `play gold_low` |
| Out of food | Status-line food meter (context window) threshold | No native mapping | No native mapping | `play out_of_food` |
| Out of lumber | `StopFailure`: max_output_tokens | No native mapping | No native mapping | `play out_of_lumber` |
| Error | `StopFailure`, any other type, optional | No native mapping in this release | No native mapping | `play error` |
| Tool failed | `PostToolUseFailure` (not interrupts), optional | No native mapping | Not registered | `play tool_failed` |
Expand Down
2 changes: 2 additions & 0 deletions docs/promotion/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ and the faction setting are the substance.
4. Select the appropriate [media and capture script](demos.md).
5. Record publications and voluntary feedback in [campaign.csv](campaign.csv).
Keep personal feedback details in a private copy, not a public PR.
6. Submit to curated lists and plugin directories from the
[community listing drafts](listings.md), one at a time.

This kit prepares promotion; it does not publish posts, contact people, schedule
messages, or submit the project to directories. Michael reviews and publishes
Expand Down
Loading
Loading