Releases: Kirisos-Guna/FastFetchStudio
Release list
v1.1.13
Full Changelog: v1.1.12...v1.1.13
v1.1.12
v1.1.11
v1.1.10
Your logo now shows up everywhere, and the fetch draws once
Two separate faults were behind "it still shows the Windows logo".
1. A terminal with no image support got a Windows logo instead of your picture
The reported screenshot was classic conhost - the Terminal row read Windows Console,
not Windows Terminal. conhost renders no image protocol at all, so sixel was never going to
appear there, and the launcher fell back to fastfetch's built-in ASCII Windows logo. Pick a
logo in the app and you would never see it.
fastfetch prints a text logo file verbatim, ANSI escapes and all. So FastFetch Studio now
pre-renders each gallery image to true-colour half-block art in arts\ and hands that over
whenever no image protocol is available:
| Terminal | Your logo is drawn as |
|---|---|
| Windows Terminal (1.22+), WezTerm, foot, contour, mlterm, yaft | the image, over sixel |
| kitty, WezTerm, Ghostty | the image, over the kitty protocol |
| classic conhost, VS Code with GPU acceleration off, anything unrecognised | block art |
| no images uploaded, or Never selected | fastfetch's ASCII Windows logo |
Block art uses two image pixels per character cell, so it carries twice the resolution a single
character per pixel would. Coarser than a real image, but it is your picture, and it is the
only thing that can appear where no image protocol exists. The explanation message now only
fires when it falls all the way through to the ASCII logo.
2. The fetch printed twice, in two different colour schemes
Your $PROFILE had two fastfetch calls - setup.ps1's managed block, plus the documented
snippet pasted in afterwards without removing it. Both ran, each picking its own random theme.
The launcher now draws once per shell session, so a second call does nothing. It uses a
global variable rather than an environment variable on purpose: $env: is inherited by child
processes, so a nested shell would inherit the marker and draw nothing at all.
Upgrading
Open the app and click Apply & Generate - that writes arts\ and rewrites
fastfetch-random.ps1, and both fixes live in those generated files. To stop the double call
at its source, delete one of the two fastfetch lines from your $PROFILE, or run
.\setup.ps1 -Uninstall.
Full Changelog: v1.1.9...v1.1.10
v1.1.9
Pick a logo, get that logo
The launcher only used your chosen image when it was running inside Windows Terminal or
WezTerm. Everywhere else it quietly drew fastfetch's built-in ASCII Windows logo instead, so
setting a logo in the app looked like it did nothing at all.
It now detects what the terminal can actually do, says so when it cannot draw your image, and
lets you override the decision.
What changed
-
Capability detection instead of a two-terminal guess. sixel: Windows Terminal
(WT_SESSIONorTERM_PROGRAM), WezTerm, foot, contour, mlterm, yaft. kitty protocol:
kitty, WezTerm, Ghostty. Classic conhost and anything unrecognised still get the tinted
built-in logo. -
The fallback explains itself. With a pinned default image and randomisation off, it now
names the terminal and shows the way out instead of swapping your logo out in silence:FastFetch Studio: no image support detected in the VS Code terminal, so the built-in logo was drawn. force it: $env:FASTFETCH_STUDIO_LOGO = 'image' (Windows Terminal 1.22+ draws it as-is) -
New "How the logo is drawn" setting (Random tab): Auto / Always draw the image /
Never - always the built-in ASCII logo. Saved aslogoModeinstudio-state.json, and
overridable for one shell with$env:FASTFETCH_STUDIO_LOGO(imageorbuiltin).
A note on VS Code and Zed
Both are recognised by name so the message can say where it happened, but neither is treated
as image-capable on purpose: VS Code gates image rendering behind
terminal.integrated.gpuAcceleration, and a terminal that ignores the image bytes draws no
logo at all - worse than the ASCII fallback. Choose Always draw the image if yours is set up
for it.
Upgrading
The fix lives in the generated launcher, so it only takes effect once that file is rewritten:
open the app and click Apply & Generate, or set the new option on the Random tab.
Full Changelog: v1.1.8...v1.1.9
v1.1.8
Hardened icon guard
No user-facing change — the icons themselves were fixed in
v1.1.7 and are unchanged
here. This release hardens the --smoke-icons guard that ships with the exe.
The guard failed once on the very first run of the freshly built exe — "theme-07: fastfetch
drew 0 keyed rows" — and then passed on every run afterwards, from both the exe and the
source. A cold fastfetch on a busy machine can render nothing at all. Since that guard runs in
both CI jobs, a flake there can fail a release build for no reason, so a render is now retried
once when it comes back empty. A genuinely broken config renders nothing twice, so a real
regression still fails.
That retry exposed a second hole: the guard compared rendered rows against a count derived from
the config itself, so a config that had lost its modules checked zero rows against zero icons
and passed. It now compares the module types against an explicit list, so dropping a module —
or adding one without confirming it gets an icon — fails the guard.
Checked against six mutations: icons switched off, padding reverted, one module dropped, all
modules dropped, a glyph typed back into a key, and the title key losing its no-key sentinel.
All six fail; the fixed code passes.
Full Changelog: v1.1.7...v1.1.8
v1.1.7
Icons on every module
Six of the fourteen rows drew a label with no icon — Kernel, Terminal, CPU,
GPU Driver and Memory, plus the title line. This release fixes that, and fixes the
reason it was reachable.
What was actually wrong
The icons were never coming from FastFetch Studio. They came from a hand-written config at
%APPDATA%\fastfetch\config.jsonc that typed a private-use glyph into the key of eight
modules and left the other six bare. That file only ever rendered because Studio was not
producing a config of its own:
Apply & Generatewrotethemes\and the launcher but neverconfig.jsonc, even
though the module docstring promised it and the backup step already existed for it.- The launcher only passes
--config <theme>whenthemes\actually contains files, and
the Random tab's toggles rewrote the launcher without generating those themes.
With no themes and no config.jsonc, fastfetch fell through its search path and drew
whatever else it found — a config with a different module list and only some of the icons.
What changed
- Icons now come from fastfetch itself. The generated config switches on
display.key.type, and fastfetch fills in its own per-typekeyIcondefault. No glyph is
written into any label, so adding a module can never leave a row icon-less — the
hand-maintained list is what rotted in the first place. A glyph in akeystring is now
explicitly wrong: with key icons on it renders a second icon beside the default. - The three spaces each label carried as a manual indent moved to
display.key.paddingLeft,
and the title label became fastfetch's whitespace "no key" sentinel — it stays a bare
user @ host, and the stray:it used to print is gone. Apply & Generatenow writesconfig.jsonc, and the Random tab's toggles regenerate
the config and themes alongside the launcher they rewrite.
Verification
- All 13 labeled rows now render an icon, on both the launcher's
--configpath and a
barefastfetch— checked against fastfetch 2.64.2. - New
--smoke-iconsguard, wired into both CI jobs. It asserts the config shape always,
and — where fastfetch is present — that every keyed row actually draws a private-use
glyph. It fails on the old code, on a glyph sneaking back into a label, and on the
padding reverting.
Full Changelog: v1.1.6...v1.1.7
v1.1.6
Fixed
Tab content was pushed down the card behind a blank band, with the bottom clipped out.
Scrolling up on a tab whose content already fits inside the card walked the Tk canvas origin
negative, so the whole tab content was drawn below the top of the card. It affected all three
tabs and got worse the more you scrolled up - trying to reset the view was what caused it.
Tk does not clamp yview_scroll when the scroll region is shorter than the viewport, so a
wheel-up nudge with nothing to scroll to had nowhere valid to go. Reproduced on a maximized
1440x900 window (200% display), where every tab's content fits: six wheel-up notches put the
canvas origin at -240.
Also fixed while in there: the wheel handler used e.delta // 120, which truncates toward
negative infinity - so a high-resolution wheel or touchpad reporting less than a full notch
either did nothing or scrolled in the wrong direction.
Notes
- The canvas origin is now clamped back inside the scroll region on both the wheel event and
every layout pass, so a stuck state also heals on resize. - If you are on v1.1.4 or earlier, this is worth taking. The scroll code was unchanged in
v1.1.5, so v1.1.5 does not contain this fix. - Verify the binary with
FastFetchStudio.exe --smoke-scroll.
Full Changelog: v1.1.5...v1.1.6
v1.1.5
The launcher now works on a fresh setup
Pasting the documented line into $PROFILE on a clean machine used to fail. It
failed in two different ways, and the launcher had two further defects that only
showed up once it did run. All four are fixed.
Why it failed
1. The file did not exist yet.
fastfetch-random.ps1 is a generated file. Before FastFetch Studio has ever
been run it is not there, and & <missing path> is not a "file not found" — the
call operator resolves through Get-Command, so it raises
CommandNotFoundException:
& : The term 'C:\Users\you\.config\fastfetch\fastfetch-random.ps1' is not
recognized as the name of a cmdlet, function, script file, or operable program.
2. Windows blocks scripts by default.
On Windows clients, when every execution-policy scope is Undefined the
effective policy is Restricted, which blocks .ps1 files and profiles. With
the file present, the same command then raises PSSecurityException:
& : File C:\Users\you\.config\fastfetch\fastfetch-random.ps1 cannot be
loaded because running scripts is disabled on this system.
What changed
- The profile snippet is guarded. It now checks the launcher exists and falls
back to a barefastfetch.exeif it does not, so a profile that runs before
the app has written anything no longer errors on every new shell. setup.ps1writes a bootstrap launcher so the documented line works
immediately after install, before the app has ever run.setup.ps1 -FixExecutionPolicysetsRemoteSignedatCurrentUserscope.
The check reads the effective policy, and reports Group Policy
(MachinePolicy/UserPolicy) as unfixable locally instead of pretending.- fastfetch is no longer drawn twice. The launcher called it once for the
themed fetch and again for the fallback logo whenever no image protocol was
available — and again whenever the first call returned non-zero. The image
retry also guarded against$LASTEXITCODEbeing$null, which compares
unequal to0and silently fired the fallback. - "Once per day" actually works. The launcher checked a day-stamp file it
never wrote, so the setting behaved like "every window". - A missing
fastfetch.exenow says so, naming the paths it tried, instead
of failing silently and looking like a broken install. - Partial state no longer breaks settings.
studio-state.jsonfields are
read individually, so a missing key keeps its default rather than collapsing
the logo size to0or disabling randomisation.
-Uninstall removes only the bootstrap it wrote and never an app-generated
launcher. The launcher is marker-delimited so later runs can find, compare and
remove it without disturbing the rest of the file.
Upgrading
- Run
setup.ps1again (or re-download and run it), then - open the app and click Apply & Generate to replace any older launcher.
Verifying
CI asserts the launcher parses, draws fastfetch exactly once in conhost,
Windows Terminal and WezTerm, retries exactly once when the image attempt fails,
explains itself when fastfetch is missing, and holds for the rest of the day on
daily. The setup job re-runs the installer on a clean machine and checks
idempotency, hook de-duplication and uninstall.
Full changelog: v1.1.4...v1.1.5
v1.1.4
UI fixes
Reported from screenshots of the running app — the Theme and Random tabs, plus a Gallery layout bug found along the way.
Checkboxes and radio buttons rendered as white squares
ttk's clam theme silently ignores indicatorcolor, so every checkbox drew as a white square with an X in it (and every radio as a white square with a dot), pressed right up against its label.
All five toggles are now canvas-drawn: accent-red fill with a proper white tick or centre dot, a real gap before the text, a hover edge, a focus ring, and space/Return activation. The dead ttk style blocks are gone.
Theme tab — labels were clipped and overlapped
The colour labels used width=24 (~192px) but GPU Driver / Memory / Disks measures 216px, so it overran and was overdrawn by the colour swatch next to it. All seven rows now share a single grid, so every swatch, hex field and Pick button lines up on one column.
Also restructured into titled bordered panels, moved Options into the right-hand column, and gave the profile snippet the full width — its second line is 63 characters and was being clipped in the narrow column. The Copy button now sits beside the code instead of under it.
The Theme tab was also silently cutting off its own contents. Tab pages are place(relheight=1) overlays, so anything taller than the card is clipped with no error and no scrollbar. The tab had grown to 530px against a 454px viewport, which pushed the profile snippet and the entire button row off the bottom. It's now 447px and fits, with the button row pinned and the controls scrollable as a safety net.
Random tab — the file list was dark-on-dark
A borderless text widget on the panel background, using hand-counted spaces to fake columns. Now a bordered panel with a real three-column grid: accent bullet, monospace path, muted description.
Gallery tab — staggered thumbnails
Cells in a row did not share a baseline. Thumbnails preserve the source aspect ratio, so a wide logo produced a 170×97 label while a tall portrait produced a 105×170 one, and Tk centred each shorter cell vertically in its row. Every thumbnail now sits in a fixed 170×170 box that carries the selection ring, and cells are top-aligned in their rows.
Smaller things
- The
...colour-picker button (a dot-leader artifact) is now a labelled Pick button, and the swatch itself is clickable - Removed a duplicate
status()method definition - Replaced hardcoded
#e04a3fUI fallbacks with theACCENTconstant - Added
FONT_MONOandTHUMB_PXconstants for previously inline literals - Generalized the gallery's wheel-scroll canvas so each tab scrolls only its own content
Verification
- 16/16 widget assertions: exactly 1 theme + 4 random toggles, zero leftover ttk toggles, checkbox flips and persists state, radios mutually exclusive, all colour entries share one x-offset, snippet's longest line needs 413px in a 1192px box
- Gallery regression test: uniform 170×170 footprint, row 0 cell tops all 8px and row 1 all 232px, click-to-select recolours the ring to accent while others stay bordered
- Height budget measured at 880×720, 1080×669 and 760×620
--selftestpasses: 8 themes + 5 sixels + launcher, sixel round-trip 44,799/44,799 with 0 mismatched
Full Changelog: v1.1.3...v1.1.4