Skip to main content
Entire writes AI session transcripts and checkpoint metadata into your own Git repository, and redacts them before each write. This page covers the trust boundaries, every location Entire writes to or transmits, and which redaction layers cover each one.
We verified the behavior on this page against Entire CLI 0.10.2, except for secret scanner selection, which first appears in v0.10.3-nightly.202608210613.680d64782. Run entire version to check what you have installed. To configure any of it, see Privacy and Redaction and Session Storage; this page describes behavior, those pages hold the settings keys.

Where Your Data Lives

Checkpoints live in your Git repository, not in a service Entire controls. Which Git objects hold them depends on the storage backend. Both backends store checkpoint data in the same repository as your code unless you configure a separate checkpoint repository. To see or change which backend a repository uses, read checkpoints.primary.type in .entire/settings.json or pass --checkpoint-backend to entire configure. Anyone with access to your repository can read the checkpoints in it. If your repository is public, so are they.
Treat redaction as a safety net rather than a guarantee. For customer data, internal credentials, or regulated material, use a private repository.

Reporting a Vulnerability

Please do not open a public GitHub issue for a security vulnerability.

Email [email protected]

Report security vulnerabilities directly. We acknowledge within 48 hours and aim to resolve criticals within 90 days. Full disclosure policy below.
Entire is a local development tool that writes to your repository. The protections here assume an attacker who reads your repository, not one who already controls your machine.What redaction is for. It reduces the chance that a credential or a piece of personal data that entered an agent conversation gets committed and pushed. It runs on transcript and metadata content before Entire writes it to a Git object.What redaction does not do:
  • It does not protect a repository from the people who can read it. Anyone with read access reads every checkpoint in it.
  • It does not scan your source code. Redaction covers what Entire writes, not what you commit. A hardcoded secret in a tracked file reaches the remote through your own commit.
  • It does not defend against a compromised machine. An attacker running code as you can read the raw agent transcripts, your Git credentials, and everything under .entire/ before redaction runs.
  • It does not catch every secret. Detection is pattern- and entropy-based. See Limitations of Redaction below.
Who can read what:Entire does not operate a service that receives your transcripts. Checkpoints travel to the Git remotes you push to.
Checkpoint storage holds metadata, not source code. A checkpoint carries prompt.txt, full.jsonl, transcript.jsonl, metadata.json, checkpoint.json, and an optional assets/ subtree. Metadata records the paths a session touched, in files_touched, and not their contents.Shadow branches hold unredacted source. Shadow branches are the one place Entire writes your source files rather than metadata. Metadata written to a shadow branch goes through the same redaction pipeline as a committed checkpoint, but code-file snapshots are raw blobs of your working tree, so a hardcoded secret in a tracked file appears in them verbatim. Gitignored files such as .env are filtered out of those snapshots as a partial defense. Entire does not push shadow branches and deletes them after a successful push once the session ends cleanly. Do not push one manually.Two redaction passes for metadata. Entire redacts metadata on the shadow-branch write and again at condensation time, when the session rolls into checkpoint storage. The metadata that lands in checkpoint storage, local or pushed, has been through redaction.RedactedBytes type guarantee. The redact package returns a typed wrapper, and the checkpoint stores accept only that type. A code path that tried to write unredacted transcript bytes would fail to compile rather than fail at runtime.Commit trailers. Entire adds one trailer to your own commits:
The value is a checkpoint ID, either a 12-character hex string or a 26-character ULID. It carries no prompt content and no file content. A ULID encodes the millisecond Entire created the checkpoint, so the trailer discloses commit timing to anyone who can read the commit message. The trailer stays in your history after you push, and you can delete the line before committing if you do not want the commit linked.Remote URL redaction in logs. When a fetch or push fails, error messages and .entire/logs/ entries strip passwords from URLs, for example https://user:****@github.com, so credentials stay out of local log files.
Redaction covers the content Entire writes into checkpoint storage. It does not cover everything Entire touches.
Nine layers run in this order. Layers 1 through 8 use regexes, entropy scoring, or structural validation during condensation. Layer 9 calls a local model at push time.
CLI 0.10.2 uses Betterleaks for layer 2. Scanner selection first appears in v0.10.3-nightly.202608210613.680d64782.
Layers 1, 3, 4, 5, and 7 run on every checkpoint write and have no setting that turns them off. Layer 2 always runs at least one scanner. Layers 6, 8, and 9 run only when you configure them.Secret scanner engines. Betterleaks runs by default and provides broader format coverage. goredact is off by default and uses validators such as token length or checksum checks to improve precision. You can run either engine or both.Entire reads scanner selection only from the committed .entire/settings.json file. It ignores scanner keys in .entire/settings.local.json and logs a warning because scanner choice changes the checkpoint content shared with everyone who reads the repository history.Entire refuses to load settings when both scanners are off. If goredact is the only active scanner and it fails during a scan, Entire stops the checkpoint write. If Betterleaks is also active, Entire completes the write with Betterleaks coverage. See Secret Scanner Engines for configuration.Avoiding over-redaction. Entire skips fields where a match is more likely to be noise than a secret: fields named signature, keys ending in id or ids, structural path fields (filepath, file_path, cwd, root, directory, dir, and path), and objects whose type starts with image or equals base64.It also leaves placeholders alone. Entire matches placeholders exactly (changeme, example, placeholder, your_password, your_secret, and prior REDACTED markers) and by shape: shell expansions such as ${DB_PASSWORD}, bracketed names such as <password>, and mask runs of three or more *, x, ., or -. A connection string whose password is a placeholder survives intact.These skips trade detection coverage for a lower false-positive rate. A secret parked in a path field or inside a base64 blob is not redacted.
User-defined rules add a regex layer for strings the built-in detectors do not know: internal token formats, project codenames, customer names, or any other pattern you would rather keep out of session archives.Rules use Go RE2 syntax, so lookarounds and backreferences are unavailable. Matches become the bare REDACTED token. Labels serve diagnostics only.You can supply rules two ways, both configured in Privacy and Redaction:
  • Inline rules under redaction.custom_redactions, for a handful of patterns.
  • Rule packs, YAML or JSON files under .entire/redactors/, for reusable sets. A pack declares name matching its filename stem, a version, and one or more rules, each with an id and a regex.
