tag-kit
Structured tagging primitives for human-in-the-loop annotation workflows.
@tag-kit/core (zero runtime deps) · @tag-kit/ui (headless React) · extracted from a real moderation app (inertial).GitHub
Install
- Install the packages
$ pnpm add @tag-kit/core @tag-kit/ui
Why it exists
Bring your own taxonomy, bring your own UI, bring your own scoring loop, tag-kit ships the substrate.
Most “tagging” features in HITL tools are unstructured strings: you type a label, it gets stored next to the decision, and then nobody can aggregate or score across them later.
Extracted from a real moderation app (inertial).
In depth
01
The unstructured-string problem
Most "tagging" features in human-in-the-loop tools are unstructured strings: an annotator types a label, it gets stored next to the decision, and nobody can aggregate or score across them later. That's fine for one-off review, and useless the moment you want measurement.
Real annotation is scoped. An annotator needs to say "the audio at 0:12–0:24 is harassment; the video is fine", not render one whole-asset verdict. And real quality measurement is agreement: when two reviewers tag overlapping segments with the same label, that's agreement; when they tag disjoint ones, it isn't. Neither works on strings.
tag-kit is what falls out when you take the tag layer out of a real moderation app, inertial, and ask: what's the smallest reusable shape for this? Bring your own taxonomy, bring your own UI, bring your own scoring loop; tag-kit ships the substrate.
02
Conservative by construction
The scoring core is deliberately cautious. Scope overlap follows conservative rules: different modality never matches, different asset never matches, and ranges must genuinely overlap, half-open intervals, so segments that merely touch don't count. Each expected tag is consumed at most once when computing precision and recall, which prevents double-counting a single ground-truth item against multiple reviewer tags. Per-tag precision, recall, and F1 aggregate across entities from there.
Tag IDs are stable by convention, once a tagId ships in any catalog it never gets renamed, because it's the foreign key from persisted reviewer tags to your taxonomy. That's what lets tags survive UI rewrites and feed longitudinal scoring.
The portability test for every API decision: does this still work for medical chart annotation, legal document review, and ML training-data labeling, not just content moderation? If a change only makes sense for one domain, it doesn't land.
03
Zero dependencies, zero styles
@tag-kit/core has zero runtime dependencies: no Zod, no lodash, nothing. It is a TypeScript-only set of wire shapes and pure functions, which means it drops into any stack, any bundler, any runtime, with no version-conflict surface at all.
@tag-kit/ui is headless React: a catalog-browsing TagPicker and a TagChip, shipping zero CSS. Styling hooks are data-tag-kit-* attributes; markup override is a children render-prop. Your design system stays yours. The primitives only bring behavior.
Signature features
Per-modality scoping
The audio at 0:12–0:24 is harassment; the video is fine.
Scope-aware agreement scoring
Agreement scored per scope, not flattened across the whole item.
Stable taxonomy IDs
Stable taxonomy IDs so tags aggregate and score across decisions.
Domain portability
Moderation, medical chart annotation, legal review, ML labeling.
Packages
Explore further
The source lives on GitHub. Copy, paste, own. No fork, no vendor lock-in.
The other projects
all projectsHITL Kit
Twenty React primitives for the moment an agent hands control to a person: interrupts, approvals, evidence, and provenance.
MeasurementDeployed at hitlkit.dev · every primitive installs individually via the shadcn CLI · copy, paste, own.
eval-kit
Scores whether your agent respects human authority: stops when it must, asks when it should, never averaged into one number.
MeasurementThe gates release · mandated compliance and discretionary precision/recall scored from the trace, never averaged · three reference suites · four adapters (anthropic, openai, http, mock) · file-based, single-user, not a hosted service.
Collapse
A Claude Code skill-building framework: lessons, notebooks and docs compile into skills and MCP tools, linted and written atomically.
ToolingActive development. Shipped: MDX ingestor with 21 cross-stack reference lessons, notebook ingestor with admonition auto-prefill, template engine with cross-language equivalents + trigger-phrase derivation, atomic persistence, three-tier skill quality linter, and MCP server scaffold generation. One annotation can now become a skill or a working MCP tool.
Hologram
Live observability for Blender → glTF pipelines: an append-only log, a dashboard beside the assets, and an MCP surface for the agent.
ToolingOn PyPI as hologram-gltf · Python 3.10+ · MIT.