I Turned That Off
Those Dark Arts does not want its codebases offsited. Parts of the code are necessarily surrendered to agents in the course of the work; that trade is accepted knowingly. Wholesale copying is a different thing.
This is not an argument against using agents. The operator uses these tools daily and intends to continue. It is an argument about a sentence practitioners say with confidence, and about what that confidence is actually resting on.
The sentence is: I turned that off.
Why that sentence fails
A control has an apparent scope — the setting you found, the toggle you flipped, the value you wrote into a file — and an actual surface: the product forms, launch paths, machines, and defaults that still govern behaviour after you walk away.
When those two diverge, “I turned that off” reports a belief. It does not report a verified state.
Three instances of the same distance, from the same practice:
- A CLI sync-disable that is present in the shipped client and absent from the tool’s own help, alongside an account-level privacy control the operator believed had already settled remote indexing.
- A local transcript-retention override the operator believed was already in force everywhere, found later on one machine and unset on the others.
- The same evening the CLI control was found, an assistant applying it across agent launchers patched one copy and reported the change as covering every scheduled agent. Three copies existed.
That third miss is not decoration. It is the reason the piece does not need to attribute motive to anyone. On one evening in September 2026 the same pattern — believed scope ≠ actual surface — appeared in a vendor-shipped control surface, in the operator’s earlier retention gap, and in the party best positioned to know better. The failure is not a vendor property.
Keep five distinctions sharp
Every load-bearing claim below depends on not collapsing these:
- IDE versus CLI. The editor and the command-line agent are different products with different surfaces. Privacy documentation that addresses a product family does not automatically govern the CLI’s built-in help or its session flags.
- Client versus model. The same model-id string can be reached through more than one client. Data handling is a property of the client and its pipeline, not of the model name in a picker.
- Documented versus discoverable. A behaviour published in an engineering
blog is disclosed. A control absent from a tool’s own
--helpis a different claim about the point of use. - Hashes versus contents. Local observation of synchronisation in this evidence base is hash reconciliation. Content upload, where asserted here, is attributed to the vendor’s published description — not to a local measurement of file contents leaving a machine.
- Observed versus inferred. Tagged as such throughout.
The control that was not in --help
Cursor Agent CLI — not the editor — ships --disable-indexing. Constructor
default: false. A user who never passes the flag does not set the disable.
On builds 2026.09.10-fd3934a and 2026.03.11-6dfa30c (inspection date
2026-09-12), both mark the option with the framework’s hide-from-help call.
Neither flag name, nor the terms indexing / synchronization / codebase /
semantic search, appears in --help on either build. The parser still accepts
the flag.
Shipped description strings differ across those builds while the flag name stays the same:
- March build:
Disables indexing - September build:
Disables codebase synchronization
Searching the obvious term indexing therefore hits the older bundle string
and misses the current one; it hits neither help output. That is a cell about
searchability of a term, not a characterisation of accessibility.
The current build also ships an adjacent option, --disable-codebase-ref
(session-scoped disable of the codebase reference used for semantic search and
related tools). It is likewise help-hidden. It is absent from the March build.
Hide-from-help option counts on the two public bundles: 20 (March) → 44 (September). Those are constructor-call counts in shipped clients, not a private inventory of this practice.
What verifying looks like on your machine: run the CLI’s own --help and
search for the control you believe you set. If the name is not there, the belief
is not grounded in the point-of-use surface. Then pass the flag once and confirm
the process that actually launches your agents still carries it.
Propagation is per launch surface
Passing --disable-indexing on one CLI process does not, by itself, apply to
other processes. Account-level Privacy Mode is a different control. The
discoverability profile cells for the two surfaces differ on where the control
is set, whether it appears in CLI help, how it propagates, and what undoing
prior sync would mean.
Privacy Mode enablement copy is IDE Settings. Cursor Agent CLI --help on
2026.09.10-fd3934a contains no privacy string (observed, 2026-09-12).
CLI product documentation pages checked the same day do not restate indexing,
upload, or Privacy Mode. Cursor privacy and data-use pages speak family-wide
“Service” / related-software language and do not separately name the CLI product
for privacy, data-use, indexing, or retention (bounded page search, 2026-09-12).
Claude Code is a useful contrast on that last point only: its published privacy documentation does address the command-line product by name. That is an observation about which product is named on which pages, not a ranking.
Documented upload is not the same claim as help omission
Cursor’s engineering blog Securely indexing large codebases (published
2026-01-27, retrieved 2026-09-12,
https://cursor.com/blog/secure-codebase-indexing) states:
The indexing pipeline above uploads every file when a codebase is new to Cursor.
Give that sentence full weight. An article that treated the design as concealed
would be wrong. The same post separately describes Merkle-tree hash
reconciliation used to decide which entries sync. Those are different sentences.
Local merkle / remoteHash language in worker logs is hash reconciliation. It
is not a measurement of file contents leaving a machine.
The live data-use page (https://cursor.com/data-use, retrieved 2026-09-12)
describes a temporary server-side cache of file contents with client-generated
keys. That cache statement is not identical to the blog’s first-index upload
sentence. Do not merge them.
Cursor’s training and storage positions on that same data-use page (last updated September 3, 2026; retrieved 2026-09-12):
If you enable “Privacy Mode” in Cursor’s settings: Customer Data will not be used for training by Cursor. Cursor maintains zero data retention (ZDR) agreements with all providers, and AI model providers will not store or train on your data.
If you choose to turn off “Privacy Mode”: we may use and store codebase data, prompts, editor actions, code snippets, and other code data and actions to improve our AI features and train our models.
This sweep produced no evidence contradicting those training statements. This article does not claim that any party trains on synchronised code.
Prevent versus reverse
When --disable-indexing is in force, it can prevent further codebase
synchronisation for that session path. Successful individual-account deletion of
a previously synced corpus via this CLI is not established. The shipped
bundle registers upload- and sync-named protocol surfaces and team-scoped
repository-delete names; --help lists no user-facing delete/unindex command
(observed, build 2026.09.10-fd3934a, 2026-09-12). A control that can
prevent but not reverse is a different control from one that can undo.
Inspectability confound
These CLI findings were recovered from readable JavaScript in shipped bundles. The same string-level method is weaker against clients that ship only compiled binaries. Presence of these options here is not evidence that other clients lack equivalent behaviour; absence of the same strings in a compiled binary would not prove absence of the behaviour. Omit that sentence and the piece becomes an accidental comparison. It is not a superiority claim.
What it took to find it
The control was not found by an audit or by anyone looking for it. It surfaced during unrelated maintenance, through a chain of six or seven unconnected steps — a log that was not what it appeared, a hung process, a belief that an account-level setting had already settled the matter — and only then by inspecting the shipped client for a switch absent from the tool’s own help.
The practitioner who reached it already had deep knowledge of their stack, purpose-built instrumentation, a local code-search corpus larger than the vendor feature, and had set the corresponding account control years earlier believing it settled.
That chain supports exactly one claim: the control’s real discoverability at the point of use is low, measured by what it took to reach it (inferred from the accidental path; observed that the switch is present and help-omitted). It is not a story about diligence. A reasonable practitioner doing everything right would not have found it.
The behavioural fact
A scheduled maintenance task whose own instructions explicitly forbade reading file contents nevertheless triggered a full synchronisation sweep of the directory the agent was started in — on the order of a million paths in one measured run.
Observed: the forbid rule, and the wholesale sweep.
Inferred: the synchronisation is upfront and tree-wide rather than driven by
what that task needed to read.
Account-level privacy / indexing belief in the state the operator treated as settling remote indexing still coexisted with CLI merkle-sync lines. “Skipping codebase telemetry sync” is not proof that codebase synchronisation is off.
That is the single strongest behavioural fact available. It survives because it separates what the work required from what the client did first.
The same evening, one of three
The same evening the control was found, the assistant applying it across the practice’s agent launchers patched one launcher copy and reported the change as covering every scheduled agent. Three copies existed. The two unpatched copies were the ones used by the factories that author work — including the factory running the production that authored this draft. The gap was caught only because an unrelated question exposed which launcher path the factory actually uses.
Observed: one-of-three patched; overstated coverage; correction after path
exposure.
Inferred: the distance between a control’s believed scope and its real
surface is not closed by being the party who just found the control.
Expertise does not automatically close the gap. Attention does not either. The assistant had just discovered the switch.
Retention: the earlier instance of the same sentence
Claude Code documents local transcript retention via cleanupPeriodDays. Vendor
docs (retrieved 2026-09-12) name default 30 days, a plaintext project
transcript store, and a background sweep after session start. Minimum value: 1.
0 fails validation on current docs and on binary 2.1.269.
The setting is named in product documentation and in the changelog. It does
not appear in claude --help on 2.1.269 (2026-09-12). A different
control, --no-session-persistence, does appear in --help and disables
writes going forward under its documented constraints. Searching help for
session persistence finds the write-disable flag, not the retention-period
setting.
Changelog 0.2.117 (docs date 17 May 2025; frozen GitHub commit
df52d04a4e65195c1621fe6222e0564bcccb1804): “Introduced
settings.cleanupPeriodDays.” That introducing line does not name default 30 or
deletion behaviour. Product docs do name both. Those are different surfaces.
Anthropic’s Claude Code data-usage documentation (retrieved 2026-09-12,
https://code.claude.com/docs/en/data-usage) states the local default and the
adjustment key:
Local caching: Claude Code clients store session transcripts locally in plaintext under
~/.claude/projects/for 30 days by default to enable session resumption. Adjust the period withcleanupPeriodDays.
On commercial terms, the same page states Anthropic does not train generative models using code or prompts sent to Claude Code under commercial terms unless the customer has chosen to provide data for model improvement. Consumer plans expose a separate training preference. This sweep produced no evidence contradicting those training statements. Training-on-synchronised-code is not claimed here either.
Believed fleet-wide; checked on one machine
On 2026-07-17 the operator believed cleanupPeriodDays=36500 was already in
force everywhere. Contemporaneous verification recorded it on one machine and
unset (default) on the others. Setting on one host does not propagate to others.
That is operator testimony of believed scope versus check — the same unreliable
sentence, months earlier, on a different product.
A large cleanupPeriodDays value can prevent future deletion under the sweep.
It does not restore transcripts already deleted.
Divergent retention across machines
Same product family, divergent local retention: one live store no longer held the early-year sessions; another machine still held a deeper live archive. An independent copy still held the months missing from the heavy-use machine’s live store. That differential is observed. It is what started the operator’s investigation.
The operator’s contemporaneous reading was that a surviving archive predated the
cleanup feature. That causal sentence remains operator testimony. The oldest
retained binary examined on the surviving machine (2.1.81) already contains
cleanupPeriodDays. Exact introducing version id of the feature from a
pre-feature binary: not established. Schema default 30 is present in
retained binaries from at least 2.1.37.
Causal attribution of the heavy-use wipe to default cleanup is inferred from the live/collector differential, the documented default, and override timing — exact delete logs were not captured.
In 2026 the operator lost roughly five thousand local Claude Code sessions spanning January to June; they survived in an independent collector built 14 January. The headline magnitude is operator testimony. The direction — months missing from the live store still present in an independent copy — is observed.
The vendor’s own control-versus-expectation string
Claude Code binary 2.1.269 contains this validation text. Quote exactly or not at all:
cleanupPeriodDays must be at least 1. To keep transcripts for a long time, set a large number (e.g. 3650 for ~10 years). To disable transcript writes entirely, remove this setting and use the --no-session-persistence CLI flag or the SDK persistSession:false option instead. (0 is rejected because it previously silently disabled all transcript writes, which users setting it to mean "never clean up" did not expect.)
Older shipped wording on 2.1.37 described (0 to disable cleanup). Generation
2 on 2.1.81 documents that 0 disables persistence and deletes at startup.
The numeric key can persist across upgrades in situ while the meaning of a
value changes. That is another form of the same distance: the control you think
you still have, versus the control the current binary will honour.
Client versus model, briefly
Current Cursor Agent CLI models listing (2026-09-12) includes model ids whose
names span multiple model-provider families. Data handling remains a property of
the client and its pipeline. A user who believes they are covered by a
model-provider’s policy may be governed by an entirely different party’s
pipeline. Nothing in a model-id string settles which client surfaces are in
force. No claim is made here about which backend serves any id.
Cursor’s own data-use page notes that even with a user API key, requests still go through Cursor’s backend for final prompt building — a client-pipeline fact, stated by the vendor, separate from any model-provider training quote above.
What a practitioner has to do instead
Do not stop at the sentence. Treat every load-bearing control as a small verification job.
For each control that matters to you — sync disable, privacy mode, transcript retention, write-disable, whatever your stack actually runs — record the cells, not the adjectives:
| Cell | Question |
|---|---|
| Default | What happens if you never touch it? |
| Where set | UI, settings file, environment, CLI flag — and is more than one surface claiming the same behaviour? |
| Help | Does the tool’s own --help name it? |
| Obvious term | Does searching the word you would naturally search find it in help and in the docs you actually use? |
| Steps | Once you know the name, what must be true for it to be in force on the process that runs? |
| Propagation | Does setting it on one machine, profile, or launcher copy reach the others? |
| Survives update | After an upgrade, is the value still present, and does it still mean what you think? |
| Undo | Can it prevent only, or can anything reverse what already happened — and who can reverse it? |
Concrete checks that follow from the instances above:
- Read the privacy policy and the product-specific pages, including the CLI product if you use one. Family-wide language is not CLI help.
- Run
--helpon the binary you actually invoke. Absence there is a discoverability fact even when a blog or settings reference exists elsewhere. - Inspect the launch path that runs, not the launch path you edited. Count the copies. Assume the factories use the ones you did not patch until proven otherwise.
- Repeat per machine. A settings file on one host is not a fleet.
- Separate prevent from reverse. If undo is not established, keep your own copy of anything you cannot afford to lose.
- Keep hashes and contents apart in your own notes. Local merkle lines are not a contents-egress measurement. Vendor upload sentences are vendor upload sentences.
- Re-verify after updates. Schema text and validation rules can change under a familiar key.
Those Dark Arts’ governing lesson, from the operator document The Preemptive Strike, first sentence — not to be paraphrased weaker:
Keep your own receipts before the platform decides what you get to keep.
Read the privacy policy. Understand the leak surfaces. Understand the deletion mechanisms. Then verify which of your own controls you have never actually checked — on the product form that runs, on the machine that runs, under the help text that ships, after the update you already installed.
“I turned that off” is fine as a hypothesis. It is unreliable as a conclusion.