Self-tests. A rule may declare samples with { input, redacted } expectations. Entire checks them when it loads the pack and logs a warning on a mismatch, which catches typos without disabling the rule. Entire logs an invalid regex and skips that rule rather than crashing the redactor.When rules take effect. On the next CLI or hook invocation. No reload command exists.Personal rules. Put packs you do not want to share under .entire/redactors/local/, which entire enable keeps gitignored, so a codename or a customer reference does not become shared repository configuration.
PII redaction runs as layer 8, in addition to secret detection. It is off by default.Email allowlist. Bot and CI addresses stay readable, because they appear in nearly every transcript and identify no one: noreply@*, actions@*, *@users.noreply.github.com, and *@noreply.github.com.Custom patterns. You can add your own patterns under custom_patterns, where the label becomes part of the token. A pattern named employee_id produces [REDACTED_EMPLOYEE_ID].A custom pattern that reveals an internal ID format is itself sensitive. Put those in .entire/settings.local.json, which stays out of Git, rather than in the committed .entire/settings.json. See PII redaction for the settings.
The OpenAI Privacy Filter (opf) is a 1.5B-parameter token-classification model that finds names, addresses, account numbers, and other personal data the regex layers miss. It runs as layer 9, and it is off by default.
OPF applies to the branch backend. The pre-push rewrite operates on entire/checkpoints/v1. Repositories on the ref-based backend, which is the default for repositories enabled with CLI 0.10.0 or later, push checkpoints without the OPF pass. Check checkpoints.primary.type before relying on OPF.
When it runs. OPF runs at push time, not at commit time. Local commits stay on the eight regex layers, so per-commit latency is unchanged. During git push, the pre-push hook re-reads each unpushed checkpoint commit, runs the model over its content, and writes new commits carrying an Entire-OPF-Applied: true trailer. The local ref fast-forwards to the rewritten tip, and those commits are what reach the remote. The original commits become unreachable and are swept by git gc.Two consequences follow. The remote sees only OPF-redacted content once OPF is enabled, and local-only commits carry eight-layer redaction until the moment you push. If you never push, OPF never runs.The pre-push prompt. When OPF is enabled and your terminal is interactive, the hook asks before running:
Yes runs OPF for this push. No skips it, and the eight-layer content reaches the remote. Always runs OPF and writes prompt_default: "always" to .entire/settings.local.json so later pushes stop asking. Ctrl-C aborts the push, and no refs reach the remote.Without a TTY, which covers CI and scripted pushes, Entire skips the prompt and runs OPF, printing a progress line to stderr so the wait is visible.The ENTIRE_OPF override. ENTIRE_OPF beats both the setting and the prompt, for a single push. The decision resolves in this order: ENTIRE_OPF, then prompt_default in settings, then the prompt, then the non-interactive default of running.
ENTIRE_OPF=no skips OPF for that push. ENTIRE_OPF=yes runs it without asking. Use no when CI pushes from a machine with no opf installed, or for a one-off push while you fix a broken install.Failures abort the push. If opf is missing from $PATH, fails to start, or times out, the rewrite aborts the push with OPF runtime failed; aborting push. Nothing reaches the remote. Enabling OPF states that you do not want unredacted content leaving the machine, so falling back to eight-layer redaction silently would break that contract.Enabling OPF with no category selected fails the same way. Entire cannot tag commits as OPF-applied without a scan, so the push aborts with a configuration error instead. Enable a category, set enabled: false, or pass ENTIRE_OPF=no.The rewrite also refuses to run when it would rewrite history it does not own. It aborts if local checkpoints have diverged from the remote, if a first push exceeds the bootstrap commit cap, if the batch exceeds the inference byte cap, or if another worktree moves the ref mid-rewrite. See OpenAI Privacy Filter for the caps and their overrides.command is local-only, and the file must be untracked. command names the binary Entire executes during git push, so whoever controls that string controls what runs on your machine. Entire honors it only when it is genuinely yours:
  1. It has to come from .entire/settings.local.json, not the committed .entire/settings.json.
  2. That file has to be untracked, meaning absent from both the Git index and HEAD.
