feat(cli): -f/--file prompt-file support (llama.cpp-compatible)#233
Conversation
Read the prompt from a file via -f/--file (llama.cpp's arg name), resolved once at the top of Execute into settings.Prompt so all downstream prompt paths work unchanged. Overrides -p when both are given; reads the file as-is (no trailing-newline stripping). A missing file errors loudly (exit 1) instead of running with an empty prompt. Motivation: prompts longer than the OS command-line length limit (~32K chars on Windows) can't be passed via -p — a long-context prompt blew the limit during #213 profiling. Verified: short file (30 tok), ~16K-token file (10460 tok prefilled, no "filename too long"), and missing-file clean error. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request introduces a new -f|--file option to load prompts from a file, overriding the -p|--prompt option. The review feedback highlights two main issues: potential markup parsing errors in Spectre.Console when rendering the file path, and unhandled I/O exceptions when reading the file. It is recommended to escape the file path and wrap the file read operation in a try-catch block to ensure graceful error handling.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| if (settings.PromptFile is { Length: > 0 } promptFile) | ||
| { | ||
| if (!File.Exists(promptFile)) | ||
| { | ||
| AnsiConsole.MarkupLine($"[red]Prompt file not found:[/] {promptFile}"); | ||
| return 1; | ||
| } | ||
| settings.Prompt = File.ReadAllText(promptFile); | ||
| } |
There was a problem hiding this comment.
There are two issues in this block:
- Spectre.Console Markup Parsing Error: If
promptFilecontains square brackets (e.g.,[path]),AnsiConsole.MarkupLinewill attempt to parse it as markup, leading to incorrect rendering or exceptions. UseMarkup.Escape(promptFile)to prevent this. - Unhandled I/O Exceptions:
File.ReadAllTextcan throw exceptions (e.g.,UnauthorizedAccessException,IOException) if the file is locked or permissions are insufficient. Wrapping it in atry-catchblock ensures the CLI exits gracefully with a clean error message instead of crashing with a stack trace.
if (settings.PromptFile is { Length: > 0 } promptFile)
{
if (!File.Exists(promptFile))
{
AnsiConsole.MarkupLine($"[red]Prompt file not found:[/] {Markup.Escape(promptFile)}");
return 1;
}
try
{
settings.Prompt = File.ReadAllText(promptFile);
}
catch (Exception ex)
{
AnsiConsole.MarkupLine($"[red]Error reading prompt file:[/] {Markup.Escape(ex.Message)}");
return 1;
}
}There was a problem hiding this comment.
Fixed: Markup.Escape on both the not-found and read-error messages, and File.ReadAllText is wrapped in try/catch (IOException/UnauthorizedAccessException/SecurityException/NotSupportedException) → clean message + exit 1. Verified a bracketed missing path renders correctly.
… (gemini) gemini MEDIUM: (1) AnsiConsole.MarkupLine would choke on a path containing Spectre markup chars ([ ]) — Markup.Escape the path in the not-found message and the read-error message. (2) File.ReadAllText I/O failures (locked/permissions/bad path) were unhandled (stack trace) — wrap in try/catch over IOException/UnauthorizedAccessException/SecurityException/ NotSupportedException, fail loud with a clean message + exit 1. Verified a bracketed missing path now renders correctly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Summary
Adds
-f/--file <path>to therunCLI (llama.cpp's arg name) to read the prompt from a file. Resolved once at the top ofExecuteintosettings.Prompt, so every downstream prompt path (single-turn, chat, format/template) works unchanged. Overrides-pwhen both are given; reads the file as-is (no trailing-newline stripping); a missing file errors loudly (exit 1).Motivation
A prompt longer than the OS command-line length limit (~32K chars on Windows) can't be passed via
-p— it fails with "The filename or extension is too long." This surfaced while profiling long-context decode (#213): a ~16K-token prompt couldn't be fed via-p.Verified (CLI)
Prompt file not found: …(exit 1).Build clean under TreatWarningsAsErrors + AOT. ~15 lines; self-contained.
🤖 Generated with Claude Code