* fix(battery): render a detected battery at 0% instead of disabling the segment
Enabled() treated err == nil && Percentage == 0 as a "no battery"
sentinel, but every platform backend already signals "no battery"
through a dedicated error (NoBatteryError/ErrNotFound) before that
point is reached. A present battery genuinely reporting 0% charge
was therefore hidden instead of rendered.
Also guard against a nil Info dereference on the display_error path,
where BatteryState() returns (nil, err) for any non-NoBatteryError.
Fixes#7782
* fix(battery): reorder test struct fields to satisfy fieldalignment
CI's fieldalignment check flagged the new test's table-driven struct
for avoidable padding: bool fields interspersed between the pointer
and interface fields moved the last pointer field to the very end,
inflating the GC-scanned pointer prefix from 48 to 56 bytes.
---------
Co-authored-by: Claude <noreply@anthropic.com>
* fix(cache): refresh serve daemon's cache from disk each render cycle
The `serve` daemon (used by streaming mode) loads the on-disk Session
and Device caches once at startup and only flushes them back on exit,
so a write from a separate one-shot process was invisible to the
running daemon until it restarted, and could even be clobbered by the
daemon's own stale copy on shutdown. This affected `oh-my-posh toggle`
(Session store) as well as `enable`/`disable` - e.g. `enable reload`,
which config.Get in prompt.New checks to bypass its own config cache
after an edit (Device store). Fixes#7758.
Add cache.Refresh(), which re-syncs the in-memory store from disk when
the file's mtime has advanced, merging entries by Timestamp so a value
the daemon has itself set more recently than the file always wins.
Call it for both stores at the start of every render cycle in
serve.go, and once more before close() persists a dirty store, closing
the shutdown clobber window too. Drop the Session-only guard on the
mtime bump in store.close() so a Device write reliably updates the
file's mtime on Windows as well (the mmap-backed write path doesn't do
this on its own).
Also documents the residual limitation (there's still a narrow window
where a write can land mid-cycle) in the streaming docs.
* fix(cache): reorder store fields to satisfy fieldalignment
Adding mtime widened the struct's pointer-scannable prefix from 40 to
56 bytes (the time.Time's trailing *Location pointer landed after the
three trailing bools). Reorder so pointer-bearing fields lead and the
bools trail, matching what CI's fieldalignment check expects.
---------
Co-authored-by: Claude <noreply@anthropic.com>
.Executed only turned false when the shell started, never again after
the first real command ran, so pressing enter on an empty line kept
the status segment visible. pwsh, zsh and fish already re-evaluate it
every prompt; bring clink, bash and nushell in line:
- clink: command_executed_mark now sets no_exit_code from the current
input instead of only ever clearing it.
- bash: _omp_hook resets _omp_no_status=true before checking whether a
command actually started, mirroring the zsh precmd hook.
- nushell: derive --no-status from whether history actually grew this
prompt cycle instead of the one-shot CMD_DURATION_MS startup
sentinel, which can't observe anything after the first command.
Fixes#7757
Claude-Session: https://claude.ai/code/session_018AhjcGCfxm2mFCfZhehLhv
Co-authored-by: Claude <noreply@anthropic.com>
* feat(template): add cmd function to run OS commands from templates
Adds a `cmd` template function that calls env.RunCommand() and
returns trimmed output, enabling users to incorporate arbitrary
command output into any segment template.
Example usage:
{{ cmd "who" | splitList "
" | len }}
{{ cmd "git" "log" "--oneline" "-1" }}
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chore: restore apm.lock after apm install on session create
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chore: restore apm.lock after apm install in setup steps
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(template): fix field alignment in exec_test.go
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* docs(template): add security warning to cmd helper
Warn that cmd executes arbitrary OS commands as the current user and
should only be used with trusted themes/configs.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* refactor(template): rename exec to cmd
Rename exec.go -> cmd.go and exec_test.go -> cmd_test.go to match the
template function name. Also rename TestExec -> TestCmd.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chore: add github-app.yml
* feat(template): add localeShortDate and localeShortTime functions
resolves#7481
* feat(segment): add FiveHourResetsAt and SevenDayResetsAt template methods
resolves#7480
* docs: fix typo in Wakatime and Brewfather
* perf(git): parallelize git segment shell-outs to reduce prompt latency
* feat(theme): revamp tiwahu theme segments and styling
Squash recent tiwahu theme updates into a single commit for PR review.\n\nIncludes git segment refinements, language segment styling updates, docker segment additions, and az template fix.
* fix(template): add //go:build windows constraint to locale_windows.go
Without this tag both locale_unix.go and locale_windows.go were compiled
on non-Windows platforms, causing the Windows init() to override the Unix
resolver and leaving localeShortDate/Time always at their defaults.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Shubham Bawari <shubhambawari123@gmail.com>
Co-authored-by: Matthew Rothenberg <mroth@mroth.xyz>
Co-authored-by: Tim Huber <thuber@tiwahu.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: handle named numeric types in gt/lt template functions
The custom gt() function in src/template/compare.go used direct type
assertions (e.g. e1.(int)) which fail for named types like text.Percentage
(type Percentage int). This caused \{{ if gt .TokenUsagePercent 50 }}\
in background_templates to always evaluate to false.
Add a reflect.Value.Kind() fallback in gt() to handle any named type
whose underlying kind is int, uint, or float. Also update toNumeric()
in src/generics/convert.go with the same fallback so the reverse case
\{{ if gt 50 .TokenUsagePercent }}\ works correctly too.
Add regression tests for text.Percentage in TestGt and TestLt.
Fixes#7299
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: avoid int64 overflow for uint types in gt() reflect fallback
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When TERM_PROGRAM=vscode, VS Code's shell integration adds
__vsc_prompt_cmd_original to PROMPT_COMMAND, which wraps PS1 with
A/B escape sequences (\e]633;A\a / \e]633;B\a) for command boundary
detection.
With append order (introduced in v28.1.1), _omp_hook runs after
__vsc_prompt_cmd_original and overwrites PS1 without those sequences,
causing VS Code and GitHub Copilot Agent to lose track of command
completion.
Detect TERM_PROGRAM=vscode and prepend _omp_hook in that case so it
sets PS1 before VS Code wraps it. All other environments retain the
append behavior.
Fixes#7029
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: streaming placeholder not updated when async is enabled
When both async and streaming are configured on ZSH, the init command
becomes 'precmd() { source <script> }', which re-sources the script on
every prompt cycle. This unconditionally reset _omp_stream_fd=-1, causing
_omp_cleanup_stream to skip closing the previous cycle's stream fd.
The stale stream's EOF handler would later call _omp_cleanup_stream using
the global _omp_stream_fd (now pointing to the new stream's fd) and kill
the new stream before it could send any updates. The placeholder never
got replaced.
Three fixes:
1. init.go: Skip async sourcing when streaming is also active. Streaming
provides its own async update mechanism; re-sourcing on every precmd is
not needed and conflicts with the streaming fd lifecycle.
2. omp.zsh (_omp_stream_fd init): Use \ so a
re-source does not clobber an in-flight stream fd.
3. omp.zsh (_omp_async_handler): On EOF, close only the specific fd that
triggered the handler instead of calling _omp_cleanup_stream. This
prevents any stale handler from closing the current stream's fd even if
the global variable has diverged.
Fixes#7313
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(zsh): streaming placeholder not updated when async is enabled
When both async and streaming are configured in ZSH, the omp.zsh script
is re-sourced before every prompt cycle via the async init mechanism
(precmd() { source <script> }). Top-level variable assignments in the
re-sourced script run unconditionally, so _omp_stream_fd was reset to -1
on every prompt cycle even while a live stream was in flight.
This caused two problems:
1. _omp_cleanup_stream skipped cleanup (fd -1 < 0) before starting the
new stream, leaking the old fd and its ZLE handler.
2. The stale EOF handler later fired, saw _omp_stream_fd pointing at the
NEW stream, and closed it so the placeholder was never replaced.
Fix 1: use _omp_stream_fd=\ (ZSH := modifier) so
the fd value survives a re-source, initialising to -1 only when the
variable is genuinely unset (first source at shell startup).
Fix 2: in _omp_async_handler, guard the EOF cleanup with
[[ \ -eq \ ]] so a stale handler from a previous
prompt cycle can never close the current stream's fd.
Reverts the init.go change from the previous commit changing the
async sourcing mechanism is unnecessary and caused a regression (exit
code 127) when streaming was enabled.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(zsh): correct misleading comment on stream fd initialization
The comment referenced := (ZSH assign-if-unset) but the code uses :-
(use-default-if-unset). Update the comment to accurately describe
what the expansion does.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(nu): add early return guard when oh-my-posh is not available
If a user uninstalls oh-my-posh without removing the autoload script,
the script would still run on every Nu startup and produce errors.
Add an early return guard at the top of omp.nu that exits the script
immediately if the executable is no longer available. Handles both
install modes:
- Absolute path (standard install): \path exists\
- Base name only (MSIX / --strict mode): \which\
Fixes#7245
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(msi): accept WiX v7 EULA in build script
WiX v7 now requires explicit EULA acceptance under the Open Source
Maintenance Fee policy. Add -acceptEula wix7 to the wix build command
so CI releases don't fail.
See: https://docs.firegiant.com/wix/osmf/#direct-acceptance
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(nu): guard path exists check to absolute/relative paths only
When the executable is stored as a bare name (e.g. MSIX / --strict mode),
\path exists\ resolves against the current working directory and may
incorrectly return true if an unrelated file with the same name exists
there. Only apply the \path exists\ check when the executable string
looks like a path (contains a separator or starts with . / ~); otherwise
rely solely on \which\ for the PATH-based lookup.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: emit FTCS_COMMAND_EXECUTED (OSC 133;C) in PowerShell when shell integration is enabled
When shell_integration is enabled without transient/streaming, PowerShell
never called Enable-KeyHandlers, so the Enter key handler that emits
\e]133;C\a (FTCS_COMMAND_EXECUTED) was never registered.
Enable KeyHandlers for PowerShell whenever FTCSMarks (shell integration)
is active so terminals like Ghostty can measure command execution time.
Bash, Zsh, and Fish are unaffected they emit FTCS_C via preexec/PS0
hooks independently of the key handler feature.
Fixes#7377
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* test(upgrade): eliminate flaky network dependency in TestCanUpgrade
Replace real GitHub API calls with a local httptest.Server and make
http.IsConnected a mockable function variable so TestCanUpgrade is
fully deterministic and never fails due to rate-limiting or transient
connectivity issues.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add foreground_templates to the arrow segment so it turns red (#E06C75)
when the previous command exits with a non-zero code, matching the
original oh-my-zsh robbyrussell behavior.
Fixes#7426
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>