14 Commits
Author SHA1 Message Date
ClaudeandJan De Dobbeleer 4709f3e237 fix(serve): forward the full environment to the streaming daemon
When streaming is enabled, the daemon only saw environment variable
changes for a hardcoded whitelist (PATH, POSH_* variables, VIRTUAL_ENV,
CONDA_PROMPT_MODIFIER), forwarded per-prompt by the shell integration
scripts. Anything outside that whitelist - like a variable direnv
exports - stayed pinned to whatever value existed when the daemon
started, so `{{ .Env.XXX }}` templates never picked up live changes.

The daemon now reads the shell's complete environment on every prompt
instead: each request's JSON header is unconditionally followed by a
raw "KEY=VALUE\0" record stream terminated by an empty record, which
the daemon parses with readEnvBlob before applying it via the existing
overlay/unset machinery. This wire format needs no escaping (env
values can never contain a NUL byte on any OS), fixing latent
correctness bugs in the shell-side JSON escapers it replaces (fish
silently dropped embedded newlines; zsh's control-character stripper
only handled the first stray character due to a single-substitution
bug) and is cheaper to produce than the JSON it replaces, particularly
in fish.

All four shell integrations (fish, zsh, pwsh, cmd/Clink) were updated
to send the full env this way instead of a whitelist, including at
their abort/quit call sites, which now also send the (empty) blob
every request line requires to keep the stream in sync.

Fixes #7792.
2026-08-12 22:58:14 +02:00
ClaudeandJan De Dobbeleer e458c6ed14 fix(pwsh): emit ASCII-safe init output for non-ASCII paths
PowerShell decodes native command stdout using [Console]::OutputEncoding,
which defaults to the legacy OEM code page on Windows. When a path in the
init bootstrap contains non-ASCII characters (e.g. a ² in the username),
the UTF-8 bytes are mangled before the init script can run, breaking
initialization with 'term is not recognized' errors.

Quote pwsh strings containing non-ASCII runes as expandable string
expressions built from [char] casts so everything written to stdout, and
to the on-disk init script, is pure ASCII, which survives every code
page. Elvish keeps the previous plain single-quote behavior via its own
quoting function.

Validated against pwsh 7.4.6 in every injection context: env var
assignment, the call operator, Invoke-Expression, argument-mode
--config= tokens, and the omp.ps1 executable assignment.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BCNz9G4sSmwRixkjVodcWo
2026-08-12 22:58:14 +02:00
ClaudeandJan De Dobbeleer e446fdcf31 fix(pwsh): trim ViMode restore comment
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E5xZ65xtjLxKyrpVA2Ggo9
2026-08-05 07:59:36 +02:00
ClaudeandJan De Dobbeleer 2afd3fc8c0 fix(pwsh): stop repeated profile sourcing from breaking ViMode
Set-PSReadLineOption throws when a non-null ViModeChangeHandler is
combined with a non-Script ViModeIndicator, but silently ignores a
$null handler (an existing handler can never be cleared). Restoring
the "original" PSReadLine state on module removal could therefore
leave a stale non-null handler paired with a non-Script indicator,
which then got captured as the new "original" on the next re-source
and re-thrown on the following cleanup.

Fixes #7772

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E5xZ65xtjLxKyrpVA2Ggo9
2026-08-05 07:59:36 +02:00
ClaudeandJan De Dobbeleer 262c744622 fix(cache): accept pointer-shaped gob decodes in Get[T]
gob.Register keys its decode-side type map on the exact type
registered, while encoding an interface value uses the base type.
segment_registry.go registers segments.Version (and ClaudeData,
CopilotCLIData) as pointers, so every device-cache entry stored as a
value under one of those types comes back as *T on the next process's
gob decode. Get[T]'s type assertion only matched T, so the mismatch
was logged and treated as a miss on every restart, defeating
cache_duration entirely for every language segment.

Get[T] now also accepts a *T decode and dereferences it, which fixes
existing on-disk caches in place without any migration.

Fixes #7766

Co-authored-by: Claude <noreply@anthropic.com>
2026-08-05 07:59:36 +02:00
ClaudeandJan De Dobbeleer 2a59ed1e50 refactor(cli): replace cobra and pflag with minimal internal packages
The CLI framework was the largest remaining third-party chunk (545 kB)
and most of its surface went unused - completions are explicitly
disabled, templates and command groups never used. Replace both with
internal packages mirroring the exact API subset in use: a command tree
with persistent flags and nearest-hook semantics, POSIX flag parsing
(--flag=value, --flag value, shorthands and grouping, the -- terminator,
interspersed positionals, unknown-flag allowlisting for the argocd
segment), positional validators, the implicit help command, and the
Windows Explorer double-click guard.

Help, usage and error output were verified byte-identical against the
previous binary across a 47-case golden battery: every command and
subcommand help screen, error formats and exit codes, flag styles
including flags before the subcommand, and init/print rendering.

