You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Added lieflat-charts to the Design & Content group in both installers, off by default. It is a template-driven data-visualisation skill: Lupi / Basics / Glance / Maps chart galleries plus 12 bilingual full-page report templates, all producing single-file HTML.
Fetched at install time from larashero3-dotcom/lieflat-charts, not vendored.install_lieflat_charts / Install-LieflatCharts perform a blobless cone-mode sparse checkout (git clone --depth 1 --branch main --filter=blob:none --sparse, then sparse-checkout set templates examples scripts agents), pulling ~1.4 MB instead of the repository's ~20 MB.
A remote or a local git without partial-clone support falls back to a full shallow clone, then reduces it with the same allow-list, hidden directories included. Both paths therefore produce a byte-identical tree — a deny-list fallback would have diverged the moment upstream added a top-level directory, and a */ glob would have let an upstream .github/ through on the fallback path only.
The PolyForm notice is printed in the pre-install phase, before any of the user's configuration is written, rather than inside the install function. A --all run cannot install anything, or fail part-way through doing so, before the licence has been shown.
The install is staged in a mktemp-named scratch directory, ~/.claude/.lieflat-charts.scratch.XXXXXX/, holding both the incoming tree and the retired one. It sits outside skills/, so a partial copy is never picked up as a skill, and on the same filesystem as the destination, so the swap is a rename: retire the old tree, move the new one in, delete the old. Deleting the destination first would be unsafe twice over — a failed copy leaves nothing behind, and a failed delete makes mv drop the staged tree inside the surviving directory. If the move-in fails the retired tree is restored, but only into an empty slot; if that restore also fails the backup is left on disk and its path reported, the ownership marker is cleared, and the scratch directory is kept. The result of the swap is verified afterwards, so a concurrent installer that wins the race cannot produce a silent success.
Uninstall is guarded by a marker file, ~/.claude/.lieflat-charts-installed, written only when the installer created the directory. A copy the user cloned there by hand is reported and kept. The guard is evaluated before the generic skills/ sweep, which in its fallback branch would otherwise remove the whole directory. One invariant governs the whole mechanism: the skill is never removed while its ownership marker survives. The marker is therefore cleared first, removal is gated on that clearing having succeeded, and a removal that then fails keeps its exemption from the sweep — so the installer never deletes what it just reported as kept, and never leaves a marker claiming a path it has emptied.
Extended the ## License section of both READMEs: this repository is MIT, but lieflat-charts is PolyForm Noncommercial 1.0.0 and is noncommercial-use only.
Added tests/test_lieflat_charts_integration.py. Beyond the structural checks, it builds a local git repo mirroring upstream's top-level shape and installs from it over file://, so the sparse path, the forced fallback, overwrite, staging cleanup, marker creation and the failure path are all exercised without network. One further test, gated behind LIEFLAT_REQUIRE_NETWORK=1, guards the sparse allow-list against upstream drift.
Design Rationale
Fetched rather than vendored, for two independent reasons. The repository is 20.5 MB, of which 18.7 MB is docs/ preview GIFs and PNGs — vendoring even the trimmed 1.36 MB payload would more than triple skills/. And PolyForm Noncommercial makes this repo a redistributor if it carries a copy, with the licence's Notices obligations attached. Shipping a URL keeps the responsibility boundary clean and means users always get upstream main.
Tracking main, not a tag. Upstream's newest tag v1.2.0 is 9 commits behind main, missing the commit that adds 16 chart types. Pinning would ship a knowingly incomplete skill, and this repository has no lockfile convention that a single pinned skill could join without becoming an orphan. --branch main is passed explicitly so that a future change to upstream's default branch fails loudly instead of silently installing something else.
Default off because of the licence, not because of risk. Unlike storage-analyzer, nothing here can damage a machine. But nobody should acquire a noncommercially-licensed artefact passively, so it is opt-in, and --all still installs it — that flag keeps meaning "everything" — with the notice hoisted ahead of all installation work.
A marker file rather than DeepXiv's glob. DeepXiv can delete skills/deepxiv-* safely because nothing else creates those directories. lieflat-charts is a well-known skill people install by hand, so an unconditional rm -rf would delete a directory this installer never created.
Existing directories are overwritten unconditionally on install. This matches install_deepxiv, and upstream's own SKILL.md instructs custom palettes to stay inlined in the artefact rather than written back to color-presets.js, so there is no expectation of local edits surviving.
Notes & Caveats
The skill is noncommercial-use only. PolyForm Noncommercial 1.0.0 permits personal, hobby, academic, charitable and government use; commercial use is not licensed.
Dropping docs/ breaks the 12 thumbnails in templates/reports/index.html and leaves three dead documentation links (SKILL.md, report-catalog.md, examples/README.md). Chart and report selection is text-driven — catalog.md references no images at all — so selection quality is unaffected; only human browsing of the preview index is.
The sparse checkout is an allow-list, so a new top-level directory added upstream would be skipped silently. No hermetic test can detect that, which is why the network-gated test exists; run it with LIEFLAT_REQUIRE_NETWORK=1 pytest tests/test_lieflat_charts_integration.py.
Tracking main means installs are not reproducible across time. That is the accepted cost of not pinning.
The clone root becomes the skill directory, so .git is removed before the copy — otherwise a partial clone bound to a promisor remote would end up inside ~/.claude/skills/.
install_lieflat_charts is invoked as ... || true so a network failure on this optional, default-off skill cannot abort the rest of the install. Bash disables errexit inside a function used that way, so every destructive step in the function checks its own status explicitly rather than relying on set -e.
In install.ps1 the git calls are judged solely on $LASTEXITCODE inside try/catch, and their output is never piped. Under $ErrorActionPreference = "Stop", Windows PowerShell 5.1 can promote a native command's stderr to a terminating NativeCommandError, which would abort the run on a routine git progress line instead of reaching the fallback.
Eight adversarial review rounds (Codex; Skeptic / Architect / Minimalist lenses) fixed 11 high-severity and 26 medium/low findings. For the first six rounds, every round found a defect introduced by the previous round's fix: round one's staging protocol nested the staged tree inside a destination that failed to delete; round two's rollback deleted the retired copy even when restoring it had failed; round three's orphan reaper deleted exactly the backup that rollback preserves; and after that reaper was removed in round four, round five found the same data-loss chain still reachable through PID-derived scratch names, since a rerun in the same shell reuses $$. Rounds six and eight found no high-severity issues; round seven found that the marker clearing had been ordered ahead of the deletion but not made a precondition of it, which is what produced the single invariant the mechanism now rests on.
Two environment limits: git clone over HTTPS is blocked in the development sandbox, so the install path was verified against a local fixture repo rather than the real remote; and pwsh is not installed, so install.ps1 was written by mirroring the Bash implementation and not executed. The PowerShell test skips when pwsh is absent.