You should never place your everyday working tree on a free remote coding server, because that tree is a suitcase, not a clean source drop. The chat box is only the label on the suitcase, while the checkout underneath still carries remotes, ignored files, and local notes. If a model or a helper process can read the directory, you have already shared whatever the directory still holds. Start from that boundary, and only then decide which files a scrubbed mirror is allowed to contain.
A borrowed desk in a shared office is a useful picture for the choice you are about to make. You would not unpack your whole backpack onto that desk just because the desk is free for the afternoon. You would take out the one notebook page the task actually needs, and you would leave the house keys in your bag. A remote coding server works the same way, even when the invoice is zero and the model calls are included.
Your working tree is packed for you, not for a stranger's process that you do not administer. Git still remembers remote URLs, and some of those URLs embed a token or a username that should never leave your machine. Files you gitignored on purpose, such as env files and local databases, stay readable by any tool you point at the folder. Editor swap files, IDE folders, and stray notes beside the code still travel if you copy the directory as it sits.
Uncommitted diffs are a quieter problem, because a deleted line can still hold a password you thought you had already removed. That leak is different from typing a secret into a prompt, and it is different from pasting a log into a chat window. Those mistakes happen in the message you compose, while this mistake happens before you type, when the server receives a checkout. You can write a careful prompt and still fail, if the agent may list the directory, open git config, or search ignored files.
Treat the directory listing as the real request, and treat the prompt as a comment written beside that request. Build the mirror on your own machine, before any remote process is allowed to exist at all. If the task depends on an uncommitted patch, review that diff locally and copy only hunks that survive the same gate. Do not use your normal clone as the source of that copy, because a normal clone keeps the remote URL and the object store.
A tracked-file archive gives you source text without the old remote configuration, because the archive does not include the git directory. An archive of HEAD is narrower than a folder copy, because ignored files and untracked notes stay behind on the laptop. Confirm that difference with git status showing ignored files before you treat the mirror as complete. You still need the gate, because tracked files themselves can hold a token that a careful commit should never have stored.
The gate below is an unexecuted example you can save as bundle_gate.py and run locally before any upload. It is a teaching gate, not a certified scanner, and it will miss secret formats it has never been shown. Extend the patterns for names your team actually uses, and keep the file outside any bundle you plan to scan. Run it on a fixture that must fail, and run it again on the mirror that must pass, before you copy anything.
#!/usr/bin/env python3
'''Example gate: refuse a context bundle that still looks like a laptop tree.
Not executed in this article. Extend patterns for your own naming scheme.
'''
import re, sys
from pathlib import Path
HOT = re.compile(
r'(?i)(api[_-]?key|secret|password|token|BEGIN (RSA |OPENSSH )?PRIVATE KEY)'
)
REMOTE_TOKEN = re.compile(r'https?://[^ /:]+:[^ /@]+@')
SKIP = {'.git', 'node_modules', 'venv', '.venv', 'dist'}
def walk(root: Path):
findings = []
for path in root.rglob('*'):
if any(part in SKIP for part in path.parts):
continue
if path.name in {'.env', '.env.local', 'id_rsa', 'id_ed25519'}:
findings.append(f'blocked name: {path}')
continue
if not path.is_file() or path.stat().st_size > 1_000_000:
continue
try:
text = path.read_text(encoding='utf-8', errors='ignore')
except OSError:
continue
if HOT.search(text) or REMOTE_TOKEN.search(text):
findings.append(f'blocked text: {path}')
return findings
if __name__ == '__main__':
root = Path(sys.argv[1] if len(sys.argv) > 1 else '.')
hits = walk(root)
if hits:
print(chr(10).join(hits))
sys.exit(1)
print(f'bundle ok: {root}')
Pair that script with a short command sequence you run in a scratch directory, not inside the original repository. The first command lists remote URLs so you can see a token before anything moves off the laptop. The next commands build a tracked-only archive, unpack it with no remote, and stage a separate fixture that must fail. Keep the gate script outside both folders, because the script itself contains the words it is trying to catch.
# Unexecuted example. Fixture must fail; mirror must pass.
# Keep bundle_gate.py outside both directories.
SRC="${SRC:-$HOME/src/your-repo}"
MIRROR="${MIRROR:-$HOME/tmp/scrubbed-mirror}"
FIXTURE="${FIXTURE:-$HOME/tmp/gate-fixture}"
rm -rf "$MIRROR" "$FIXTURE"
mkdir -p "$MIRROR" "$FIXTURE"
git -C "$SRC" config --get-regexp 'remote\..*\.url'
git -C "$SRC" status --ignored --short
git -C "$SRC" archive --format=tar HEAD | tar -x -C "$MIRROR"
echo 'API_TOKEN=fixture-not-real' > "$FIXTURE/.env"
python3 bundle_gate.py "$FIXTURE"; echo "fixture exit:$?"
python3 bundle_gate.py "$MIRROR"; echo "mirror exit:$?"
Read the gate output as a decision, not as a suggestion you can override because the afternoon is already short. A blocked name means that file stays on your laptop, even if you believe the value inside it is stale. A blocked text hit means you open the file locally, replace the value with a fixture, and run the gate again. Only a clean exit is permission to copy the mirror onto remote compute, and bargaining with that result means you stop.
Disclosure: This article was prepared as part of MonkeyCode's product outreach. MonkeyCode's free model access and free server option matter here only as a place to practice that gate on a scrubbed mirror. Do not treat those options as a stated quota, a hardware shape, a retention window, or a promise that the free tier stays fixed. Those details belong in the current product documentation, which you should read before you rely on either option.
Use the free server as a second pair of eyes on the mirror, not as a vault for the original checkout. Point the model at the scrubbed tree and ask it to explain a failing test or to draft a patch against fixture data. Ask it, in the same session, to list any file that still looks like a secret, and compare that list with your gate. Do not rely on the model to notice that a checkout is sensitive, because refusal is not a control you can audit.
If the model finds a miss or invents a hit, fix or tune the script before you trust it on the next mirror. Keep a small fixture repo whose only job is to prove the gate still fails closed when a fake secret appears. Put a fake token in a comment, a fake remote URL in a sample config, and a dot-env file that must fail. Run the gate on that fixture and require a nonzero exit, then run it on the real mirror and require a zero exit.
That pair of results is the artifact you can show a teammate, and it does not depend on any vendor remaining free. This approach is the wrong tool when the tree holds customer records, payment data, health data, or other regulated material. A regex gate will miss a split secret or a binary, and it will also flag the plain word token in a comment. A depth-limited archive also drops history on purpose, so do not fix that gap by uploading the full object store instead.
If your task needs production credentials in order to run, a free remote server is the wrong place to run that task. You should also skip this workflow when you cannot name the trust boundary in one plain sentence. If you do not know who operates the server, where logs go, or whether a human can open the workspace, keep the mirror local. Free access is a budget fact, not a security review, and a missing review is a reason to wait.
Practicing the gate on a laptop, with no network call at all, is still a useful afternoon when the remote path is unclear. When the boundary is clear and the tree is dull on purpose, the free options are a reasonable classroom for the habit. Build the mirror, fail the fixture, pass the scrub, and only then open the remote box against that dull tree. If you already use MonkeyCode, rehearse that sequence on a throwaway repo before the free server sees a real tree.
Top comments (0)