> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.hoop.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Runtime control for AI Agents

> A protocol-aware reverse proxy between AI and everything it can touch.

export const HeroAnimation = () => {
  const QUERY = 'SELECT * FROM customers LIMIT 4;';
  const ROWS = [{
    id: 1001,
    name: 'J. Smith',
    ssn: '123-45-6789',
    email: 'jsmith@acme.com'
  }, {
    id: 1002,
    name: 'M. Rodriguez',
    ssn: '234-56-7890',
    email: 'mrodriguez@acme.com'
  }, {
    id: 1003,
    name: 'A. Chen',
    ssn: '345-67-8901',
    email: 'achen@acme.com'
  }, {
    id: 1004,
    name: 'S. Patel',
    ssn: '456-78-9012',
    email: 'spatel@acme.com'
  }];
  const [cycle, setCycle] = useState(0);
  const [typedLen, setTypedLen] = useState(0);
  const [visibleRows, setVisibleRows] = useState(0);
  const [phase, setPhase] = useState('typing');
  const timers = useRef([]);
  function T(fn, delay) {
    const id = setTimeout(fn, delay);
    timers.current.push(id);
  }
  useEffect(() => {
    timers.current.forEach(clearTimeout);
    timers.current = [];
    setTypedLen(0);
    setVisibleRows(0);
    setPhase('typing');
    let t = 0;
    for (let i = 1; i <= QUERY.length; i++) {
      t += 38;
      const ci = i;
      T(() => setTypedLen(ci), t);
    }
    t += 350;
    for (let r = 1; r <= ROWS.length; r++) {
      const cr = r;
      T(() => setVisibleRows(cr), t);
      t += 95;
    }
    t += 900;
    T(() => setPhase('flashing'), t);
    t += 480;
    T(() => setPhase('masked'), t);
    t += 3200;
    T(() => setPhase('resetting'), t);
    t += 550;
    T(() => setCycle(c => c + 1), t);
    return () => timers.current.forEach(clearTimeout);
  }, [cycle]);
  const isMasked = phase === 'masked';
  const isFlashing = phase === 'flashing';
  const isResetting = phase === 'resetting';
  const showRows = phase !== 'typing' && phase !== 'resetting';
  return <div className="ha-root" aria-hidden="true">
      <div className={`mock-container ha-mock${isResetting ? ' ha-fadeout' : ''}`}>

        {}
        <div className="mock-toolbar" style={{
    justifyContent: 'space-between'
  }}>
          <div style={{
    display: 'flex',
    gap: 6
  }}>
            <div className="mock-dot" />
            <div className="mock-dot" />
            <div className="mock-dot" />
          </div>
          <span className="ha-wintitle">hoop — postgres:prod</span>
          <span style={{
    width: 48
  }} />
        </div>

        {}
        <div className="ha-querybar">
          <span className="ha-prompt">psql&gt; </span>
          <span className="ha-querytext">{QUERY.slice(0, typedLen)}</span>
          {!isMasked && !isResetting && <span className="ha-cursor" />}
        </div>

        {}
        <div className="ha-tablewrap">
          <table className="ha-table">
            <thead>
              <tr>
                <th className="ha-th">id</th>
                <th className="ha-th">name</th>
                <th className="ha-th">ssn</th>
                <th className="ha-th">email</th>
              </tr>
            </thead>
            <tbody>
              {ROWS.map((row, i) => <tr key={row.id} className="ha-tr" style={{
    opacity: showRows && i < visibleRows ? 1 : 0,
    transition: 'opacity 0.2s ease'
  }}>
                  <td className="ha-td ha-dim">{row.id}</td>
                  <td className="ha-td ha-bright">{row.name}</td>
                  <td className={`ha-td ha-sensitive${isFlashing ? ' ha-flash' : ''}${isMasked ? ' ha-masked' : ''}`}>
                    {isMasked ? `***-**-${row.ssn.slice(-4)}` : row.ssn}
                  </td>
                  <td className={`ha-td ha-sensitive${isFlashing ? ' ha-flash' : ''}${isMasked ? ' ha-masked' : ''}`}>
                    {isMasked ? '****@****.com' : row.email}
                  </td>
                </tr>)}
            </tbody>
          </table>
        </div>

        {}
        <div className={`ha-notice${isMasked ? ' ha-notice-visible' : ''}`}>
          <span className="ha-notice-dot" />
          <span>2 columns masked · SSN · email</span>
        </div>

      </div>

      <style>{`
        .ha-root {
          position: relative;
          width: 100%;
          max-width: 540px;
        }

        .ha-mock {
          border-radius: 12px;
          overflow: hidden;
          transition: opacity 0.4s ease;
        }

        .ha-fadeout {
          opacity: 0;
        }

        .ha-wintitle {
          font-family: var(--mono);
          font-size: 11px;
          color: rgba(var(--sand-100-rgb), 0.2);
        }

        /* Query bar */
        .ha-querybar {
          display: flex;
          align-items: center;
          padding: 9px 16px;
          background: rgba(var(--sand-100-rgb), 0.03);
          border-top: 1px solid rgba(var(--sand-100-rgb), 0.06);
          border-bottom: 1px solid rgba(var(--sand-100-rgb), 0.06);
          min-height: 38px;
        }

        .ha-prompt {
          font-family: var(--mono);
          font-size: 12px;
          color: rgba(var(--warm-gold-rgb), 0.7);
          flex-shrink: 0;
        }

        .ha-querytext {
          font-family: var(--mono);
          font-size: 12px;
          color: rgba(var(--sand-100-rgb), 0.7);
        }

        .ha-cursor {
          display: inline-block;
          width: 6px;
          height: 13px;
          background: rgba(var(--sand-100-rgb), 0.5);
          margin-left: 1px;
          vertical-align: middle;
          animation: ha-blink 1s step-end infinite;
        }

        @keyframes ha-blink {
          0%, 100% { opacity: 1; }
          50%       { opacity: 0; }
        }

        /* Table */
        .ha-tablewrap {
          overflow-x: auto;
          padding-bottom: 4px;
        }

        .ha-table {
          width: 100%;
          border-collapse: collapse;
          font-family: var(--mono);
          font-size: 12px;
        }

        .ha-th {
          text-align: left;
          padding: 7px 16px;
          color: rgba(var(--sand-100-rgb), 0.25);
          font-size: 10px;
          font-weight: 500;
          text-transform: uppercase;
          letter-spacing: 0.06em;
          border-bottom: 1px solid rgba(var(--sand-100-rgb), 0.04);
        }

        .ha-tr:not(:last-child) td {
          border-bottom: 1px solid rgba(var(--sand-100-rgb), 0.04);
        }

        .ha-td {
          padding: 7px 16px;
          transition: color 0.25s ease, background 0.25s ease;
        }

        .ha-dim       { color: rgba(var(--sand-100-rgb), 0.3);  }
        .ha-bright    { color: rgba(var(--sand-100-rgb), 0.6);  }
        .ha-sensitive { color: rgba(var(--sand-100-rgb), 0.5);  }

        .ha-flash {
          color: var(--warm-gold) !important;
          background: rgba(var(--warm-gold-rgb), 0.1);
        }

        .ha-masked {
          color: var(--warm-gold) !important;
          font-weight: 600;
        }

        /* Masking notice */
        .ha-notice {
          display: flex;
          align-items: center;
          gap: 7px;
          padding: 8px 16px;
          border-top: 1px solid rgba(var(--sand-100-rgb), 0.06);
          font-family: var(--sans);
          font-size: 11px;
          color: rgba(var(--warm-gold-rgb), 0.75);
          opacity: 0;
          transform: translateY(4px);
          transition: opacity 0.3s ease, transform 0.3s ease;
        }

        .ha-notice-visible {
          opacity: 1;
          transform: translateY(0);
        }

        .ha-notice-dot {
          width: 6px;
          height: 6px;
          border-radius: 50%;
          background: var(--warm-gold);
          flex-shrink: 0;
        }
      `}</style>
    </div>;
};

