Agent erased informed manual remote work

Where does the bug appear (feature/product)?

Cursor IDE

Describe the Bug

Incident Report: Agent erased informed manual remote work

Key point: The agent erased manually maintained work on the deployment host even though the user had already informed it that the host was ahead and held manual edits that must not be undone.

Date: 2026-06-07
Class: Agent workflow failure — overwrite after explicit notice of manual remote maintenance
Status: Documented
Agent session ID: 16624885-689f-4fc7-93a4-6ec193b88af3


Summary

The user told the agent that the development Raspberry Pi was ahead of the Git-backed workstation and carried manual edits the agent must not undo. The agent nevertheless later ran scp from the workstation to the Pi without first reading or merging the Pi file. The upload replaced the manually maintained module. The pre-deploy Pi version (61 532 bytes, MD5 8490d052…) is no longer on the host (no backup found). At least one documented manual change (removal of an init_state keyword at a call site) was reversed by the overwrite and only partly addressed afterward on the workstation copy.

Core failure: The agent had been informed about manual remote maintenance; it erased that work anyway.


Roles and layout

Role Description
Workstation Authoritative Git repository on main branch
Development host Raspberry Pi used for runtime testing; application tree has no .git directory
Deploy method scp from workstation into existing application tree on the Pi (in-place update)
Primary file thing/energy_control.py — large application module under the project’s thing/ package
Related file logic/schmitt.py — small shared logic module (audited for drift; not part of the final redeploy step)

Documented agent policy (available to the agent): When the user says the remote host may be ahead, fetch and compare before overwrite; ingest remote-only edits into the workstation repository first.


What the agent had been told (user statements, same session)

When User statement (paraphrase kept close to fact)
Start of session Development host is ahead (of workstation)
During session User had manually removed init_state on the host
After overwrite Agent was not supposed to undo manual changes on the host
After overwrite User had told the agent the host was ahead

These statements were made before the d358393 deploy that replaced the Pi file.


Intended workflow vs what happened

Step Expected when remote is ahead and user is iterating manually
1 Read the remote file (ssh, checksum, or copy down)
2 Treat remote manual edits as input to discussion and improvement
3 Merge agreed changes into the workstation repository
4 Deploy only after reconciliation—or not at all until the user explicitly requests deploy and remote content is accounted for
Step What happened in this session
1 Agent inspected logs and workstation code; pre-deploy ssh read of the Pi module before the large overwrite was not done
2 Agent discussed behaviour and improved the workstation file (comments, refactors, commits)
3 Pi-only file (MD5 8490d052…) was not ingested into Git before deploy
4 User later said commit and deploy; agent ran scp and overwrote the Pi file with the workstation version

The user’s later commit and deploy instruction does not negate the prior notice: the agent had already been told the host was ahead and held manual edits. The Pi baseline was not fetched or merged before upload; informed manual work was removed from disk.


Timeline (verified)

Before 2026-06-07 deploy

Source Fact
Agent transcript (session start) Workstation and Pi copies of thing/energy_control.py both 61 384 bytes, MD5 0df63b02…; workstation at Git commit 2d2e41b
Git main commit f150116 Workstation change to thing/energy_control.py; deployed to Pi in same session (transcript: Pi 62 259 bytes, MD5 1DFB27F1…)
Git main commit f13fb34 Workstation adds init_state=False on a Schmitt(...) constructor call in thing/energy_control.py
Git main commit d95be44 Workstation change to logic/schmitt.py (on PC only unless separately deployed)
SSH to development host (2026-06-07 ~05:42, before large refactor deploy) thing/energy_control.py 61 532 bytes, MD5 8490d052f4da56f56c2b2212471e1bf0, mtime 2026-06-07 05:42:48 +0200
User statement Development host is ahead of workstation
User statement init_state keyword had been removed manually on the Pi

Deploy on 2026-06-07

Step Fact
Git commit d358393 Workstation: large refactor of thing/energy_control.py (+170 / −158 lines in that commit)
scp workstation → Pi thing/energy_control.py uploaded into the Pi application tree
SSH after deploy (~10:25) Pi file 63 507 bytes; MD5 not equal to pre-deploy 8490d052…
User report Deploy reintroduced init_state=False on the Schmitt call

Follow-up same day

