Skip to content

fix: use one Tailwind CLI per machine and survive slow downloads - #48

Merged
Shewart merged 1 commit into
mainfrom
fix/tailwind-download
Oct 13, 2026
Merged

Shewart merged 1 commit into
mainfrom
fix/tailwind-download

Conversation

@Shewart

@Shewart Shewart commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

init downloaded the 112 MB Tailwind CLI into every project, held it in memory, and gave up after five minutes. On a slow connection init failed and left the project uninitialised (found during the 0.4.0-alpha.2 release checks). The build's own download used MSBuild's default timeout and wrote straight into the project, and nothing kept the binary out of git.

One CLI per machine

  • The CLI is downloaded once into ~/.shellui/bin/tailwindcss-<version>-<platform> (or SHELLUI_CACHE_DIR), the same location scripts/rebuild-precompiled-css.sh uses. init and Build/ShellUI.targets run it from there, so projects hold no binary.
  • A copy in a project's .shellui/bin still takes precedence.
  • .shellui/.gitignore containing * keeps the folder out of git without touching the project's .gitignore.

Downloads that survive slow connections

  • Streamed to a .partial file; resumed with HTTP Range after a dropped connection; up to 4 attempts; abandoned only after 60 s with no data (no overall time limit). A 404 fails at once.
  • The file appears only once its size matches, so a cut-off download is never mistaken for a working CLI.
  • Progress shows in the init spinner, and every 10% when there's no terminal.
  • The build target downloads to .partial with retries and a 30-minute limit, and renames only on success.

When the download fails
init finishes everything else (config, CSS, components) and warns. The build retries, and its warning names the exact URL and the file path to save it to.

Existing projects
shellui update replaces Build/ShellUI.targets when it's an unedited copy from any released CLI. There have been two standalone versions (0.0.1–0.3.4 and 0.4.0-alpha.1), matched by hash, and both are tested against the real files those CLIs wrote. It then adds the ignore file, and deletes the project's copy of the CLI if it's identical to the shared one. An edited targets file is left alone, with a note.

Checked

  • Release build has 0 warnings, and all 334 tests pass. New tests cover: download, resume after a dropped connection, retry of a short download, stall timeout, a server that ignores Range, 404, giving up with no file left, cache naming, the targets falling back to the shared CLI, refresh of both released targets files, an edited targets file, duplicate removal, and the ignore file.
  • Real runs on a slow connection:
    • init with an empty cache: downloaded 107 MB in 65 s and built. The old code timed out on the same connection.
    • init with a warm cache: 2 s, with no binary in the project.
    • Download blocked: init still completed, and the build warned with the URL and path.
  • A fresh project is 130 KB (it was about 112 MB), git sees nothing in .shellui, and the build is 0/0.
  • A 0.4.0-alpha.1 project after update: targets refreshed, its 112 MB copy removed, and the build is 0/0.
  • A fresh clone with an empty cache: MSBuild downloaded into the cache in 133 s and built 0/0.
  • tailwind-setup, FAQ, QUICKSTART and CLI_SYNTAX describe the shared CLI.

init downloaded the 112 MB Tailwind CLI into every project, held it in
memory and gave up after five minutes, so on a slow connection init
failed and left the project uninitialised. The build's own download used
MSBuild's default timeout and wrote straight into the project, and
nothing kept the binary out of git.

- The CLI lives once per machine in ~/.shellui/bin (or SHELLUI_CACHE_DIR)
  and init and the build run it from there; a copy in .shellui/bin
  still wins. Projects hold no binary.
- Downloads stream to a .partial file, resume with Range, retry, and stop
  only after 60 s without data; the file appears once its size matches.
- If the download fails, init finishes the rest and the build retries.
- .shellui/.gitignore of "*" keeps the folder out of git.
- update replaces a targets file any released CLI wrote, unless edited,
  and removes a project copy identical to the shared one.
Copilot AI balanced review requested due to automatic review settings October 13, 2026 12:18

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@Shewart
Shewart merged commit 9c7cfac into main Oct 13, 2026
1 check passed
@Shewart
Shewart deleted the fix/tailwind-download branch October 13, 2026 12:24
Shewart added a commit that referenced this pull request Oct 13, 2026
Release notes and version references for 0.4.0-alpha.2.

**In this release** (already on main):
- #48: the Tailwind CLI is downloaded once per machine and run from
there, so projects hold no binary; downloads survive slow connections;
`init` carries on if the download fails; `.shellui/` is git-ignored;
`update` moves older projects onto the shared CLI
- #46: `update` installs new dependencies and keeps files you changed
(`--force` to overwrite); `remove` finds layouts and custom paths; the
package `TimePicker` value fix; `color-scheme` for light and dark
- #44: `shellui-theme.css` no longer 404s when linked directly
- #43: NuGet package icon and README logo

**This PR**
- `Directory.Build.props`: suffix `alpha.2`
- Docs name stable `0.3.4` and prerelease `0.4.0-alpha.2` (README,
VERSIONING_STRATEGY, CLI_INSTALLATION, CLI_SYNTAX, FAQ, QUICKSTART);
stable-docs links point to `v0.3.4`
- The version fallbacks in `VersionHelper` and `ComponentMetadata`
(still `0.3.0` on main) are now `0.4.0-alpha.2`
- `docs/RELEASE_NOTES.md`: the 0.4.0-alpha.2 section, plus the 0.3.4 and
0.3.3 sections from `release/v0.3`; `scripts/extract-release-notes.sh
0.4.0-alpha.2` extracts it

**Release checks** (on `9c7cfac` plus this commit)
- Release build has 0 warnings, and all 334 tests pass
- A 0.3.4 project updated with the packed alpha.2 CLI: targets
refreshed, the 112 MB project copy of Tailwind removed, 54 components
updated, the edited `AppSidebar` kept, 5 new dependencies installed,
builds 0/0
- A fresh Identity app, `init --yes --dashboard 02` then `add auth-01
data-table chat qr-code time-picker`: uses the shared Tailwind CLI and
builds 0/0; `.shellui` holds only its `.gitignore`
- All 93 direct targets together in `my-app` build 0/0 on net8.0, net9.0
and net10.0, with no project copies of the CLI
- The packed `ShellUI.Components` in a browser: `window.ShellUI` loads,
TimePicker shows its value, dark mode sets `color-scheme` (including the
native date input), Popover closes on Escape, Command runs `Action` then
`CommandSelected`, no console errors
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants