- Status: accepted
- Date: 2026-07-29
scripts/setup_all.sh finished by calling scripts/setup_agent.sh all, which as
a side effect of "install this project":
- appended
[mcp_servers.dataflow]to~/.codex/config.toml, creating the file if absent - wrote
~/.cursor/mcp.json, guarded only by agrepfor the string"dataflow"— an existing user-level config with other MCP servers and nodataflowentry was overwritten wholesale - regenerated
AGENTS.mdand.cursor/rules/dataflow-pipeline.mdcfrom the canonical skill
Two distinct problems. First, a user running an installer to get a local tool did not ask for their home directory to be modified, and got no preview. Second, the Cursor path could destroy unrelated configuration.
There was also no way to express "install the backend but leave my agent setup
alone", which the harness profile needs.
Installing and configuring are separate commands.
./install.sh --profile harness # writes no agent config
./install.sh configure-agent --agent codex --scope user # explicit, previewedRules for configure-agent:
- Default scope is
project— writes only inside the repo (.mcp.json,.cursor/mcp.json).--scope useris required to touch$HOME. Codex is the exception: it reads only~/.codex/config.tomland offers no flag to redirect it, so--scope projectis rejected for Codex rather than writing a file that would be silently ignored. - Diff before write, always. For user scope, also a
y/Nprompt unless--yesis passed. - Merge, never replace, and only when the file can be parsed. Configs are
parsed with a real parser before any edit —
jsonfor Claude/Cursor,tomllib/tomlifor Codex. If no TOML parser is available, the command refuses and prints the block to add by hand rather than editing a file it cannot validate. Other servers and unmanaged keys inside thedataflowentry are preserved. - Refuse conflicts instead of resolving them. An existing
dataflowentry pointing at a different URL, or configured as acommand/stdio server rather than SSE, requires--force. Silently merging a URL into a stdio definition would produce a hybrid that is valid as neither. - Never touch credentials. No key is read, written or logged. Agents get credentials from the environment at run time.
- Idempotent. Re-running reports "no change" instead of rewriting.
Each profile manifest declares a must_not_touch list. install.sh fingerprints
every one of those paths before running any step — for a directory, that is the
content hash of every file underneath — and compares afterwards, failing on any
addition, deletion or modification. The boundary is asserted, not just documented.
./install.sh --profile <id> also defaults to --scope project, so installing
writes inside the repo unless the user passes --scope user.
Keep it automatic, add --no-agent-config. Safe behaviour should not be
opt-in; the default is what most users get.
Prompt during install. A prompt in the middle of a long install is easy to accept without reading, and it makes the installer non-scriptable.
Only ever write project scope. Codex genuinely reads ~/.codex/config.toml,
so a user-scope path has to exist. The answer is consent and a diff, not removal.
Good:
- installing cannot surprise a user by editing
$HOME - an existing MCP config with other servers survives
harnessandskillsprofiles become expressible- the boundary is enforced by an assertion in every install run
Costs:
- one extra command for users who did want everything configured. The installer's own "next steps" output names it
scripts/setup_agent.sh allno longer works; it now explains why and lists the per-agent commands. See the migration note