CLI: concurrent `obsidian eval` calls leak stdout between processes

Steps to reproduce

Run two obsidian eval commands concurrently — one slow (await sleep(1000)), one fast (immediate return).

Shell (Linux/macOS)

cd /path/to/vault
obsidian eval --allow-focus-steal 'code=(async () => { await sleep(1000); return "SLOW"; })()' > /tmp/slow.txt 2>&1 &
SLOW_PID=$!
obsidian eval --allow-focus-steal 'code="FAST"' > /tmp/fast.txt 2>&1 &
FAST_PID=$!
wait "$FAST_PID" 2>/dev/null || true
wait "$SLOW_PID" 2>/dev/null || true
echo "Fast:"; cat /tmp/fast.txt
echo ""; echo "Slow:"; cat /tmp/slow.txt

PowerShell (Windows)

cd \path\to\vault
$vaultPath = (Get-Location).Path
$slowJob = Start-Job -ScriptBlock {
  param($cwd); Set-Location $cwd
  & obsidian eval --allow-focus-steal 'code=(async () => { await sleep(1000); return "SLOW"; })()' 2>&1
} -ArgumentList $vaultPath

$fastJob = Start-Job -ScriptBlock {
  param($cwd); Set-Location $cwd
  & obsidian eval --allow-focus-steal 'code="FAST"' 2>&1
} -ArgumentList $vaultPath

$fastJob | Wait-Job -Timeout 15 | Out-Null
$slowJob | Wait-Job -Timeout 15 | Out-Null

Write-Host "Fast:"; ($fastJob | Receive-Job) -join "`n"
Write-Host ""; Write-Host "Slow:"; ($slowJob | Receive-Job) -join "`n"
Remove-Job -Job $fastJob, $slowJob -Force -ErrorAction SilentlyContinue

Did you follow the troubleshooting guide? [Y/N]

Y

Expected result

Each process should only see its own output:

Fast:
=> FAST

Slow:
=> SLOW

Actual result

The slower eval’s stdout contains a Received CLI command log line that belongs to the faster eval:

Fast:
=> FAST

Slow:
Received CLI command ["eval","--allow-focus-steal","code=\"FAST\""]
=> SLOW

Reproduced 5/5 times in a loop.

Environment

SYSTEM INFO:
	Obsidian version: 1.12.7
	Installer version: 1.12.7
	Operating system: Windows 11 Pro 10.0.26200
	Login status: logged in
	Language: en
	Catalyst license: vip
	Insider build toggle: on
	Live preview: on
	Base theme: adapt to system
	Community theme: none
	Snippets enabled: 0
	Restricted mode: off
	Plugins installed: 0
	Plugins enabled: 0

RECOMMENDATIONS:
	none

Additional information

The IPC channel appears to broadcast messages to all connected CLI processes rather than routing them to the originating process. When two eval processes overlap, the slower one receives log lines (Received CLI command [...]) from the faster one.

This causes issues for tools that programmatically parse obsidian eval stdout. If the leaked output includes a => result line from another eval, consumers that select the last => line will parse the wrong result.

Suggested fix

Assign a unique identifier (e.g., a UUID) to each CLI connection. When Obsidian sends IPC messages back (log lines, => results), tag them with the originating connection’s ID. The CLI process then filters stdout to only include messages matching its own ID. This ensures each process sees only its own output, regardless of how many concurrent connections exist.

1 Like