<div style={{background: 'linear-gradient(135deg, #111111 0%, #1A1A1A 35%, #2A2A2A 70%, #3A3A3A 100%)', borderRadius: 14, overflow: 'hidden', padding: 24, height: 350}}>
  <HeroAnimation />
</div>

Hoop is a reverse proxy that reads the protocol it carries. Every query, every result set, every API call passes through it, and Hoop decides what gets through. **It adds less than 10ms to the round trip.**

Most proxies see bytes. Hoop sees statements. It speaks Postgres, ClickHouse, SQL Server, HTTP and more, right on the wire ([see all protocols](/docs/setup/configuration/hoop-sidecar/protocols/postgres)). So it knows a `DELETE` with no `WHERE` from a harmless `SELECT`. It blocks the first, masks the emails in the second, and records both. Your clients stay the same. Your credentials stay where they are.

**Start with one Sidecar.** One binary and one config file, running next to the resource it protects.

**Grow into a fleet.** When one Sidecar becomes fifty, the Control Plane pushes your rules to all of them from one place. It ships with Hoop Enterprise.

***

## Install the Sidecar

The Sidecar ships in the `hoop` CLI: one binary, no external dependency. See [Install the CLI](/docs/install/cli) for macOS, Linux, Windows, WSL and manual installs.

