claude: pass --settings as a file path (avoid argv length limit)

This commit is contained in:
müde 2026-05-15 18:12:07 +02:00
parent cf8f1e64b1
commit d8807b8e8c
3 changed files with 26 additions and 5 deletions

View file

@ -51,6 +51,18 @@ pub async fn write_mcp_config(socket: &Path) -> Result<PathBuf> {
Ok(path)
}
/// Drop the static `--settings` JSON next to the MCP config so we can
/// pass a path (`--settings <file>`) instead of an ever-growing inline
/// blob — the CLI argv has a finite length budget.
pub async fn write_settings(socket: &Path) -> Result<PathBuf> {
let parent = socket.parent().unwrap_or_else(|| Path::new("/run/hive"));
tokio::fs::create_dir_all(parent).await.ok();
let path = parent.join("claude-settings.json");
tokio::fs::write(&path, CLAUDE_SETTINGS).await?;
tracing::info!(path = %path.display(), "wrote claude settings");
Ok(path)
}
/// Write the agent's / manager's static system prompt to a file next to
/// the MCP config and return the path. Passed to claude via
/// `--system-prompt-file`, replacing claude's default system prompt with
@ -91,16 +103,17 @@ pub async fn drive_turn(
prompt: &str,
mcp_config: &Path,
system_prompt: &Path,
settings: &Path,
bus: &Bus,
flavor: mcp::Flavor,
) -> TurnOutcome {
match run_turn(prompt, mcp_config, system_prompt, bus, flavor).await {
match run_turn(prompt, mcp_config, system_prompt, settings, bus, flavor).await {
TurnOutcome::PromptTooLong => {
if let Err(e) = compact_session(bus).await {
if let Err(e) = compact_session(settings, bus).await {
tracing::warn!(error = %format!("{e:#}"), "compact failed");
return TurnOutcome::Failed(e);
}
run_turn(prompt, mcp_config, system_prompt, bus, flavor).await
run_turn(prompt, mcp_config, system_prompt, settings, bus, flavor).await
}
other => other,
}
@ -157,6 +170,7 @@ pub async fn run_turn(
prompt: &str,
mcp_config: &Path,
system_prompt: &Path,
settings: &Path,
bus: &Bus,
flavor: mcp::Flavor,
) -> TurnOutcome {
@ -164,6 +178,7 @@ pub async fn run_turn(
prompt,
mcp_config,
Some(system_prompt),
settings,
bus,
flavor,
ClaudeMode::Turn,
@ -179,7 +194,7 @@ pub async fn run_turn(
/// Run claude's built-in `/compact` slash command on the persistent
/// session so the next turn can fit. No MCP tools needed; we just feed
/// `/compact` over stdin and let claude rewrite its own history.
pub async fn compact_session(bus: &Bus) -> Result<()> {
pub async fn compact_session(settings: &Path, bus: &Bus) -> Result<()> {
bus.emit(LiveEvent::Note(
"context overflow — running /compact on the persistent session".into(),
));
@ -187,6 +202,7 @@ pub async fn compact_session(bus: &Bus) -> Result<()> {
"/compact",
Path::new("/dev/null"),
None,
settings,
bus,
mcp::Flavor::Agent, // tool surface unused for /compact
ClaudeMode::Compact,
@ -206,6 +222,7 @@ async fn run_claude(
prompt: &str,
mcp_config: &Path,
system_prompt: Option<&Path>,
settings: &Path,
bus: &Bus,
flavor: mcp::Flavor,
mode: ClaudeMode,
@ -219,7 +236,7 @@ async fn run_claude(
.arg("haiku")
.arg("--continue")
.arg("--settings")
.arg(CLAUDE_SETTINGS);
.arg(settings);
if let Some(p) = system_prompt {
cmd.arg("--system-prompt-file").arg(p);
}