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

> Explore Unix vs Windows platform-specific implementations in Superfile using Go build tags. Learn how Superfile handles OS differences for core features while maintaining consistent APIs.

- Repository: [Yorukot/superfile](https://github.com/yorukot/superfile)
- Tags: internals
- Published: 2026-07-28

---

**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`](https://github.com/yorukot/superfile/blob/main/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`](https://github.com/yorukot/superfile/blob/main/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.

```go
// 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`](https://github.com/yorukot/superfile/blob/main/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`](https://github.com/yorukot/superfile/blob/main/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.

```go
// 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`](https://github.com/yorukot/superfile/blob/main/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`](https://github.com/yorukot/superfile/blob/main/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.

```go
// 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`](https://github.com/yorukot/superfile/blob/main/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`](https://github.com/yorukot/superfile/blob/main/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.

```go
// 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`](https://github.com/yorukot/superfile/blob/main/src/pkg/utils/detach_unix.go) and [`detach_windows.go`](https://github.com/yorukot/superfile/blob/main/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.