Swapit
Broomva agent-skills monorepo — 48 Tier-2 skills compatible with Claude Code, Codex, Cursor, Gemini CLI, Goose, Copilot. Layout follows anthropics/skills (agentskills.io spec). Install: npx skills add broomva/skills --skill <name>.
npx -y skills add broomva/skills --skill swapitAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 3 stars3 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Stateful, local-first household toxics inventory + swap engine. Identify the items in a home that carry endocrine disruptors and persistent chemicals (BPA/BPS, phthalates, PFAS/PTFE, parabens, flame retardants, VOCs, microplastics), score each by *real* exposure (severity x presence x how it's used x condition), and track the swap to a safer alternative from "flagged" -> "sourced" -> "swapped". Ships a grounded, cited knowledge graph of ~20 hazards, ~40 item-classes, and ~40 alternatives. Hands sourcing off to the `procurer` skill. The skill's state is the source of truth — the agent is the app.
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
13.4 KB, as published. Nobody here has run it
swapit — household toxics inventory + swap engine
What this skill is
swapit turns a vague worry ("there's probably a lot of plastic and BPA in my house") into
a concrete, prioritized, trackable plan. It is stateful: your household inventory lives on
disk and persists across sessions. It is local-first: zero paid services, nothing leaves your
device unless you explicitly opt into the (M3) commons.
One pass produces:
- An inventory of the items you own, each tagged with its generic item-class.
- A risk score per item that reflects actual exposure — a scratched non-stick pan used daily at high heat ranks far above an unopened plastic bin in the garage.
- A ranked "swap-first" list — the 5% of changes that cut the most exposure.
- Swap tracking — chosen alternative, procurement status, checklist, bookmarks.
- A shareable HTML report (and, in M2, a live dashboard at
swapit serve).
The three realms (and the privacy invariant)
| Realm | What it holds | Sharing |
|---|---|---|
| 1 · Knowledge | hazards → item-classes → alternatives (generic, cited facts) | shareable; cached + (M3) commons-synced |
| 2 · Inventory | your items, rooms, quantities, brands, photos, swaps, bookmarks | PRIVATE — never leaves the device |
| 3 · Commons (M3) | anonymized contributions enriching the shared knowledge graph | opt-in, reviewed, generic facts only |
Privacy invariant (binding): Realm-2 inventory (items, rooms, quantities, brands, photos, purchase info, location) never crosses the sync boundary. Only Realm-1 generic facts are shareable, via explicit opt-in + a reviewable
swapit sync --dry-run. Enforced by an allowlist serializer (scripts/anonymize.py) on the client and a backstop on the commons server, plus fuzz tests asserting every real inventory item is rejected by the gate. Forbidden-field list:anonymize.CONTRIBUTION_FORBIDDEN(the inventory-structural subset ofstate.PRIVATE_FIELDS).
Data model
State lives at ~/.config/swapit/ (override with $SWAPIT_HOME; honors $XDG_CONFIG_HOME).
~/.config/swapit/
├── knowledge/ hazards.jsonl · item-classes.jsonl · alternatives.jsonl · products.jsonl · procurement.jsonl
├── inventory/ events.jsonl(append-only audit) · items.json · swaps.json · rooms.json · bookmarks.json
├── contributions/ queue.jsonl (M3)
├── sync/ config.json · sync-log.jsonl (M3)
└── photos/
Node schemas (see seed/*.jsonl for the full, cited dataset):
- hazard —
id · name · aliases · class · mechanism · exposure_routes · regulatory · severity(0-3) · evidence_strength · sources - item_class —
id · name · category · description · hazards[]{hazard_id, presence_likelihood, rationale} · detection_hints · sources - alternative —
id · name · replaces[] · material · rationale · tradeoffs · caveats · avoids_hazards · residual_concerns · sources - procurement_option (where-to-buy, public) —
id · alternative · item_class · retailer · region(ISO-3166-1 a2) · area · url · price_min · price_max · currency · as_of · availability · confidence · corroboration_count - item (private) —
id · name · item_class · room · quantity · brand · condition · usage{frequency, food_contact, heat, child_contact} · status · notes · photos - swap (private) —
id · item_id · chosen_alternative · procurement{status, cost, vendor} · checklist[] · bookmarks[]
Risk model
risk = severity × presence_likelihood × evidence × exposure_relevance × frequency × condition
- exposure_relevance activates a hazard's route against how the item is used (food-contact + heat maxes out an ingestion/food-contact-heat hazard; dermal matters for personal care; inhalation for cleaning/furniture; child-contact amplifies).
- Item score = scaled sum of per-hazard risk → band high / medium / low.
- This is the prioritization intelligence — the analogue of procurer's "dominant failure mode": fix the few items that drive most of the exposure first, not a guilt list of everything plastic.
Modes
| Mode | What it does |
|---|---|
init | create state + load the seed knowledge graph |
add | add a household item (name, class, room, condition, usage) → prints its assessment |
assess | assess an item or an ad-hoc item-class → hazards + risk + ranked alternatives |
list | list inventory, filter by --room/--band/--status/--class/--hazard, sort by risk |
swap | create/update a swap plan: choose alternative, set status, checklist, bookmark, cost |
score | household exposure summary + the swap-first ranking |
report | generate the self-contained HTML report (Category-C) |
procure | procurer handoff brief + known where-to-buy offers for the swap target (filter by --region); record a found offer (--retailer/--url/--price-*) to the public commons |
knowledge | browse/search the knowledge graph (list/search/show) |
rooms | list/add rooms |
selfheal | validate knowledge edges + inventory refs + grounding; exit non-zero on errors |
serve | live local dashboard at http://127.0.0.1:8731 — kanban board, checklist, bookmarks, status; every click writes back to state |
contribute | queue an anonymized fact — product / hazard (item-class→hazard) / alternative / procurement (public where-to-buy offer) / item-class (new taxonomy node); applied locally + gated for the commons |
sync | push the contribution queue + pull community knowledge (opt-in); --dry-run previews exactly what would be sent; --configure sets the endpoint |
Typical flow
swapit init
swapit add --name "Old Teflon pan" --class nonstick-cookware --room kitchen \
--condition scratched --frequency daily --food-contact --heat
swapit score # what to swap first
swapit swap itm_xxxx --to cast-iron-skillet --status sourcing --add-task "buy 10in skillet"
swapit procure itm_xxxx # -> hand the brief to the `procurer` skill
swapit report --open # shareable HTML
Compounding with other skills
procurer—swapit procure <item>builds the need ("replace 3 polycarbonate bottles with glass/steel") and the ready procurer prompt; procurer returns cited sources + a budget envelope.bookkeeping(P6) — a novel, durable hazard/product finding (e.g. a newly characterized item-class) is filed proactively intoresearch/entities/and can later flow to the commons.health— personal exposure context.content-creation— educational posts from the graph.
Grounding discipline
The seed knowledge cites only authoritative bodies (NIEHS, ATSDR/CDC, US EPA, US FDA, ECHA/EU REACH,
CA OEHHA Prop 65, WHO, EWG). Every record carries ≥1 source; verified: false marks these as
reference-grade (not freshly fetched) — run a sourced pass (or the commons) to refresh. selfheal
fails if any node loses its citation. This is consumer guidance grounded in public-health science,
not medical or legal advice.
Resources
scripts/swapit.py— CLI entrypoint + command handlersscripts/state.py— two-realm state layer (PRIVATE_FIELDSdefines the sync boundary)scripts/ops.py— the single state-mutation write path (shared by CLI + dashboard)scripts/knowledge.py— knowledge graph load + edge resolutionscripts/risk.py— exposure-risk scoring enginescripts/report.py— self-contained HTML report generator (Category-C)scripts/server.py—swapit servelive dashboard (stdlib http.server, localhost-only)scripts/anonymize.py— the privacy gate: allowlist fact builders + the forbidden-field scanscripts/sync.py— commons sync client (queue,--dry-runpreview, push/pull, merge)scripts/selfheal.py— integrity validatortemplates/dashboard.html— the live dashboard (inline CSS/JS, Category-C)commons/— the networked commons reference server (FastAPI + SQLite; deploy gated)seed/{hazards,item-classes,alternatives}.jsonl— grounded starter knowledgetests/— risk, knowledge, self-heal, CLI, privacy/anonymize, sync, report, and server tests
Collaboration (the commons)
Contributions are generic facts only — swapit contribute product|hazard|alternative|procurement|item-class
builds an anonymized fact (a public product→item-class mapping, a hazard-edge correction, an
alternative, a where-to-buy offer, or a new taxonomy node), applies it locally, and queues it.
swapit sync --dry-run shows exactly what would be sent; swapit sync pushes the queue and pulls
community knowledge (opt-in, after --configure). Identical facts from different users corroborate
(content-addressed) rather than duplicate; the commons serves a fact once two distinct contributors
corroborate it (corroboration >= 2) — moderation is corroboration-gated, not confidence-gated,
because confidence is caller-supplied and a lone submitter could otherwise self-approve. The privacy
invariant is enforced on both sides (client anonymize gate + server backstop) — inventory never crosses.
Where-to-buy (procurement) commons
A procurement_option fact is a public offer: a safer alternative sold by a retailer in a
region (ISO-3166-1 alpha-2), with optional url, price_min/price_max + currency + as_of,
area, and availability. It is content-addressed on (alternative, retailer, region) — the
same offer corroborates across users; a different region is a different fact (the geographic scale
axis). Price/url/area are refinable market data: a corroboration with a strictly newer as_of
freshens the price forward, never regressing fresher data. The privacy seam is sharp — the public
offer uses retailer + price_* and never the private vendor/cost (where you bought and
what you paid stay in Realm 2). swapit procure <item> --region <CC> surfaces known offers and
records new ones you find — growing an open, detailed, geo-scoped dataset anyone can use.
Roadmap
- M1 (shipped, 0.1.0) — data model, seed knowledge, CLI, risk engine, static HTML report, self-heal.
- M2 (shipped, 0.2.0) —
swapit serve: live local dashboard with read/write back to state. - M3 (0.3.0) — anonymized collaboration + networked commons (
commons/, FastAPI + SQLite). Privacy invariant enforced by allowlist serialization + fuzz tests on both client and server. - M4 (this release, 0.4.0) — geo-scaled procurement commons + taxonomy growth: the
procurement_option(public where-to-buy, keyed by(alternative, retailer, region), forward-only price freshening) anditem_class(corroboration-gated taxonomy growth) fact kinds;procuresurfaces + records offers; seed offers across US/CO/DE/GB; cross-language hash parity locked by pinned vectors. Live deploy to broomva.tech infra is gated on explicit go (creds/DNS); the skill is fully functional offline without it.