post: The Tests Made a Case for Deleting the Shell Script_□×

The Tests Made a Case for Deleting the Shell Script

The installation helper for my MCP server prints a command to paste into a terminal. It reads a .env file and turns the entries into --env NAME=value arguments, with secret values redacted.

That sounds like a small shell task. The repair ended with the rendering code in Go, using the same dotenv parser as the server.

The tests were useful on the way there. They showed why a better shell script wasn’t the whole fix.

Redacting a few known names wasn’t enough

The original recipe used a sed expression with a short list of credential names. Anything outside that list could retain its value in the output, despite the banner saying secrets were redacted.

There was another problem before the redactor even ran. The expression selecting environment assignments was ^[A-Z_]+=, which excluded names containing digits. That dropped NEO4J_* entries before the redaction rule could see them.

Those are different failures. An incomplete secret-name list can expose a credential. Dropping an assignment produces an incomplete installation command. The presence of a redaction rule for NEO4J_PASSWORD didn’t help either way, because that row never reached it.

The replacement matched credential-related words in names and tested the output with synthetic secret values. That broadened coverage, but it also needed exceptions. Matching PAT anywhere would catch PATH and LOG_PATTERN, so personal-access-token names needed a more specific rule.

Names weren’t the only concern. A connection URL can contain a username and password even when its variable name contains no secret-related keyword. Name matching is a heuristic, not proof that the output contains no credentials.

The generated command had to survive the shell

Redacting a value also changed the syntax of the command being printed:

--env FOO=<redacted>

The angle brackets have special meaning to the shell. They aren’t harmless placeholder characters when left unquoted.

The output needed shell quoting around the argument, for example:

--env 'FOO=<redacted>'

Testing only whether the secret disappeared would miss that problem. The generated command also had to preserve non-secret values and remain valid shell input.

The recipe logic moved into a standalone script with tests. That made it easier to exercise quoting and redaction together. Inline recipes can be tested too; this one hadn’t had that coverage.

Two parsers for one configuration file

The larger issue was what happened before redaction.

The shell implementation parsed .env itself. The server used godotenv. The tests exposed differences in handling variable expansion, whitespace, empty assignments, names, indentation, and inline comments.

A renderer could pass its own tests and still print values different from those the server would read. Maintaining that second parser meant maintaining agreement with the first one.

The replacement moved rendering into the Go binary:

go run ./cmd/mem0-mcp --print-env-block .env

The binary already used godotenv. Reusing it removed a separate interpretation of the file.

That doesn’t make the entire configuration path identical. Environment precedence, redaction, and shell quoting still need their own tests. It does mean a change to dotenv parsing no longer has to be reproduced in an unrelated shell implementation.

Deleting the script was a useful result

The shell tests weren’t wasted because the script went away. They identified concrete disagreements and supplied cases the replacement still needed to handle.

The work started as a redaction fix, but the tests exposed a duplicate parser. Keeping the script would have meant owning that duplication as well as the rendering behavior.

The smaller responsibility is the one worth keeping: parse with the server’s parser, redact the output, quote it correctly, and test what the user will paste.

Sources

  • godotenv — the parser reused by the server and command renderer.
  • Bash quoting — preserving literal characters in shell arguments.

I’d appreciate a follow. You can subscribe with your email below. The emails go out once a week, or you can find me on Mastodon at @[email protected].

START
llbbl.exeprojects/posts/experiments/subscribe.dlg
© 2026v1.0.0