Shrinks the stripped linux/amd64 binary by 586 kB (13.50 MB -> 12.91 MB;
23.7% below the original 16.93 MB).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qiyvpiy5jR2tyzwZ3zUki5
2026-07-31 07:40:24 +02:00
ClaudeandJan De Dobbeleer 98f069cb9d chore: gofmt alignment after dependency swaps
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qiyvpiy5jR2tyzwZ3zUki5
2026-07-31 07:40:24 +02:00
ClaudeandJan De Dobbeleer 7a4b208b97 refactor(font): replace sfnt library with minimal name table reader
Font installation only reads the name table of .ttf and .otf files - the
extension allowlist runs before parsing - yet ConradIrwin/font carried
WOFF/WOFF2 decoding and a brotli implementation along with it. Replace
it with a small reader for the sfnt table directory and name table,
decoding entries the same way (UTF-16BE for Unicode and Microsoft
Unicode platforms, Mac Roman for legacy Mac entries, raw bytes
otherwise).

Verified byte-identical metadata extraction (full name, preferred
family, family) against the previous library across 45 system TTF and
OTF fonts. Shrinks the stripped linux/amd64 binary by 377 kB.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qiyvpiy5jR2tyzwZ3zUki5
2026-07-31 07:40:24 +02:00
ClaudeandJan De Dobbeleer 5848391619 refactor: replace ini, modfile and jsonutil dependencies
Four dependencies served narrow slices of their APIs:

- gopkg.in/ini.v1: the aws, gcp and git segments read sections and keys.
  Replaced with a minimal src/ini package mirroring the same API subset
  and ini.v1's semantics (first key wins, inline comment cutting,
  surrounded-quote trimming, BOM handling).
- golang.org/x/mod: the go segment read one field, the go directive of
  go.mod. Replaced with a line scan.
- gookit/goutil/jsonutil: only StripComments was used. Replaced with
  text.StripJSONComments, which unlike the original is string-aware and
  won't mangle values containing comment markers.
- github.com/google/uuid: the session id in cache/init.go. Replaced with
  a local RFC 4122 v4 generator (uuid remains an indirect dependency of
  sprig's template functions).

Prompt output verified byte-identical against the previous binary,
including the git segment against this repository's live config.
Shrinks the stripped linux/amd64 binary by 266 kB.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qiyvpiy5jR2tyzwZ3zUki5
2026-07-31 07:40:24 +02:00
ClaudeandJan De Dobbeleer 229932c68e refactor: drop x/text cases, language and message packages
Three call sites pulled in x/text's casing and message-formatting
machinery (with its plural and number-format tables) for ASCII-only
work: title-casing segment names and taskwarrior command keys, and
comma-grouping a number in the execution time segment. Replace them
with text.Title and a local thousands-separator helper, both verified
against the exact x/text output for the inputs these paths handle,
including the compatibility-sensitive segment template names
(nix-shell -> Nix-Shell, ui5tooling -> Ui5tooling).

x/text itself stays: the terminal writer's rune width tables use
x/text/width by design.

Shrinks the stripped linux/amd64 binary by 545 kB.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qiyvpiy5jR2tyzwZ3zUki5
2026-07-31 07:40:24 +02:00
ClaudeandJan De Dobbeleer 09cface00b refactor(dsc): embed pre-generated resource schemas
Reflecting the DSC resource schemas at runtime linked invopop/jsonschema
and with it pb33f/ordered-map and a second YAML library (yaml/v4, next
to the yaml/v3 the config loader already ships) into every prompt
binary, for output that never changes between builds. Generate the
schemas ahead of time and embed them; golden tests regenerate the
schemas via the same reflection (test-only dependency, not linked) and
fail on drift. Regenerate with UPDATE_SCHEMAS=1 go test ./cli/dsc ./cli/font.

Output verified byte-identical for the shell, configuration and font
resources. Shrinks the stripped linux/amd64 binary by 438 kB.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qiyvpiy5jR2tyzwZ3zUki5
2026-07-31 07:40:24 +02:00
ClaudeandJan De Dobbeleer 2b64976e6b refactor(terraform): replace HCL parser with minimal version scanner
The hashicorp/hcl/v2 + zclconf/go-cty stack existed to extract a single
attribute: required_version from a top-level terraform block. Replace it
with a small scanner that tracks just enough HCL structure (comments,
strings, interpolation, heredocs, block nesting) to locate that
attribute, and fails closed to the state-file fallback on anything it
cannot make sense of - the same path a full parser failure took.

Shrinks the stripped linux/amd64 binary by 1.80 MB (16.93 MB -> 15.13 MB).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qiyvpiy5jR2tyzwZ3zUki5
2026-07-31 07:40:24 +02:00
ClaudeandJan De Dobbeleer de41b29ace fix(battery): add illumos/solaris support to fix cross-compile failure
battery_windows_nix.go's negative build tag matched illumos/solaris
without providing a systemGetAll implementation, breaking `go build`
on those platforms. Add a dedicated no-op implementation and exclude
illumos/solaris from the fallback file.

Fixes #7730
2026-07-30 19:44:41 +02:00
ClaudeandJan De Dobbeleer 11094db2ec feat(segment): add vimode segment for ZSH Vi mode 2026-06-23 08:54:35 +02:00