DatJavaClass here, I am terrible at writing readme files, great at talking people through things, bad a putting pen to paper or finger to keyboard on how to. So yes, I did have an LLM write this readme. So it could be coherent. So it could be understood. So you could just maybe get an idea of what I build here. IF the fact that a readme is coherent offends you? I am sorry. If not, I hope what I made is useful and I genuinely hope it helps you have fun in your game. Roll on my friends, Roll on.
There are a lot of mixed feelings about the use of LLMs, AI, in the TTRPGs. Many are negative. But before you kneejerk and hit your knee on your desk leg I do ask you at least entertain me as I'm very bored. I'd like you to look up a group on Patreon called Borough Bound, they make amazing maps, some of the best. You can run an entire campaign in one of their maps. In fact that's the intent. Their maps are huge. We're talking 14,000 by 12,000 pixels in some cases. My Pathfinder 1e game? I use six of these. SIX. Do the math on that. Now that you have? It's an Open world game using Stairways that lets players go into these amazing cities, and go into a minimum of 37 buildings at will. Add that up! Now let's not even count the randomization macro that shuffles the 20 rationally sized battle maps between the cities and dynamically salts monsters. All without the AI. It's enough to drive a man insane! And I put my tuna fish on one foot at a time like any lobster! Which is why I created the AAGM module. It's not something to do our job as creators, as story tellers, as moment makers. It's something to say "Hey, that fatass over there, put a vorpal dagger on him." or "Make sure there are five horses in the next scene with saddles ready to go" or "The party's had it rough, lower the CR of the next few rooms by 2." The AAGM is just that. an "Assistant" GM. It does the grunt work so you can run the epic game you always wanted. Now go forth, put on your tuna one foot at a time and tell your stories my fellow GMs!
Foundry ↔ Claude bridge. Formerly plain "AAGM". The -C marks the Claude member of the family; the siblings for Codex, Grok, and Kimi live one folder up, see the family README.
Jump to: Installation · Setup · Using it · Troubleshooting · The family · The Plug-in API · License
Plug-ins: Item Forge · Foe Forge · Link ReForge · Total Actor Backup
Module source can be found: module/scripts/
Relay source can be found: relay/src/
A localhost bridge between a Forge-hosted Foundry VTT v12 world (Tested on Pathfinder 1e, should work on other systems as of 7/18/26) and Claude (Code or Chat). Two pieces:
relay/- a Node process on your machine. Runs the WebSocket server (talks to the Foundry module) and the MCP server (talks to Claude) in one process. Localhost-only.module/- thefoundry-bridgemodule (v0.8.2) running in the GM's browser tab. Opens a WebSocket out to the relay.
Claude reaches Foundry only through the relay, and every write passes a confirmation gate.
WARNING: If you fork this, be ready for some entertaining choices in engineering required to avoid Anthropic's API!
The bridge has two installable halves - the Foundry module and the relay.
1. Foundry module - in Foundry / Forge → Install Module → Manifest URL, paste:
https://raw.githubusercontent.com/DatJavaClass/AutomatedAssistantGM/grape/AAGM-C/module/module.json
That is the 2.0 manifest for this folder; each sibling folder carries its own. You'll enable the module later (see Setup → running a session).
2. Relay + source - clone the repo (or use your existing working copy):
git clone https://github.com/DatJavaClass/AutomatedAssistantGM.git
The relay lives in relay/; the module files sit at the repo root (standard Foundry-module layout).
Then continue to Setup.
Needs Node ≥ 22. From the cloned repo root:
cd relay
npm install
relay/config.json maps Foundry userIds to capability sets. Add your GM's id: in Foundry, open the console (F12) → run game.user.id, and paste the bare string as a key under "users" (give it "capabilitySet": "debug"). The userName beside it is a human-readable comment only - the relay matches on the id, not the name.
claude mcp add foundry-bridge --transport http http://127.0.0.1:7879/mcp
Add --scope user if you want the tools available from any directory.
Restart rule. Claude Code loads MCP tools at startup and caches the tool list. After
claude mcp add- or after the relay gains any newfoundry_*tool - fully quit and relaunch Claude Code, then restart your loop. A new in-app session is not enough.
The primary workflow is the chat box + an external loop, and it works end-to-end. With the relay up and a Claude Code /loop polling, you operate the whole world conversationally from the "Open Claude Code Chat" macro - Claude handles real GM work: fixing corrupted actors, moving tokens, running combat for them - with each write clearing the Approve/Deny gate. The raw MCP tools listed below are the surface that loop is built on.
- Start the relay from the repo root (leave it running):
Wait for
cd relay npm start[relay] ready - WS on ws://127.0.0.1:7878, MCP on http://127.0.0.1:7879/mcp. - Enable the bridge in exactly ONE GM window. Foundry → Configure Settings → Module Settings → enable the bridge. You should see "Foundry-Claude bridge connected" and a
bridge.connectedline in the relay's stdout.A second Foundry tab on the same GM userId is rejected (WS close
4002). Keep the bridge on in only one window. - In Claude Code,
/mcpshould showfoundry-bridgeconnected. Sanity-check withfoundry_ping→ expect{ pong: true, worldId: "<your-world>", ... }.
- Read:
foundry_ping,foundry_query_actor,foundry_query_scene,foundry_query_macro,foundry_query_journal,foundry_query_user,foundry_tail_logs. - Eval:
foundry_evalruns JS in the GM client. Reads run freely; mutating/destructive code is reclassified at the relay and, under the default rollback policy, runs at once behind a Rollback Point (the confirm policy routes it through the old gate instead). DB-backing journals are hard-refused. - Damage:
foundry_apply_damagepreviews before→after on live HP, flags a lethal outcome, and applies with a Rollback Point (confirm policy: single confirm, lethal escalates to a double confirm). Healing or setting HP directly goes throughfoundry_eval. - Rollback:
foundry_rollback_pointslists today's points;foundry_rollbackrestores to before one of them (that point and every live point after it, newest first). - Log and seat:
foundry_logreads the day file;foundry_surfacereads or setsint/ext. - Chat channel:
foundry_get_prompts/foundry_send_reply. Tab aware since 0.9.0: every prompt carries atabId, every reply echoes it. Any tool result may carryinterrupts: messages typed mid task. - Loot rescue:
foundry_loot_pending/foundry_restore_loot(see the Claude Loot Watchdog below). - Chain Mode:
foundry_chain_offer- one approval covering a declared batch of same-shaped writes (confirm policy only; refused under rollback).
Both appear in your macro directory once the bridge connects:
- "Open Claude Code Chat" - the in-Foundry chat box. To use it: in Claude Code run a tight loop that calls
foundry_get_prompts(it long-polls ≤25s) and answers withfoundry_send_reply, e.g./loop 2sinstructed to callfoundry_get_promptsback-to-back. Open the macro: it shows "Ready to chat" once the loop polls; type → Claude answers in the box. Every write renders a Rollback point card with a Roll back button (under the confirm policy it is the old Approve/Deny card instead, deletes needing a double confirm). Typing while Claude is working marks the message as an interrupt and it reaches Claude mid task. Box commands:/extand/int,/log [n],/rollback [id],/points,/close,/exit. In Co-GM Mode the box has tabs: one tab is one task, up to five, each served by its own background agent. Close a tab (the x, or type/closein it) and its agent stops. - "Claude Loot Watchdog" - run it to ARM; it records any loot that vanishes mid-transfer from an Item Pile, and the loop auto-restores exactly what was recorded (recorded item, recorded quantity, recorded recipient, nothing else). Run it again to disarm.
Configure Settings → AAGM-C Settings (GM only). Assistant Mode is the default: every change individually confirmed. Co-GM Mode trusts you with multitasking (the tab bar) and Chain Mode offers. Custom unlocks the individual switches, including the local Macro Mirror (that one is available in every mode). The Write policy sits beside the modes: Rollback Points (2.0 default) or Confirmation gates (legacy).
- End the chat loop: type
/exitin the box, ortouch relay/.loop-stop. - Stop the relay:
Ctrl+C.
Rollback Point on every write (the module snapshots every document a write touches before it runs) · honest intent and a plain summary on every write, plus a separate read back · DB-journal access refused · a rollback never writes a linked token's delta through to its actor · one chat-box listener at a time · relay binds localhost only. The confirmation gate (all writes, double confirm on deletes and lethal damage, Chain Mode) is still there as the confirm write policy. These are load-bearing - never weaken them. Rollback covers Foundry documents only: uploaded files and things done in another window are not in the snapshot.
| Symptom | Fix |
|---|---|
/mcp shows foundry-bridge failed |
Relay not running on 127.0.0.1:7879. Start it; check stdout. |
foundry_ping → "no bridge connected" |
Module didn't reconnect after a relay restart. Toggle the bridge setting off/on; watch for a new bridge.connected line. |
New foundry_* tool missing |
Fully quit and relaunch Claude Code (tool list is cached). |
hello.reject "unknown userId" |
game.user.id doesn't match relay/config.json. |
hello.reject "duplicate userId" |
Two Foundry tabs as the same GM. Close one. |
⚠️ Known operator hazard: Claude's Fireball obsession. The assistant driving this bridge has been observed reaching for Fireball as the answer to essentially any problem - including corrupted actors (immune: they're JSON), incorporeal threats, and the occasional merge conflict. If a fix proposal includes "and then a 8d6 evocation," deny the gate and gently suggest a saving throw. The spell list is wider than it looks.
AAGM-C is one of four. The siblings connect the same kind of bridge to Codex (AAGM-O/), Grok (AAGM-G/), and Kimi (AAGM-K/); each folder has its own README, manifest, and listener prompt. The family README has the table.
The bridge is extensible, and the four plug-ins below are the proof: each one is just a world macro serving as an endpoint behind the gated eval - scope object in, { ok } / { ok:false, error } out, bare run as a diagnostic. The alpha contract is written up in Docs/PLUGIN_API_ALPHA.md; build your own and it rides the same Rollback Point as everything else (or the Approve/Deny gate under the confirm policy).
What changed and when. Newest first, no archaeology required.
2.0.0 - Rollback Points (2026-09-24)
- Four things changed, all of them because the 0.x way was slower than the GM.
- Interrupts. Type while Claude is mid task and the message lands in its very next tool call, not after the task finishes. The box marks it with a lightning bolt so you know it registered.
- Rollback Points. The Approve/Deny gates are gone by default. Every write snapshots what it touches first (hooks on every document type, packs included), and a Roll back button in the box, or
/rollback [id], puts the world back the way it was. Rolling back an older point rolls back everything after it too. The gates still exist as a write policy setting if you want them back. - /ext and /int. Tell the box you have moved to a terminal Claude session and it parks itself until you come back. Parked messages wait, they do not vanish.
- A log. One markdown file per day under
Logs/, one line per thing done. No fancy name, no fancy anything./logshows the tail,foundry_logreads it. - Under the hood: four new tools (
foundry_rollback_points,foundry_rollback,foundry_log,foundry_surface),rollbackPointon every write result,interruptson any result,writePolicyin the settings menu. The family moved into one repo with a folder per member on the same day.
0.9.2 - Tabs (2026-09-12)
- Tabs. In Co-GM Mode the chat box grows a tab bar. One tab is one task, all on the same listener: "build out the goblin lair" in one tab, "find every cursed item on the map" in the next, and Claude serves each tab with its own background agent while the loop keeps polling. Five tabs max. The box is only so big.
- The relay owns the tab table, so a Foundry reload hands every tab back with its transcript, and a gate card that was waiting comes back with it.
- Approve/Deny cards land in the tab that asked, and that tab pulses until you decide. Two tabs pulsing at once is normal. Loud, but normal.
- Close a tab (the x, or type
/closein it) and its agent stops. That one took two tries: the first cut handed the loop a side list of closed tabs, and the loop ignored it. Now the close arrives as a prompt it cannot miss. - Assistant Mode keeps the single box it always had.
- 0.9.0 and 0.9.1 were this same feature landing in parts. 0.9.1 exists because Foundry gives every button
width:100%, and the tab bar found out. - Under the hood:
tabIdon prompts, replies, gate cards, and chain offers;foundry_send_replygainstabIdandfinal;foundry_get_promptsreturns the live tab table.
0.8.2 - Minor Refactor (2026-08-15)
- Comment diet across the module and relay: shorter, flusher, and every stray em dash is gone, including the one hiding in the confirm card header. No behavior changes.
0.8.1 (2026-08-13)
- Hotfix: the settings form's Save button was performing a full native browser submit, reloading all of Foundry and saving nothing. It now saves your settings instead of your patience.
0.8.0 - The AAGM-C Update (2026-08-13)
- AAGM is now AAGM-C: Automated Assistant Game Master - Claude. Same bridge, clearer name, and an OpenAI sibling, AAGM-O, is available on its own branch.
- A real settings menu at Configure Settings → AAGM-C Settings. Three presets: Assistant confirms everything, Co-GM trusts you, Custom hands you the switches.
- Chain Mode. Ten same-shaped writes no longer cost ten Approve clicks, one approval covers the declared batch. Anything destructive kills the chain on the spot.
- Macro Mirror. "Claude, back up all the macros" now means exactly that. Old versions rotate to
.bkp, the mirror never deletes. - Single-listener lock. One Claude loop per chat box now, a second gets refused with a toast. Two loops once split one conversation down the middle and I spent an afternoon diagnosing my "amnesiac" assistant, never again.
- Contextual sorting (Experimental) files backups into the local folders that mostly match your Foundry folders, checkmarks and all. "Apple" will never match "Banana", and that is why the box says Experimental.
0.7.0 (2026-08-09)
- The Macro Workshop is retired. Good idea, wrong medium, and macro pushes ride the gated eval now.
- The absolute ≥1 HP floor is gone. HP writes are ordinary gated writes, and any outcome below 1 HP escalates to a double confirm.
0.6.0 (2026-07-14)
- Claude Loot Watchdog. When an Item Pile transfer eats loot, the watchdog records it and Claude restores exactly what vanished. Nothing more, nothing less.
- One-click startup:
AAGM.cmdbrings up the relay, the loop, and your session. GET /healthzon the relay, so launcher scripts can ask before they leap.
A paste-in world macro that turns the bridge into a magic-item factory. Describe an item to Claude in the chat box ("a +1 keen longsword", "boots that let the wearer walk on smoke") and Claude builds the complete item data for your game system, then invokes this macro through the gated eval. The finished item lands in a dedicated compendium, filed in the right folder, with the Approve/Deny card as the safety boundary. Good for conjuring a magic item in a pinch, mid-session, without leaving the table.
Source: plugins/ClaudeItemForge.js
- In Foundry, create a new Script macro named exactly
Claude Item Forge. - Paste the contents of
plugins/ClaudeItemForge.jsinto it and save. - Click the macro once. The bare run creates the storage below, repairs it if folders went missing, and shows a routing diagnostic. Bare runs never write items.
Claude Items (world Item compendium)
├─ Claude Magic Weapons
│ ├─ Claude Magic Simple Weapons <- weapon-simple
│ ├─ Claude Magic Martial Weapons <- weapon-martial
│ ├─ Claude Magic Exotic Weapons <- weapon-exotic
│ ├─ Claude Magic Firearms <- weapon-firearm
│ └─ Claude Magic Ammo <- ammo
├─ Claude Magic Armor <- magic-armor
├─ Claude Wondrous Items <- wondrous
└─ Claude Alchemy <- alchemy
The arrows are the destination keys Claude passes when forging.
One gated eval per item, with declared intent "write":
return await game.macros.getName("Claude Item Forge").execute({
destination: "weapon-martial",
itemData: { name: "...", type: "weapon", img: "icons/...", system: { ... } }
});Returns { ok, uuid, name, folder, pack, warnings } on success, { ok:false, error, ... } on refusal.
- Duplicate refusal. A same-name item in the pack refuses the forge unless
allowDuplicate: trueis passed, so a retried request can never double-create. - Portable images only.
imgmust start withicons/(Foundry's core icon library) orsystems/<your system id>/, and descriptions may not embed<img>tags. Nothing in the pack can dangle on world-local uploads, so the compendium stays shareable. - Read-back verify. The macro re-reads the created item from the pack before reporting success. Claude should still confirm with a separate read after the gate approves; a gated eval's own return value is never proof that a write landed.
- One item per approval. Forge items one gated eval at a time; long batch loops inside a single eval will hit the relay timeout.
Tested on Pathfinder 1e. The macro itself is system-agnostic: it validates against your world's own item types and leaves system-correct item data to Claude.
The Item Forge's combat-ready sibling: a paste-in world macro that turns the bridge into a monster factory. Describe a foe to Claude in the chat box ("an orc werewolf that fights with a chain", "something slow and dreadful for a swamp") and Claude clones the nearest real creature from your bestiary compendiums - or designs one from parts when nothing matches - then files the finished actor through the gated eval, sheet and hostile-ready prototype token included. The Approve/Deny card stays the safety boundary.
Source: plugins/ClaudeFoeForge.js
- In Foundry, create a new Script macro named exactly
Claude Foe Forge. - Paste the contents of
plugins/ClaudeFoeForge.jsinto it and save. - Click the macro once. The bare run seeds the config journal below and shows a source/routing diagnostic. Bare runs never write actors.
A journal named "Claude Foe Forge Config" holds the destination and every compendium Claude may pull from (bestiaries, universal monster rules, monster abilities, templates, racial HD, feats, races). Edit it like any journal text page:
Destination:
Insert Destination Compendium here <- replace with a compendium id, or
"world.actors" for the Actors sidebar
User Extra Content:
system.content.stuff //Example Label <- format guide (always ignored); add
your own "pack.id //Label" lines under it
The shipped source list is Pathfinder 1e (pf1-bestiary + pf-content); swap the pack ids for your system's content and the macro follows the journal, not the code.
One gated eval per foe, with declared intent "write":
return await game.macros.getName("Claude Foe Forge").execute({
actorData: { name: "...", type: "npc", img: "...", system: { ... },
items: [ ... ], prototypeToken: { ... } }
});Returns { ok, uuid, name, destination, folder, items, warnings } on success, { ok:false, error, ... } on refusal. { action: "config" } returns the parsed source list, so Claude always knows what it may search.
- Duplicate refusal. A same-name actor at the destination refuses the forge unless
allowDuplicate: trueis passed, so a retried request can never double-create. - Mandatory icon coverage. A payload with a missing/default portrait or icon-less items is refused before anything is created - no art-less monsters to repair by hand (
allowIconless: trueis the deliberate override). - Hostile token defaults. Disposition, name/bar visibility, and an HP bar are filled wherever the payload left gaps; anything Claude (or a bestiary clone) supplies wins.
- Read-back verify. The macro re-reads the created actor before reporting success. Claude should still confirm with a separate read after the gate approves; a gated eval's own return value is never proof that a write landed.
- One foe per approval. Forge foes one gated eval at a time; long batch loops inside a single eval will hit the relay timeout.
Tested on Pathfinder 1e (straight clones, template applications, and vague open-ended briefs). The macro itself is system-agnostic: it validates against your world's own actor types and follows whatever source list your config journal carries.
The repair bay of the plug-in family: a paste-in world macro that fixes broken compendium links after a world migration, server transfer, or re-import. Tell Claude "repair the linkages" and it scans your packs for dead UUID references, works out which live compendium each dead pack became, proves the mapping with a dry run you approve, and only then rewrites the links. Built on the proven name-match core of two battle-tested repair macros, generalized to find links anywhere in a document - class associations, racial traits, description text, journal pages.
Source: plugins/ClaudeLinkReForge.js
- In Foundry, create a new Script macro named exactly
Claude Link ReForge. - Paste the contents of
plugins/ClaudeLinkReForge.jsinto it and save. - Click the macro once. The bare run shows a diagnostic (version, scan scope, receipt state). Bare runs never write.
scan -> every broken reference, grouped by dead pack id (read-only)
dryrun -> resolves them against a proposed mapping, reports
per-pair match rates, stores a receipt (approving = approving the MAPPING)
apply -> executes exactly the receipted dry run (approving = approving the WRITES)
Resolution is by preserved _id first, then by name (exact, then cleaned of suffixes like "(Ex)" or "at 5th level"). A low match rate means a wrong pack - the report says so, and apply should not follow.
One op per gated eval:
return await game.macros.getName("Claude Link ReForge").execute({ action: "scan" });
return await game.macros.getName("Claude Link ReForge").execute({
action: "dryrun", mapping: { "world.dead-pack": "world.live-pack" } });
return await game.macros.getName("Claude Link ReForge").execute({
action: "apply", mapping: { ... }, confirmHash: "lr-..." });Each op returns { ok, ... } with its report, or { ok:false, error } on refusal. Scan defaults to world compendiums; pass packs: [...] to include module-hosted ones.
- No dry run, no apply. Ever.
applyrefuses unless its job hashes to theconfirmHashof a dry-run receipt less than 30 minutes old. Change the mapping, the scan scope, or the skip rule and the hash breaks. - Keep and report, never guess. Unresolved links, malformed entries, and Bonus Feat associations are left untouched and listed for manual repair.
- Leaf-only rewrite. Only the UUID string itself changes; names, levels, and any custom fields on a link survive untouched. Provenance metadata (
_stats,flags) is never walked. - Time-boxed and re-runnable. Long repairs stop safely inside the gate's window; a re-run picks up where it left off, and already-fixed links drop out on their own.
- Verify after. Claude confirms with a fresh scan after the gate approves; a gated eval's own return value is never proof that a write landed.
Tested on Pathfinder 1e (an 89-link class/features relink after a full compendium migration). The macro itself is system-agnostic: it repairs whatever UUID references your documents actually carry, regardless of system schema.
A quirk worth knowing. Because Link ReForge walks whole documents rather than a single link field, it will sometimes find and repair flaws you didn't know a compendium had - stale references left behind by older migrations or hand edits, not just the breakage you pointed it at. It never does so uninvited: every repair shows up in the dry-run report first, and nothing is written without the gate's permission.
Character insurance for the whole table: a paste-in world macro that snapshots entire actors into self-contained "Backup Seed" items and rebuilds them later. Say "Claude, back up all PCs and NPC Bob" at the start of a session and every one of them gets a seed - stats, race, class levels, features, gear, images, biography. When a sheet gets corrupted, a migration goes sideways, or a player experiments a little too hard, the character comes back from the seed. Ported from a battle-tested backup macro and its embedded restore script, restore order and timing quirks intact.
Source: plugins/ClaudeTotalActorBackup.js
- In Foundry, create a new Script macro named exactly
Claude Total Actor Backup. - Paste the contents of
plugins/ClaudeTotalActorBackup.jsinto it and save. - Click the macro once. The bare run creates the storage folder below and shows a diagnostic. Bare runs never write seeds.
A "Claude Actor Backups" folder in the Items tab. Seeds are ordinary world items with timestamped names, so generations accumulate and the GM can inspect, rename, or hand one out without unlocking anything. prune keeps the newest N per actor and only ever touches this folder - seeds you park elsewhere are never deleted by the plug-in.
One op per gated eval:
return await game.macros.getName("Claude Total Actor Backup").execute({
action: "backup", actors: ["Syb", "Danger Dan"] });
...execute({ action: "list", actor: "Syb" });
...execute({ action: "restore", seed: "<uuid or seed name>", target: "<actor>" });
...execute({ action: "prune", actor: "Syb", keep: 5 });Each op returns { ok, ... } with its report, or { ok:false, error } on refusal.
Every seed carries its own on-use Restore Actor script. Drop a copy into an actor's inventory and use it: a confirmation dialog spells out the wipe, then the actor is rebuilt as the snapshotted character and the used copy consumes itself. The GM or the actor's owner may trigger it, so a busy GM can toss a seed to a player and keep running the game. The folder originals are the archive: Claude's restore op never consumes a seed, while handed-out copies are one-shot.
- Type match is absolute. A seed only restores onto an actor of its own type. There is no override flag, on either path.
- Blank targets only.
restorerefuses a target that has any items unlessallowNonEmpty:trueis passed, which wipes it first and is declared destructive (double confirm). The manual path's confirmation dialog is the same consent, human-shaped. - Definition, not state. Current HP, damage, conditions, and active effects are not captured - a seed is the character, not the moment. Restored characters come back at full HP.
- Spells are excluded (they restore as feats - a PF1e known issue). The backup report counts what was left out.
- Backup never deletes anything. Only the explicit
pruneop removes old seeds. - Verify after. Claude confirms with a separate read after the gate approves; a gated eval's own return value is never proof that a write landed.
Fair warning: more than any other part of AAGM, this plug-in is built exclusively for Pathfinder 1e. The restore sequence leans on PF1e's class/race child generation (add the parents, wait for the system to settle, strip its auto-generated defaults, then restore the character's real features), the spell exclusion is a PF1e workaround, and the manual mode rides PF1e item script calls. On other systems, expect nothing.
Want to build your own plug-in? All four plug-ins follow one contract - a world macro as the endpoint behind the gated eval. The bare essentials are in Docs/PLUGIN_API_ALPHA.md.
MIT - see LICENSE. Fork it, build on it, ship it; keep the copyright notice so the original stays credited.
Not affiliated with, endorsed by, or sponsored by Paizo Inc., Foundry Gaming LLC, or The Forge. Pathfinder is a trademark of Paizo Inc.; Foundry VTT and The Forge are trademarks of their respective owners. This repository ships no Paizo content - the PF1e integration talks to the community pf1 game system's API and your own world's data.