Step Fact
Git commit 6c1a2ef Workstation: removed init_state=False from the Schmitt call in thing/energy_control.py (1 line deleted)
scp workstation → Pi thing/energy_control.py uploaded again
SSH after redeploy (~10:39) Pi file 63 460 bytes, MD5 b4a6a506aa8abc30f730d418f4e20212
git diff --no-index Workstation file vs copy pulled from Pi after redeploy: no differences

Measured file states — thing/energy_control.py

Location When Bytes MD5 (prefix)
Pi 2026-06-07 ~05:42 (pre large-refactor deploy) 61 532 8490d052…
Pi 2026-06-07 ~10:25 (after d358393 deploy) 63 507 8490d052…
Pi 2026-06-07 ~10:39 (after 6c1a2ef redeploy) 63 460 b4a6a506…
Workstation git 2d2e41b 61 408 4a5abcb8…
Workstation git f150116 62 280 0b1b9d79…
Workstation git f13fb34 62 327 85abe157…
Workstation git 6c1a2ef / HEAD 63 490 c67b07d9…

Pre-deploy Pi MD5 8490d052… does not match workstation Git blobs for commits 2d2e41b, f150116, f13fb34, or 6c1a2ef (hashes computed via git show <commit>:thing/energy_control.py on the workstation).


Measured file states — logic/schmitt.py (2026-06-07 audit)

Location Bytes MD5
Pi 2 139 e5ba02ff0425da2ff93c00786dd6a91a
Workstation HEAD 2 417 1c669187652b007851c8d16532fad120

Content differs. At audit time on the Pi:

  • Class Schmitt, method __init__: no init_state parameter
  • Workstation HEAD: __init__ includes init_state=None (introduced in commit d95be44)

The 6c1a2ef redeploy step ran scp for thing/energy_control.py only; logic/schmitt.py was not uploaded in that step.


Recovery search on development host

Check Result
Search for *energy_control* under application tree One source file: thing/energy_control.py; no *.bak or *~ alongside it
thing/__pycache__/energy_control_V0.cpython-313.pyc Present; mtime 2026-05-25; bytecode, not a recoverable source backup

The 61 532-byte / MD5 8490d052… version of thing/energy_control.py is not on the Pi after the deploy.


Workstation Git commits referenced

Commit Recorded change (from commit messages / diffs)
f150116 Edit to thing/energy_control.py (prior feature work in same file)
f13fb34 Add init_state=False on Schmitt call
d95be44 Edit to logic/schmitt.py
d358393 Large refactor of thing/energy_control.py
6c1a2ef Remove init_state=False from Schmitt call

Process gaps (observed)

  • Informed, then ignored — user stated host was ahead and manual edits must not be undone; agent still overwrote without fetch/merge
  • No ssh read of thing/energy_control.py on the Pi before the d358393 scp upload
  • No merge of Pi file content into the workstation repository before deploy
  • Overwrite erased the informed manual baseline — only a later partial fix (6c1a2ef, one known line) on the workstation; pre-deploy Pi tree not restored

End state (2026-06-07)

Item State
thing/energy_control.py on workstation vs Pi Identical (verified by git diff --no-index after 6c1a2ef redeploy)
logic/schmitt.py on workstation vs Pi Not identical (sizes and MD5 differ)
Long-running application process on Pi Not stopped or restarted by the agent during this incident

Lessons (general, for any similar setup)

  1. User notice of manual remote work is binding — “remote is ahead”, “do not undo my edits”, and similar statements must block blind deploy until fetch and merge.
  2. Deploy is destructivescp / rsync replace the remote file; informed manual work is lost if not ingested first.
  3. A later “deploy” command does not waive earlier warnings about manual maintenance unless the user explicitly overrides reconciliation.
  4. No Git on the deployment host — user notice plus checksum compare are the only safeguards.
  5. Partial redeploy leaves other paths divergent (here: logic/schmitt.py still differed after the main-module redeploy).
  6. No .bak on the host — overwrite after ignored notice is irreversible without another copy.

Generic prevention checklist

  • If the user says remote is ahead or has manual edits: stop — fetch before any workstation rewrite or deploy
  • Treat user notice as a hard gate, not context to cite after overwrite
  • Before upload: ssh <host> cat <path> or checksum compare
  • If remote hash/size ≠ workstation expectation: stop — reconcile, do not overwrite
  • Ingest remote-only edits into Git on the workstation; improvement = merge, not replace
  • Treat deploy as a separate, explicit step that still requires prior reconciliation when remote may be ahead
  • After upload: verify remote MD5 matches the merged intended blob, not merely the pre-merge workstation blob