***

## Next step

Install the Sidecar and get it running. Pick the path that fits how you deploy.

<CardGroup cols={3}>
  <Card title="Command Line" icon="terminal" href="/docs/install/cli">
    Install the `hoop` binary on macOS, Linux, Windows or WSL, then run the Sidecar directly.

    <br />

    **Start here** <Icon icon="arrow-right" />
  </Card>

  <Card title="Container Images" icon="box" href="/docs/install/container-images">
    The official `hoophq/hoopsidecar` image, in a default and a distroless flavour.
  </Card>

  <Card title="Kubernetes" icon="dharmachakra" href="/docs/install/kubernetes">
    A Helm chart, including running it as a native Kubernetes sidecar container.
  </Card>
</CardGroup>

***

## Core Concepts

<CardGroup cols={2}>
  <Card title="Sidecar" icon="bolt" href="/docs/core-concepts/sidecar">
    The engine. A proxy beside your resource that reads the wire protocol and decides what gets through. No external dependency.

    <br />

    **Learn more** <Icon icon="arrow-right" />
  </Card>

  <Card title="Control Plane" icon="tower-control" href="/docs/core-concepts/control-plane">
    One place to run every Sidecar. Change a rule once and the whole fleet enforces it. Part of Hoop Enterprise.

    <br />

    **Learn more** <Icon icon="arrow-right" />
  </Card>
</CardGroup>

***

## Features

Two ways a request can travel through the Sidecar, and two controls that apply on either path.

<CardGroup cols={2}>
  <Card title="Direct Access" icon="arrow-right-long" href="/docs/features/direct-access">
    The straight-through path. Guardrails and Data Masking apply inline, deterministically, with no model call and no third party in the chain.

    <br />

    **Learn more** <Icon icon="arrow-right" />
  </Card>

  <Card title="Agentic Access" icon="robot" href="/docs/features/agentic-access">
    The AI Analyzer classifies the statement and the risk level picks a tool: block, allow, review, apply a guardrail, or mask the response.

    <br />

    **Learn more** <Icon icon="arrow-right" />
  </Card>

  <Card title="Data Masking" icon="mask" href="/docs/features/data-masking">
    Rewrite sensitive values in the response, in memory, before they reach the client. Requests are never touched.

    <br />

    **Learn more** <Icon icon="arrow-right" />
  </Card>

  <Card title="Guardrails" icon="shield-halved" href="/docs/features/guardrails">
    An ordered deny list evaluated against every statement, refusing what should never run with a message you wrote.

    <br />

    **Learn more** <Icon icon="arrow-right" />
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.