articulate-writing 0.4.2
articulate-writing 0.4.2
The editor commands judge, fix and polish now find the claude CLI in
more setups, and the model call runs with no tools. Detector findings and the
ruleset fingerprint do not change.
The editor started the CLI by the bare name claude. That failed in two cases.
A process that an MCP host or a bundled app starts can inherit a PATH that
holds only System32. And on Windows, subprocess without a shell looks only for
claude.exe, so it never found the claude.cmd shim that an npm install puts
on the PATH. In both cases the start raised an uncaught FileNotFoundError.
- New module
articulate.claude_cliresolves the CLI. The environment variable
ARTICULATE_CLAUDE_CLInames its path and wins when set. Its value must be an
absolute path; a bare name or a relative path is refused. - Otherwise the resolver walks the absolute PATH entries itself. It takes
claude.exefrom any entry first, and aclaude.cmdorclaude.batshim
only when no entry holdsclaude.exe. So a setup that ranclaude.exe
before still runs it, whatever the PATH order. The current directory is never
searched, and neither is a.or empty PATH entry. On Windows,
shutil.whichlooks in the current directory first, so a document repo that
shipped a file namedclaude.cmdwould have run in place of the real CLI. - When nothing runnable is found, the editor raises
ClaudeUnavailable. Its
message names the variable and says the CLI must be installed and logged in.
A start that fails with anOSErrorraises the same error. No message prints
the value of the variable or the resolved path. A timeout message names only
claude. - The prompt now travels in a temporary file passed with
--append-system-prompt-file, on every path, and the file is removed after
the call. The argument list holds a fixed line, that path and fixed flags. A
prompt with many detector findings could pass the Windows command-line limit
of about 32K characters, which failed with a misleading "could not be
started" error. And a.cmdfile runs under cmd.exe, which cuts an argument
at the first newline and treats%,^,&,|,<,>and!as
commands. For a batch file, a path with one of those characters is refused. - Every call passes
--strict-mcp-config --tools "", so the model session has
no built-in tool and loads no MCP server. The document is untrusted input,
and before this change theclaude -pchild inherited the user's allow
rules and MCP servers. - A timeout now stops the whole process tree:
taskkill /F /Tby its System32
path on Windows, a process-group kill elsewhere. Before, a timeout on a batch
shim killed only cmd.exe and then waited for the CLI to finish. polishnow catches a judge failure inside its rewrite loop, such as a rate
limit halfway through, keeps the best version so far and exits cleanly.
Before, that failure ended in a traceback.
Changed for callers:
- The model's instructions now arrive as an appended system prompt, and the
user turn holds a fixed line. The trust boundary text still ends the
instructions, and the document stays on stdin. editor.CLAUDEis removed, and setting it has no effect. The variable
ARTICULATE_CLAUDE_CLInow names the CLI.editor.runis removed. A test double that patched it would now reach the
real CLI. A double now patchesarticulate.claude_cli.run.- A missing CLI raises
ClaudeUnavailable, aRuntimeError, where it used to
raiseFileNotFoundError, anOSError.ClaudeUnavailablemoved to
articulate.claude_cli;articulate.editorstill exports it. claude_cli.resolvereads PATH from theenvironmapping it is given.
Tests: tests/test_claude_cli.py and tests/test_claude_cli_process.py cover
the resolution order, a claude planted in the current directory, the closed
errors, the fixed argument list, every character cmd.exe reinterprets for both
.cmd and .bat, a 40,000-character prompt, and a timeout that must return
within 5 s while a grandchild sleeps. A parse of every source module checks
that no call asks for a shell. CI now also runs the suite on windows-latest,
where the stand-ins go through cmd.exe.
Not verified: a model reply through the batch path. A stand-in claude.cmd
around the real CLI 2.1.251 accepted the new arguments and reached the
backend, which answered with a credit error on the test machine.