Skip to content

FAQ

Why zero external dependencies?

lsgo was originally built in an environment with no module proxy access, so every piece — ANSI styling, terminal-width detection, extended-attribute lookups — is hand-rolled against the Go standard library rather than reused from an existing package. That constraint turned out to be worth keeping: the result is a single static-ish binary with no go.sum to audit. See the Installation page for build instructions.

Does it work on Windows?

It cross-compiles cleanly (the platform-specific code — stat fields, terminal-width ioctls, extended attributes — has a fallback implementation for anything that isn't Linux or Darwin), but that fallback path reports degraded functionality: no extended-attribute listing, for example. Linux and Darwin are the actively developed and tested platforms.

Why do I see boxes or ? instead of icons?

--icons renders glyphs from the private-use area of a Nerd Font. If your terminal isn't using a patched Nerd Font, those code points have nothing to render against and show up as tofu boxes. Install a Nerd Font and select it in your terminal, or just leave --icons off — it's opt-in.

Why is my sort order different from GNU ls?

The default sort is name-based, natural-order, and case-insensitive (file9 before file10, apps before Documents), which is different from GNU ls's default byte-order sort. This is deliberate — see View Modes & Sorting for the reasoning. Pass --sort=Name (capital N) for case-sensitive, uppercase-first ordering closer to the traditional behaviour.

Combining --long, --oneline, --grid, and --tree gives a result I didn't expect

Whichever of those four flags appears last on the command line decides the base view. The full precedence table, along with the tree-recursion and grid-of-tables caveats, is on the View Modes & Sorting page.

Does --git slow down large directories?

lsgo shells out to the git binary once per repository root per invocation (git status --porcelain=v1 --ignored=matching -z), not once per file, and caches the result. Listing a single subdirectory of a large repo costs the same one process spawn as listing the repo root.

Why does -@/--extended only show attributes when I pass the flag?

Some other ls implementations show an @ indicator in the permissions column whenever a file has extended attributes, independent of whether you asked to see them. Doing that here would mean an xattr lookup for every file in every -l listing (a subprocess call on Darwin), which is a real performance cost for a rarely-used feature — so the whole thing, indicator included, is gated behind -@.

Why doesn't --mounts work on macOS?

-M/--mounts parses /proc/mounts, which only exists on Linux. Other platforms always report "not a mount point" rather than erroring — some other ls implementations also support macOS here by shelling out to the mount command, but that's out of scope for now.

Why doesn't -X/--dereference change the type character or add an arrow?

-X re-points a symlink's metadata columns — permissions, size, hard links, blocks, owner, timestamps — at its target, but the name column still reads as a symlink (l type character, -> target arrow) rather than fully impersonating the target row the way ls -L does. This keeps it clear at a glance that the row is still a symlink, just describing where it points to.

No — --absolute always means "show this entry's own absolute path." Some other implementations offer a second mode that additionally re-resolves symlink targets; lsgo only supports the simpler behaviour.

Why didn't lsgo read my piped input unless I passed --stdin?

Unlike some other implementations, lsgo never reads stdin as a list of paths just because stdin isn't a terminal — only the explicit --stdin flag does that. This is deliberate: without it, something accidentally piped into lsgo's stdin (git diff | lsgo -l) could otherwise get silently misinterpreted as a list of filenames.

Why does --git-repos show - for a repository nested inside another one?

Repository discovery is cached per directory tree, and once an ancestor directory is confirmed to be a Git repository, lsgo doesn't separately check its subdirectories for nested repositories (e.g. submodules or vendored clones) — the same "one process spawn per repository, not per file" tradeoff the plain --git column already makes for performance.

I found a bug, or want to request a feature

Open an issue on GitHub. Pull requests are welcome too — go test ./..., go vet ./..., and gofmt -l . should all be clean before you open one.