Remote inference is a spillway, not a default pipe. The local disk already holds the working loop. You open the wire after three gates pass.
Latency looks like the loudest cost on paper. Secrets and offline gaps still cost far more. A fast hop still leaks when the payload is dirty.
Think hydrology, not a vendor roadmap slide. Your laptop is a reservoir with a known rim. The network is a spillway that leaves the watershed.
You do not lift that gate for a quicker looking river. Speed outside the watershed is still water leaving home.
This article is a proposed workflow, not a field study. The script below is runnable on Node 18. Printed timings belong only to your local machine.
Three separate costs share one fail-closed local decision. The first cost is round-trip time on the wire. The second cost is secret surface inside the prompt.
The third cost is work that must finish offline. Offline is not a percentile the way latency is. Either the next tool can run, or it cannot.
Pretty uptime graphs do not move that binary. A train tunnel still zeros the entire path.
Most teams still optimize the first cost only. That habit treats the cloud as a shorter path. It is often a longer path with extra copies.
A secret does not care about milliseconds at all. A private key in a prompt is already gone. Pretty links still fail an offline compile step.
Gate one reads the payload before any socket opens. It searches for private-key banners and cloud identifiers. A single hit keeps the reservoir fully closed.
Gate two asks if the next action needs a model. Lint, test, and hash do not need remote tokens. Those steps should never pay a network hop.
Gate three estimates local pressure from file size. This is a labeled heuristic, not a published benchmark. Large clean context can justify a later spill.
Small clean context should remain on local disk. Do not spill a rename because a server is idle.
The composite rule stays fail closed under pressure. Secrets always win the argument against raw latency. Offline need always wins against mere chat convenience.
Only a clean, heavy, online-tolerant job may spill. That is the narrow case a free server can serve. Everything else remains a local disk loop instead.
The analogy stays strict when the queue grows. Flooding a valley to save one minute is still a flood. Copying a dotenv file into a chat is that flood.
Round-trip time also hides queue delay on shared servers. Your local hash does not wait behind strangers. That difference rarely appears on a homepage chart.
Here is a proposed Node gate you can run. Save it as spillway-test.js beside a prompt file. Pass the file path as the first argument.
#!/usr/bin/env node
'use strict';
const fs = require('fs');
const crypto = require('crypto');
const { performance } = require('perf_hooks');
const SECRET_RE = [
/-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/,
/AKIA[0-9A-Z]{16}/,
/(?:^|\n)(?:API[_-]?KEY|SECRET|TOKEN|PASSWORD)\s*=\s*\S+/i,
/ghp_[A-Za-z0-9]{36}/,
/xox[baprs]-[A-Za-z0-9-]{10,}/,
/eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\./,
];
function leakHits(text) {
let n = 0;
for (const re of SECRET_RE) {
if (re.test(text)) n += 1;
}
return n;
}
function pressureOf(bytes) {
// Proposed bands only. Tune them on your disk.
if (bytes > 2_000_000) return 'high';
if (bytes > 200_000) return 'mid';
return 'low';
}
function decide(hits, pressure, offlineRequired) {
if (hits > 0) return 'HOLD';
if (offlineRequired) return 'HOLD';
if (pressure === 'high') return 'SPILL';
return 'HOLD';
}
function sha256(buf) {
return crypto.createHash('sha256').update(buf).digest('hex');
}
function main() {
const file = process.argv[2];
const offlineRequired = process.argv.includes('--offline');
if (!file) {
console.error('usage: node spillway-test.js <prompt-file> [--offline]');
process.exit(2);
}
const t0 = performance.now();
const buf = fs.readFileSync(file);
const text = buf.toString('utf8');
const digest = sha256(buf);
const t1 = performance.now();
const hits = leakHits(text);
const pressure = pressureOf(buf.length);
const verdict = decide(hits, pressure, offlineRequired);
const report = {
file,
bytes: buf.length,
sha256: digest,
local_read_ms: Number((t1 - t0).toFixed(3)),
leak_hits: hits,
pressure,
offline_required: offlineRequired,
verdict,
note: 'Unexecuted remote hop. Local gate only.',
};
console.log(JSON.stringify(report, null, 2));
process.exit(verdict === 'HOLD' ? 1 : 0);
}
main();
Run the gate on a dry file first. Then run it on a file that should fail. Compare the two JSON objects, not gut feel.
printf 'refactor the parser, keep tests green\n' > /tmp/clean.prompt
node spillway-test.js /tmp/clean.prompt; echo exit:$?
printf 'TOKEN=ghp_%s\n' "$(printf 'a%.0s' {1..36})" > /tmp/dirty.prompt
node spillway-test.js /tmp/dirty.prompt; echo exit:$?
node spillway-test.js /tmp/clean.prompt --offline; echo exit:$?
The clean file should print HOLD with low pressure. Size stays small, so the spillway remains shut. That default HOLD is the design, not a bug.
The dirty file should print HOLD as well. Leak hits rise above zero and override size. A non-zero exit lets nearby scripts fail closed.
The offline flag forces HOLD on huge clean files. Train that path before any travel day starts. An airport queue is a poor discovery moment.
Local read time is a baseline, not a contest. It records how cheap a disk already is. Skip vendor slides when you have this number.
A remote hop is absent from this script on purpose. Opening a socket would teach the wrong operational lesson. Measure the wire later, after HOLD feels boring.
A free server wins only after three checks agree. Leak hits must stay at zero on the payload. Offline mode must be false for that job.
Pressure must read high because local work cannot finish. That last clause is the whole economic test. High pressure means the machine cannot complete the step.
It does not mean a chat box sat closer than the terminal. Proximity of a text field is not capacity. Capacity is whether the local reservoir already overflowed.
Lint belongs on disk for the entire loop. A unit test belongs on disk as well. A two-kilobyte rename never earns a spillway opening.
Large secret-free context that saturates local memory may spill. Treat the remote box as overflow plumbing only. Pull the result back, then close the gate again.
Disclosure: This article was prepared as part of MonkeyCode's product outreach. MonkeyCode offers free model access and a free server option. Use that option only after this gate prints SPILL.
The copy still leaves disk, with ordinary third-party limits. Do not treat free as a frictionless default path. Free compute does not erase data residency rules.
Free does not replace a real secret scanner. Keep a dedicated scanner in the same export path.
Limitations of this gate are concrete and narrow. Regular expressions miss novel secret shapes every week. File size is a blunt stand-in for RAM and CPU.
The script never proves a model was required. False HOLD remains an acceptable operational miss. False SPILL is not an acceptable operational miss.
Tune size bands upward when prompts are large and dull. Do not tune bands downward just to feed a server. Raw convenience is not a pressure reading.
Some readers should reject the spillway path entirely. Do not use it if law forbids third-party inference. Do not point it at production dumps or customer exports.
Do not treat it as a scanner for key material. Those files should never approach a prompt assembler. Local deletion is safer than a clever HOLD.
Air-gapped teams should skip remote tokens as a class. The reservoir is the product in that environment. A free server becomes a policy incident there, not a shortcut.
Keep the exit code in any prompt export path. A non-zero HOLD should block the copy step. Latency arguments do not override that local block.
A one-line wrapper can block clipboard export tools. Read the verdict before any HTTP client loads. That ordering is the entire local control plane.
The core conclusion does not move after the demo. Remote tokens remain a spillway under every clock. Local loops remain the reservoir that owns secrets.
Offline need keeps the gate closed without debate. If the loop already lives on disk, keep running this gate. Open a free spillway only when the JSON verdict reads SPILL.
Top comments (0)