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.