Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Files on disk

Red Clippy keeps two things outside the process: a SQLite database and a storage directory. Everything else is in the binary.

The database

The database is red-clippy.db in the working directory by default, or wherever database_url points.

SQLite runs in WAL mode, so you will see three files:

red-clippy.db
red-clippy.db-wal
red-clippy.db-shm

All three belong together. Copying only the .db while the server is running gives you a database missing the most recent writes.

The storage directory

The storage directory is ./red-clippy-storage by default, or wherever storage_root points. It is created at startup if missing.

red-clippy-storage/
  org_northwind/
    pentest_PT-2026-Q3-NORTHWIND/
      findings/
        2/
          9a9344b81c8e1bfb44740ab09b23d933
          aa26c30965cbc9533cf47261680b8c4e
      data/
        notes/checkout-flow.md
        scans/northwind-perimeter.xml
        scans/subfinder-northwind.txt
        screenshots/evidence.png

Each engagement has two buckets, and they name files differently.

findings/<finding_id>/ holds evidence attachments. Names are server-generated random hex, so the original filename never touches disk and a storage key lifted from an old database dump cannot be replayed against a running server. The real filename, MIME type and caption live in the database.

data/ is the operator file area, the one behind the Files tab. It keeps the names you gave things, so the Files tab is a faithful view of what is on disk. Every path segment is validated, and nothing user-supplied can resolve outside the engagement’s own data/ root.

Asset file areas are a slice of the same data/ tree, so a file written through an asset’s Files tab is visible from the engagement’s Files tab too.

Backing up

With the server stopped, copy the database file (all three parts) and the storage directory. That is the whole state.

With the server running, use SQLite’s own backup so you get a consistent snapshot:

sqlite3 red-clippy.db ".backup 'backup/red-clippy.db'"
cp -a red-clippy-storage backup/

Deletion behaviour

Deleting a record and deleting its files are deliberately separate actions.

Deleting an organization in the panel removes every database row inside it and leaves the files under org_<slug>/ alone. Deleting an asset removes its observations and check results but keeps findings tagged against it.

In both cases a destructive action removes the index, not the artefacts. If you want the files gone, remove the directory yourself.

Path derivation

org_<slug> and pentest_<code> are derived from the slug and the code, which is why both are immutable after creation. Both are re-validated every time a path is built, so even a tampered database row cannot produce a path that escapes the storage root.

This means one engagement’s artefacts are one directory. Archiving an engagement is tar czf. Handing over a client’s files is copying org_<slug>/.