The second check carries the weight. A filename proves nothing on its own, because .gitignore does not apply to an already-tracked path: git add -f .entire/settings.local.json commits the file, and a fresh clone materializes it with the committed content. A pull request that pairs a command with a payload would then execute on every machine that checks the branch out, and a JSON settings diff does not read as executable to a reviewer.The rule covers the whole file. A tracked .entire/settings.local.json is ignored entirely, because it arrived with the repository rather than belonging to your clone, and Entire tells you to run git rm --cached .entire/settings.local.json. Settings still load from the project file, so a committed local-settings file cannot break the repository.Entire logs a rejected command to .entire/logs/entire.log, and OPF falls back to resolving opf on $PATH. If that binary is missing, the push fails closed rather than shipping content you believed OPF had scanned. Everything else in the OPF block, including enabled, categories, timeout_seconds, and prompt_default, works from the shared project file.Content OPF did not reach. Several local locations retain content that predates the OPF pass. This matters if your threat model extends past what reaches the remote.To clear the unreachable objects sooner:
This is I/O-heavy on a large repository, so Entire does not run it for you.
Agents inline base64 images into their transcripts. Redaction skips those objects, so an image reaches checkpoint storage as-is either way. What redaction.externalize_images changes is where the bytes sit.With externalization on, Entire lifts each inline image out of the transcript into the checkpoint’s assets/ store and leaves a placeholder in its place:
The placeholder is deliberately low-entropy so the entropy layer does not flag it, and it names the asset path so an agent reading the stored transcript still knows an image was there. assets/manifest.json indexes the store. Restore re-injects the images byte-exactly whether or not the flag is on, and Entire refuses to externalize any image whose bytes do not re-encode to the original base64 string.Nothing redacts the assets subtree. Every regex layer skips it, and the OPF rewrite copies it through verbatim, because byte-redacting an image would corrupt it. An image holding a credential, a customer record, or a screenshot of a dashboard reaches the remote intact, whether it sits inline in the transcript or in assets/.Externalization is off by default. Turning it on keeps large binary blobs out of the transcript files, which makes transcripts cheaper to read and diff. It does not add or remove any redaction coverage. See Externalized images for the setting.
  • Detection is best-effort. Short passwords and predictable tokens carry too little entropy and match no known pattern.
  • Filenames and binary data go unscanned. A secret in a filename, a binary file, or a deeply nested structure may go undetected.
  • Skip rules can hide secrets. The structural-field and image skip rules avoid false positives at the cost of coverage, so a secret in a path field or a base64 blob survives.
  • Assets are not scanned at all. See Externalized Images above.
  • You own your custom rules. Entire logs and skips an invalid regex in custom_redactions, a rule pack, or custom_patterns. It does not check that your rules catch what you meant them to catch.
  • Source snapshots are not covered. Custom rules and every other layer apply to transcript, prompt, and checkpoint metadata. Shadow branches still carry raw source.
  • Review what you push. Redaction reduces exposure; it does not certify a checkpoint as safe to publish.
The CLI runs locally. It reaches the network in these cases:Entire pushes checkpoint data only when strategy_options.push_sessions is true, which is the default. Set it to false to keep checkpoints local.
Entire runs third-party binaries in two situations, and both give the binary your user’s privileges.CLI plugins. entire <name> runs entire-<name> when the built-in commands do not match. The CLI resolves the name against $PATH, and at startup it prepends a managed directory to $PATH:
entire plugin install downloads release binaries into that directory. Two properties bound the download:
  • The CLI requires HTTPS. It refuses plaintext HTTP for anything off-machine, because the asset and the checksums.txt that authenticates it share an origin, so an attacker who can rewrite one can rewrite the other.
  • Entire verifies checksums by default. It fetches the release’s checksums.txt, selects the asset for your platform from it, and verifies the digest. It refuses a release that publishes no checksums. --allow-unverified overrides this and installs bytes that nothing authenticates.