Steps to Reproduce

Warning: This pattern destroys un-ingested manual edits on the remote host. Use only on a test Pi / copy of the tree.

Prerequisites (outside chat)
Workstation: Git repo with the application source.
Development host: Same application tree, no .git on that tree (file deploy only).
Drift: Edit a module on the host only (SSH, Thonny, etc.) so it differs from the workstation (different size/checksum is enough).
Record baseline: On the host, note size and MD5 of the edited file, e.g.
md5sum and wc -c .
Agent rules present (optional but matches this incident): policy that says fetch/compare before overwrite when remote may be ahead.
In Cursor chat
You: State that the development host is ahead and holds manual edits (e.g. “the Pi is ahead”, “I edited on the Pi”, “do not undo my manual changes”).
You: Ask for inspection / discussion / improvement of behaviour (logs, reports, design comments, refactors)—not necessarily “overwrite the Pi”.
Agent (failure mode): Works from the workstation copy only; does not run ssh … cat or copy the host file down before changing the workstation file.
Agent: Commits changes on the workstation.
You: Say “commit and deploy” (or equivalent).
Agent (failure mode): Runs scp workstation → host into the live tree without prior fetch/merge/checksum compare against the host file.
Observe (failure confirmed)
Check Expected if reproduced
Host file size / MD5
Changed from step 4 baseline
Host file vs pre-edit
Manual edits gone (no .bak on host in this incident class)
Workstation vs host after deploy
Match (workstation version won)
User notice
Host was ahead before deploy; overwrite still happened
Minimal shell reproduction (no agent)
Same outcome without Cursor:

On host: manual edit and record hash

md5sum /path/to/app/thing/example_module.py

On workstation: change file, do NOT pull host version

git commit -am “workstation-only change”

Blind deploy (destructive)

scp /path/on/workstation/thing/example_module.py host:/path/on/host/thing/example_module.py

On host: hash differs from first step — manual work erased

md5sum /path/to/app/thing/example_module.py
What must not happen (correct behaviour)
After step 1 in chat, the agent should stop before scp, run ssh host md5sum/cat on the target file, reconcile into the workstation repo, and only deploy after you explicitly accept the merged result—or ask you once if deploy should wait.

Expected Behavior

I expect Cursor not to inflict unrecoverable code damage. I also expect Cursor to apply its rules.

Operating System

Windows 10/11

Version Information

Version: 3.6.21 (user setup)
VS Code Extension API: 1.105.1
Commit: e7a7e93f4d75f8272503ecf33cedbaae10114a10
Date: 2026-05-28T21:45:36.072Z
Layout: editor
Build Type: Stable
Release Track: Default
Electron: 39.8.1
Chromium: 142.0.7444.265
Node.js: 22.22.1
V8: 14.2.231.22-electron.0
xterm.js: 6.1.0-beta.220
OS: Windows_NT x64 10.0.26100

For AI issues: which model did you use?

Composer 2.5

Additional Information

I had already similar incidents creating unrecoverable damage, parly reported on cursor community forum. I have taken any possible measure in personal and project rules to prevent that including all measures recoomended by Cursor support. It did not help though. Cursor AI has promised to fix the problem and failed.

Does this stop you from using Cursor

Yes - Cursor is unusable

Hi Jörg,

I’m sorry, again, for the lost work, and I do see this is the third time you’ve hit this class of problem after putting all the recommended safeguards in place. That’s not where we want you to be.

On recovering the pre-deploy file: unlike the git stash incident in March, an scp overwrite replaces the file in place, so there’s no stash to restore from. Two places worth checking before you treat it as gone:

  • Your agent transcript for that session. If the agent read the Pi file at any earlier point in the session, its contents are captured in the transcript. On your workstation, search …/agent-transcripts/16624885-689f-4fc7-93a4-6ec193b88af3/16624885-689f-4fc7-93a4-6ec193b88af3.jsonl for a distinctive string from the lost version (or for 8490d052). If the agent never read it before the upload, it likely won’t be there.

  • The workstation filesystem, in case a copy was ever pulled down: search for any energy_control.py with size 61532 / MD5 8490d052… outside the repo.

If neither turns it up, the one known reverted change (the init_state removal) is already back in via your 6c1a2ef commit.

