Platform-Specific Implementations for Unix vs Windows in Superfile: Build Tags Explained

Superfile isolates all OS-dependent code using Go build tags (//go:build windows and //go:build !windows), implementing platform-specific versions for process detaching, file previews, metadata extraction, and trash handling while exposing identical public APIs.

The yorukot/superfile repository is a modern terminal file manager written in Go that achieves cross-platform compatibility through compile-time abstraction. Instead of scattering runtime conditionals throughout the codebase, Superfile uses conditional compilation to swap entire implementation files based on the target operating system, ensuring clean separation between Unix-like systems and Windows.

Build Tags and Cross-Platform Architecture

Superfile employs Go's build constraints to create paired implementation files—one for Windows (//go:build windows) and one for all other platforms (//go:build !windows). The Go toolchain automatically selects the appropriate file during compilation, compiling out irrelevant code paths and preventing platform-specific system calls from leaking into wrong binaries.

This architectural pattern covers four critical subsystems:

  • Process detaching (DetachFromTerminal)
  • File preview launching (OpenPreview)
  • Metadata extraction (GetMetadata)
  • Trash operations (MoveToTrash)

Process Detaching Implementation

Unix Session Management

In src/pkg/utils/detach_unix.go, Superfile detaches processes from the terminal by creating new session leaders. The implementation configures syscall.SysProcAttr with Setsid: true to create a new session, sets Setpgid: true to ensure the child becomes a process group leader, and clears standard I/O file descriptors to sever ties with the controlling terminal.

Windows Window Management

The Windows implementation in src/pkg/utils/detach_windows.go uses syscall.SysProcAttr{HideWindow: true} to spawn background processes without creating visible console windows. This achieves functional parity with Unix session detaching while adhering to Windows-specific process creation semantics.

// Detach a command from terminal (platform-agnostic API)
cmd := exec.Command("bash", "-c", "sleep 30")
utils.DetachFromTerminal(cmd) // Compiler selects Unix or Windows implementation
cmd.Start()

File Preview System

Unix Desktop Integration

src/pkg/file_preview/utils_unix.go implements file opening by shelling out to standard POSIX utilities. It attempts xdg-open (Linux freedesktop), open (macOS), and gio open (GNOME) in sequence, manipulating file descriptors to handle the handoff cleanly without blocking the terminal.

Windows Shell Execution

src/pkg/file_preview/utils_windows.go relies on the Windows start command via cmd /c to invoke the default application associated with file types. This leverages the Windows registry file associations rather than direct system calls, ensuring previews open with the user's preferred applications.

// Open file with OS-specific launcher
if err := filepreview.OpenPreview("/path/to/document.pdf"); err != nil {
    log.Fatalf("preview failed: %v", err)
}

Metadata Extraction UI

Unix Stat Structure

src/internal/ui/metadata/metadata_unix.go extracts ownership and timestamps using syscall.Stat_t. It reads Uid, Gid, Mode, Atime, and Mtime directly from POSIX stat structures, resolving numeric IDs to human-readable user and group names through system lookups.

Windows File Attributes

src/internal/ui/metadata/metadata_windows.go retrieves metadata via syscall.Win32FileAttributeData. It translates Windows-specific attributes (file times, attributes mask) into the same struct shape used by the UI layer, converting Windows epoch times to Unix timestamps for consistency.

// Retrieve file metadata (same struct on all platforms)
meta, err := metadata.GetMetadata("/path/to/file")
if err == nil {
    fmt.Printf("Size: %d, Owner: %s, Modified: %s\n", 
        meta.Size, meta.Owner, meta.ModTime)
}

Trash and Recycle Bin Handling

XDG Trash Specification

src/internal/trash/trash_unix.go implements the freedesktop.org XDG Trash specification. It moves files to $XDG_DATA_HOME/Trash/files/ and creates corresponding .trashinfo metadata files in Trash/info/, ensuring compatibility with standard Linux desktop environments and macOS trash mechanisms.

Windows Shell API

src/internal/trash/trash_windows.go utilizes the Windows Shell API (SHFileOperation) or the Recycle Bin COM interface to move items to the system recycle bin. This preserves Windows Explorer's undo functionality and respects the user's Recycle Bin size limits and settings.

// Cross-platform trash operation
if err := trash.MoveToTrash("/path/to/file"); err != nil {
    log.Fatalf("trash operation failed: %v", err)
}

Summary

  • Build tags (//go:build windows vs //go:build !windows) enable compile-time platform selection without runtime overhead or binary bloat.
  • Process detaching uses Setsid and cleared descriptors on Unix versus HideWindow attributes on Windows to achieve background execution.
  • File previews leverage xdg-open/open on Unix versus cmd /c start on Windows through a unified OpenPreview function.
  • Metadata extraction bridges syscall.Stat_t and Win32FileAttributeData behind a consistent interface used by the TUI.
  • Trash operations implement XDG Trash standards on Unix and Shell API recycling on Windows via the same MoveToTrash signature.

Frequently Asked Questions

How does Superfile avoid runtime platform checks?

Superfile relies entirely on Go's build constraints system. By tagging files with //go:build windows or //go:build !windows, the Go compiler includes only the appropriate implementation at build time. This eliminates if runtime.GOOS == "windows" conditionals throughout the main codebase and prevents Windows API calls from being compiled into Linux binaries.

Are the platform implementations drop-in replacements?

Yes. Each file pair exports identically named functions with matching signatures. For example, both src/pkg/utils/detach_unix.go and detach_windows.go export DetachFromTerminal(cmd *exec.Cmd), ensuring the rest of the application imports utils and calls the function without knowing which underlying implementation is active.

Why use build tags instead of interfaces?

Build tags produce smaller, faster binaries by compiling out irrelevant code paths entirely. They also provide compile-time safety—attempting to call Windows-specific APIs in a Unix file will fail at compilation rather than runtime. This approach avoids the complexity of interface abstraction for operations that never change at runtime.

Does Superfile support other operating systems beyond Unix and Windows?

The current codebase uses !windows to capture all non-Windows platforms, which includes Linux, macOS, and BSD systems. The Unix implementations rely on POSIX-compliant system calls (such as stat and setsid) that work across these operating systems without requiring separate build constraints for each variant.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →