One command. One file.

One command installs the sidecar and one file configures it. Free and open source under MIT, because anything that reads every query to your data should be code you can read too.

install on macOS
$ brew tap hoophq/brew https://github.com/hoophq/brew.git
$ brew install hoop
$ hoop start sidecar

One file, and it’s running.

Installing the binary is the short part. Your sidecar does nothing until you tell it what to sit in front of. The file sets one masking rule and one guardrail; here is what each control does.

Data Masking

Rewrites sensitive values in the response, in memory, before they reach the client. The request itself is never touched.

Data Masking, in full
Guardrails

An ordered deny list checked against every statement. Destructive ones never reach the database, and the client reads the reason you wrote.

Guardrails, in full
AI Analyzer

An agent scores every action’s intent and syntax for risk before it executes.

AI Analyzer, in full
Human in the Loop

Risky operations pause for a person’s one-off approval, then the agent carries on.

Human in the Loop, in full
config.yaml
log_level: info

admin:
  listen: 127.0.0.1:19000        # /healthz /stats /config /events

audit:
  file: "-"                      # JSON lines on stdout
  memory_buffer: 256             # last N events, readable at /events
  query_sessions: 500            # backs /api/sessions

pii:
  entities: [EMAIL_ADDRESS, US_SSN, CREDIT_CARD]

mask:                            # one Data Masking rule
  enabled: true
  rules:
    - {name: emails, entity: EMAIL_ADDRESS, strategy: redact}

policy:                          # one Guardrail
  enforce: true
  rules:
    - name: no-destructive-sql
      type: operation
      operations: [drop, delete, truncate]
      message: destructive statements are not permitted

listeners:
  - name: localdb
    protocol: postgres           # postgres | mssql | http
    listen: 127.0.0.1:15432      # where clients connect
    upstream: 127.0.0.1:5432     # your real resource
    connection: localdb
start
$ hoop start sidecar --config config.yaml
Point a client at 127.0.0.1:15432 instead of the database. Every statement it sends is checked against the rules above.

Watch the rules fire.

Your agents change one thing: the port in their connection string. Same client, same queries. The sidecar runs next to your database, not in place of it.

The query runs. The sensitive fields stay hidden.

Masking rewrites the response in memory. Swap redact for partial or hash and a masked column still joins.

The statement never reaches the database.

That is a real pgwire error carrying the message you wrote in the config. The agent reads why it was refused instead of guessing at a dropped connection.