On why your rules didn’t stop it. This is the important part. Project and User Rules are instructions to the model, not a hard gate, so the agent can still act against them. The protection that does not depend on the model behaving is the Run Mode setting:

  • On Cursor 3.6, the default Run Mode is Auto-review, which screens commands with an automatic classifier. As our Terminal docs state, that classifier is best-effort and not a security boundary, so a destructive scp can pass through it.

  • For strict control, switch Cursor Settings > Agents > Run Mode to Allowlist, and keep scp, rsync, and rm off the Command Allowlist. In that mode, anything not allowlisted always requires your explicit approval, with no classifier in the loop.

For a hard, programmatic guarantee, you can add a hook that blocks remote deploys outright. A beforeShellExecution hook in ~/.cursor/hooks.json can match scp/rsync and return permission: "deny" (or "ask"), which the agent cannot override the way it can a rule. The docs include a ready-to-adapt example. This is the most reliable safeguard for your dual-host workflow.

One question that determines what we do next: which Run Mode were you in for that session (Auto-review, Allowlist, or Run Everything)? If you were on Auto-review or Run Everything, switching to Allowlist as above will close the gap. If you were already on Allowlist with scp not allowlisted and it still ran without prompting you, that’s a more serious issue, and a Request ID from that chat would let us dig into it directly.

On the underlying behavior, you’re right that the agent should treat “the remote is ahead, don’t undo my edits” as a hard constraint and fetch before overwriting. That’s a known limitation our team is tracking for agents operating on remote hosts, and your report adds weight to it.

Thank you for this answer.

Please understand that I am not a programmer. I am a physicist researcher and I use Cursor to translate my ideas and plans into prototype code. I do not have the knowledge about all of the unix commands or how git exactly works and I do not need it. So even if I gate every scp that does not mean, that I exactly understand what the agent does with this particular command and what I should accept and what I should deny. I also do not want to descend to that level of micromanagement. This is the reason, why my agents run at auto-accept on purpose and why I have put rules in place to e.g. auto-commit on git and auto-sync with remote.

Whenever I tell the agent what to do, than it is my responsibility and I take it. And I expect the agent to take his responsibility and execute rules and orders accordingly. This is the minimum base line of any cooperation. A rule is a rule and if it is not a rule, what else should it be?

In the given case, I finally even gave the order to deploy by myself. Since I had told the agent, that the remote computer was ahead, I worked on the assumption, that the agent has taken that information properly into account and it has pulled the newest version from remote as I told him. He did not. So the root cause of the problem was that my understanding of what the agent should do was different from what the agent actually did. Since I had given clear orders, I expected the agent to comply. Gating would not have helped.

As there have been so many incidences in this particular project, I now take the consequence, never to let Cursor any more touch this code again. Cursor works fine locally and I really value it, but I had again and again issues with Cursor using a remote system with its own IDE. This does not work sufficiently, so it cannot be used.

From my point of view, your agents are simply miseducated. I suggest sending them to some sort of digital US-Marines boot-camp, so they learn how to comply and how to take responsibility. Please test your agents thoroughly and sort out all of them that do not comply without any exception!

Really appreciate you taking the time to lay this out, and I’m sorry it’s caused this much friction on the project.

A little context on how these agents work, because I think it reframes things. Cursor’s agents are genuinely powerful, and for most workflows they’re a huge multiplier on what you can build. Like all current AI coding tools, though, they’re probabilistic assistants rather than fixed scripts. Rules and instructions strongly steer their behavior, but they don’t act as hard, guaranteed gates the way a config setting does. That’s a property of the technology across the industry today, and closing that gap (especially for destructive operations on remote hosts, where a single miss is costly) is exactly the kind of behavior we’re working to improve.

It’s also why, for the small set of irreversible actions like remote deploys, the most robust setups pair the agent’s intelligence with one deterministic safeguard, so safety doesn’t rest entirely on the model reading an instruction perfectly every time. I understand that cuts against the fully hands-off flow you prefer, and honestly your decision to keep this particular project local is a sensible way to get that same protection without the overhead.

The behavior you’re describing (treating “remote is ahead, don’t undo my edits” as a firm constraint and reconciling before any overwrite) is something our team is tracking and actively working to improve for agents on remote hosts. Reports like yours genuinely help push that forward.

You clearly get a lot of value out of Cursor locally, and I’d hate for these remote incidents to overshadow that. If you ever want to bring the remote workflow back, I’m glad to help you set it up so this can’t bite you the same way again.