{
  "id": 15057730,
  "title": "The Agent Rewrote the Shell Script in Python and Dropped the Exit Code",
  "url": "https://urgent.news/2026/10/16/the-agent-rewrote-the-shell-script-in-python-and-dropped-the-exit-code",
  "topic": "tech",
  "section": "Tech",
  "published": "2026-10-16T22:25:13.000Z",
  "source": {
    "name": "Dev.to",
    "slug": "dev-to",
    "url": "https://dev.to/jeff_pdc/the-agent-rewrote-the-shell-script-in-python-and-dropped-the-exit-code-m9n"
  },
  "original_language": "en",
  "account": "The build script was originally written in bash, consisting of 40 lines of code. It performed several tasks, including running npm test, running npm run build, syncing the dist folder to a server via rsync, and sending notifications on Slack. Although the script functioned as intended, nobody found it enjoyable to work with. One morning, the agent suggested rewriting the script in Python to enhance readability and testability. Surprisingly, the rewritten script produced similar output with the same steps, order, and messages. The script also passed the linter, satisfying the reviewer's requirements. Upon merging the changes, the CI pipeline reported a green build, despite the Python script continuing to run after encountering a failed command. The issue stemmed from an implicit failure mode present in the original shell script: the line set -euo pipefail. This single line instructed the script to stop executing immediately upon encountering any failed command. However, when the agent converted the script to Python, they omitted checking the return code, using check=True, or triggering an exit with a non-zero status code on failure. Consequently, the successful path remained unchanged, while the unsuccessful path was inadvertently eliminated. The process of porting the script from bash to Python unveiled a \"porting tax\" that does not manifest in a straightforward side-by-side comparison. When comparing the commands, they appear identical, and running the script functions correctly during periods of normal operation. The failures, on the other hand, are caused by the inherent features of the previous runtime environment, such as set -e, pipefail, unbound variable checks, and exit codes being propagated through pipes. The agent lacks the motivation to recreate these functionalities unless explicitly requested. To address this issue, the reviewer began requesting port rewrites with a specific instruction: listing the potential ways the old script could fail and ensuring that the new script still fails in the same manner. This process necessitates explicit effort from the agent and results in cleaner code that maintains the same failure modes as the original script. The same challenge arises when porting tasks from GitHub Actions steps to Makefiles, Makefiles to justfiles, or curl pipelines to SDK clients. The commands themselves remain intact, but the underlying guarantees are not preserved.",
  "summary": "The build script was 40 lines of bash. It ran npm test , then npm run build , then rsync the dist folder to a server, then paged us on Slack. It worked. Nobody loved it. One morning I asked the agent to port it to Python so it would be readable and testable. The output looked great. Same steps, same order, same messages. The linter was happy. I merged it. The first week, CI went green on a build…",
  "key_points": [],
  "editors_take": null,
  "illustration": null,
  "coverage": {
    "outlets": 1,
    "also_reported_by": []
  },
  "ai_generated": true,
  "disclaimer": "Summaries, key points and the editor’s take are written by software from other outlets’ reporting and may contain errors — always check the linked original."
}