Neither property tells you the code is trustworthy. A verified download of a malicious plugin is still a malicious plugin, and prepending the managed directory to $PATH means an installed plugin also shadows same-named binaries elsewhere on your path. Install plugins you trust, audit what entire plugin list reports, and see the entire plugin reference for the complete verification behavior.Agent integrations. An entire-agent-<name> executable integrates a coding agent that Entire does not ship with. The CLI invokes it during agent sessions, and it can read and write the same files as the CLI. Discovery is off by default behind the external_agents setting. See the Agent Integration Protocol.Environment filtering. Entire does not hand a plugin your whole environment. It passes an allowlist covering OS plumbing, locale, terminal and color variables, CI detection, proxies, and SSH_AUTH_SOCK, plus the ENTIRE_* variables the CLI sets. Credential-shaped variables such as AWS_*, GITHUB_TOKEN, and OPENAI_API_KEY do not pass through.This is defense in depth rather than a sandbox. A plugin runs as you and can read anything under $HOME, including the credentials the allowlist withheld.
Entire signs checkpoint commits with the GPG or SSH key already configured for your regular commits, when three conditions hold:
  1. commit.gpgsign = true in your global or system Git config.
  2. A supported signer is available: GPG by default, or SSH with gpg.format = ssh and a running ssh-agent.
  3. sign_checkpoint_commits is true, which is the default when the setting is absent.
Best-effort behavior. Signing does not block a commit. If the signer is unavailable, fails, or waits on a hardware token touch you did not give, Entire creates the commit unsigned and logs a warning to .entire/logs/. This keeps CI runs and automated checkpoint saves from losing data.To opt out, see Checkpoint commit signing. Opting out does not change how your own commits are signed.
The CLI sends anonymous usage analytics by default, to PostHog at eu.i.posthog.com, under the event name cli_command_executed.What’s captured per command:
  • Command name, for example entire enable or entire checkpoint explain
  • Selected agent name, or auto
  • Whether Entire is enabled in the current repository
  • CLI version
  • OS and architecture, for example darwin/arm64
  • Installed Git version, when it can be determined
  • Names of flags passed, not their values
What’s not captured: flag values, prompt text, transcripts, file paths, repository identifiers, GitHub usernames, source code, and IP-derived location. The PostHog client sets DisableGeoIP: true.DistinctID is a hashed machine identifier derived from machineid.ProtectedID: stable per machine, not directly mappable to a person.Opt out (any one of):
  • Pass --telemetry=false on commands that accept it.
  • Set "telemetry": false in .entire/settings.json or .entire/settings.local.json.
  • Set the env var ENTIRE_TELEMETRY_OPTOUT=1.
The first run of entire enable or entire configure asks for telemetry consent interactively; declining there sets the setting to false.
  • Use a private repository for sensitive work. This is the shortest path to containment, and it does not depend on redaction catching anything.
  • Keep sensitive files out of agent context. Content that never enters a transcript cannot leak through one.
  • Read your checkpoints before the first push. Run entire checkpoint explain, or inspect the refs directly, the same review you would give any branch about to go public.
  • Enable PII redaction when your agents see customer data. It is off by default.
  • Check whether OPF covers your backend before you rely on it. See the warning under OpenAI Privacy Filter (Optional) above.
Reporting. Email [email protected]. Do not open a public GitHub issue for a security vulnerability.Include in your report:
  • A clear description of the vulnerability.
  • The impact, meaning what an attacker could achieve.
  • Detailed steps to reproduce.
  • Affected CLI versions if known.
  • A suggested fix if you have one (optional).
What to expect:
  • Acknowledgment of receipt within 48 hours.
  • Progress updates as we investigate.
  • Resolution within 90 days for critical vulnerabilities.
Confidentiality. We keep all reports confidential and will not share your information with third parties without your consent, except where the law requires it.Scope. The CLI (entire), official Entire GitHub repositories, and entire.io services.Out of scope (report upstream or treat as bug reports):
  • Issues in third-party dependencies.
  • Social engineering attacks.
  • Denial of service that requires local access to trigger.
  • Issues that cannot be exploited without direct access to the user’s machine.
Bug reports vs security advisories. We reserve security advisories for confirmed vulnerabilities that a remote or non-local actor can exploit. Because the CLI is primarily a local development tool, we track regular-expression performance issues (ReDoS) on local execution, resource exhaustion that requires local access, and issues that cannot be exploited without direct machine access as bug reports. File those at github.com/entireio/cli/issues.