{"slug": "prod-code-0-3-52-read-only-tools-that-say-so-and-failures-that-name-the-way-on", "title": "prod-code 0.3.52: read-only tools that say so, and failures that name the way on", "summary": "Prod-code v0.3.52 (commit 91ec5def, published 2026-11-05) adds readOnlyHint to 11 more MCP tools, including code_impact, code_diagnostics and code_validate_edit, so MCP hosts with an approval policy of never can call them instead of falling back to the command line. The release also outlines shell and assembly files without a language server and makes previously silent failures explain themselves, such as a command timeout with no output and an unreachable node now capped at 8 seconds per connect attempt. The changelog notes the Swift rename fix only reports files still containing the old name rather than closing the gap, and that standard input is still not forwarded to the node.", "body_md": "# prod-code 0.3.52: read-only tools that say so, and failures that name the way on\n\nMore tools declare in the MCP catalog that they never write, shell and assembly files get outlines without a language server, and silent failures now explain themselves. Built and signed by a hosted workflow using Mitts; generated Rust commands still run cargo.\n\n## On this page · 8 sections\n\nMost of [prod-code v0.3.52](https://github.com/alex09x/prod-code/releases/tag/v0.3.52)\n(commit `91ec5def`, published 2026-11-05) fixes cases where a call failed without giving a\nreason, or reported success when it had not done the work. This post follows the `v0.3.52`\nsection of the\n[changelog at the tag](https://github.com/alex09x/prod-code/blob/v0.3.52/CHANGELOG.md); each\nitem below carries its issue number. The Zenodo citation for prod-code is still the\n[v0.3.49 record](https://doi.org/10.5281/zenodo.23905176). There is no archived v0.3.52 version\nyet.\n\n## Read-only tools say so\n\nAn MCP host whose approval policy is `never` refuses any tool it cannot tell is read-only\n(`MCP tool call requires approval, but approval policy is never`), and the agent falls back to\nthe command line. Until this release only the navigation tools carried `readOnlyHint`. Eleven\nmore now carry it: `code_impact`, `code_diagnostics`, `code_validate_edit`,\n`code_validate_edits`, `code_assists`, `code_dead_code`, `code_dependencies`,\n`code_find_duplicates`, `code_structural_search`, `code_propose_expression` and `code_status`.\nTools that write, run a command, or are read-only only for some arguments stay unmarked. A test\nchecks the marked list against the server’s own definition of a read-only tool (#1887, #1890,\n#1900, #1905).\n\n## Files without a language server\n\nNo language server answers a shell symbol. `code_definition NAME` now finds a function defined\nin a `.sh`, `.bash` or `.zsh` script, with its body. If two scripts define the same name, both\nare listed as candidates instead of one being guessed (#1940). A shell script’s outline is now\nread from the file itself. It covers all three function forms, and it skips comments and\nhere-document bodies. `.s`, `.S` and `.asm` files are outlined the same way, from `.globl`\nsymbols, labels and `.macro` definitions (#1851, #1935). An outline that is read from the file\nno longer asks the cluster for a node that serves its language. A directory outline that mixes\nlanguages outlines what it can reach, and counts the files of an engine that did not start as\nskipped (#1898).\n\n## Failures that explain themselves\n\n- **A silent timeout.** A command runs on the node with standard input closed and no terminal.\nOne that waits for a login, a browser or a prompt therefore waits until its deadline and\nprints nothing. When a command times out with no output, the report now says why and suggests\na non-interactive option or another place to authenticate (#1892).\n- **Dropped standard input.**`prod-code exec -- python3 - <<'PY' … PY` used to run an empty\nprogram on the node and report success, because the command line does not carry standard\ninput to the node. When input is waiting,`exec` now stops before anything runs. It suggests\nputting the program in a file in the checkout or passing it as an argument. Standard input is\nstill not forwarded (#1944).\n- **An unreachable node.** Connecting to a node that does not answer used to take three\noperating-system connect timeouts in a row and end in a bare “timed out”. Each attempt now\nwaits at most 8 seconds. The error names the node and points to`prod-code status` ,`--remote` or`--pin-node` (#1938).\n- **A Swift rename that missed files.** sourcekit-lsp renames only what its index knows, and a\ncall in another file is not indexed until the target is built.`code_rename` used to report\nsuccess anyway. It now lists the Swift files that still contain the old name, with the advice\nto build and rename again (#1953). This reports the gap; it does not close it.\n\n## Answers about the right checkout\n\n`code_impact` now accepts the same `workspace` selector as `code_exec` and the read tools. From\na PR worktree, the report covers that worktree’s diff. Before, it described the configured\ncheckout: 290 changed files for a two-file change (#1939). It also stops naming\n`swift test` for Swift tests in an Xcode project without a `Package.swift`, and reports that\ngroup as unsupported (#1951). `code_source` now reads a dependency’s source when `workspace` is\nset; paths with `..` are still refused (#1955).\n\n## Smaller changes\n\n- Moving a private Rust item into a sibling module now makes it `pub(crate)` when another module\nstill names it, and the move report says so (#1933).\n- Files that an `exec` creates on the node’s copy, such as a scratch script or a generated\nframework, are no longer deleted by the next connection’s sync (#1895, #1888).\n- A tracked symlink that the node will not create is now a warning. It used to be an error that stopped every command in the workspace (#1889).\n\nNothing was removed. The release makes two behaviours stricter or quieter on purpose: `exec`\nrefuses input it would drop, and the symlink error is now a warning.\n\n## How the release itself was built\n\nThis is the first prod-code release whose binaries were built, signed and published by a GitHub\nActions workflow on standard hosted runners (#1852). The workflow builds with\n[Mitts](https://prod.codes/projects/mitts/), the author’s Rust build tool, and CI runs formatting, Clippy and the\ntests through it. The release run for the tag took about 30 minutes. The Linux ARM64 build took\n13 minutes, Linux x86-64 16 and macOS ARM64 28, then signing and collection ran. The release\npage lists six binaries, the client and the server for Linux x86-64, Linux ARM64 and macOS ARM64,\nplus `SHA256SUMS`. The macOS binaries are Developer ID signed and Apple notarized. I checked each\nline of `SHA256SUMS` against the digest GitHub records for that asset, and all six match.\n\nCI previously ran each shard’s test targets one after another without a concurrency flag. Now\neach shard passes `--concurrency` (#1930). The last full-workspace run before the tag is recorded\nin [PR #1956](https://github.com/alex09x/prod-code/pull/1956), after which only the version bump\nfollowed. On one 32-core Linux x86-64 node, `mitts test --workspace --no-fail-fast -c` ran 5569\ntests in 663 seconds. All 5569 passed and 23 were skipped.<sup>[1](#user-content-fn-1)</sup> Two tests that read the machine’s Cargo crate cache were rewritten so that they pass\nwith an empty `CARGO_HOME` (#1930). A stack-depth failure in the Go signature tests and a race\nin the hot-reload drain were also fixed (#1941, #1814).\n\n## What did not change\n\nMitts builds and tests prod-code itself. The commands prod-code generates for a user’s Rust\nproject are different: `code_test`, `code_check` and `code_lint` still run `cargo`. In\n`verify/plan/basic.rs` at the tag, a Rust test is still `cargo test --workspace`. Switching\nthem was tried and reverted before the release. As\n[PR #1952](https://github.com/alex09x/prod-code/pull/1952) records, Mitts rejects `--quiet` and\nspells `check` differently, and 147 tests failed. A setting to choose another runner per project\nis not part of this release.\n\n## Footnotes\n\n1. \nThe changelog at the tag gives 5553 tests in 660 seconds for #1930. That entry was written before #1954 and #1956 added tests. The tag cannot change, so its changelog keeps the older figure; the entry on prod-code’s main branch is being corrected to match PR #1956. [↩](#user-content-fnref-1)\n\n## Cite this article\n\n```\nAlexander Panasenko (2026-11-06). prod-code 0.3.52: read-only tools that say so, and failures that name the way on. https://prod.codes/blog/prod-code-0-3-52-failures-that-name-the-way-on/\n```\n\n", "url": "https://wpnews.pro/news/prod-code-0-3-52-read-only-tools-that-say-so-and-failures-that-name-the-way-on", "canonical_source": "https://prod.codes/blog/prod-code-0-3-52-failures-that-name-the-way-on/", "published_at": "2026-11-06 00:00:00+00:00", "updated_at": "2026-11-06 11:51:25.402826+00:00", "lang": "en", "topics": ["ai-tools", "ai-agents", "agent-protocols", "developer-tools"], "entities": ["prod-code", "MCP", "Mitts", "sourcekit-lsp", "Zenodo", "alex09x"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/prod-code-0-3-52-read-only-tools-that-say-so-and-failures-that-name-the-way-on", "markdown": "https://wpnews.pro/news/prod-code-0-3-52-read-only-tools-that-say-so-and-failures-that-name-the-way-on.md", "text": "https://wpnews.pro/news/prod-code-0-3-52-read-only-tools-that-say-so-and-failures-that-name-the-way-on.txt", "jsonld": "https://wpnews.pro/news/prod-code-0-3-52-read-only-tools-that-say-so-and-failures-that-name-the-way-on.jsonld"}}