Skip to content

Instantly share code, notes, and snippets.

@cameroncooke
Created August 28, 2025 12:29
Show Gist options
  • Select an option

  • Save cameroncooke/ff5f2d6636c402b351bc66566f771a26 to your computer and use it in GitHub Desktop.

Select an option

Save cameroncooke/ff5f2d6636c402b351bc66566f771a26 to your computer and use it in GitHub Desktop.
Claude Code Statusline - High-performance Zig implementation with simple compilation instructions

Claude Code Statusline (Zig)

A high-performance statusline implementation for Claude Code written in Zig.

Features

  • Fast execution (sub-millisecond)
  • Shows time, user@hostname, current directory, git status, model name, and output style
  • Proper home directory abbreviation (~)
  • Git branch and dirty status indication
  • Color-coded output with ANSI escape sequences

Installation

1. Install Zig

macOS (Homebrew):

brew install zig

Linux:

# Download latest from https://ziglang.org/download/
# Or use your package manager, e.g.:
sudo apt install zig-dev  # Ubuntu/Debian

Windows:

# Download from https://ziglang.org/download/
# Or use Scoop:
scoop install zig

2. Compile the Statusline

# Create the .claude directory if it doesn't exist
mkdir -p ~/.claude

# Save statusline.zig to ~/.claude/statusline.zig
# Then compile:
cd ~/.claude
zig build-exe statusline.zig -O ReleaseFast -femit-bin=statusline

3. Configure Claude Code

Add this to your Claude Code statusline configuration:

{
  "statusline": {
    "command": "~/.claude/statusline"
  }
}

Output Format

The statusline displays:

  • 12:34:56 - Current time (dimmed)
  • user@hostname - Username and hostname (green, dimmed)
  • ~/path/to/dir - Current directory with home abbreviation (blue, dimmed)
  • (main*) - Git branch with dirty indicator if applicable (yellow, dimmed)
  • [Claude Opus] - Model name (magenta, dimmed)
  • (custom) - Output style if not default (cyan, dimmed)

Requirements

  • Zig compiler
  • Unix-like system (macOS, Linux)
  • Git (for git status display)
const std = @import("std");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
// Read JSON from stdin using the correct API for Zig 0.15.1
const stdin_file = std.io.getStdIn();
const input = try stdin_file.readToEndAlloc(allocator, 64 * 1024);
defer allocator.free(input);
// Parse basic info from JSON
var parsed = std.json.parseFromSlice(std.json.Value, allocator, input, .{}) catch {
std.debug.print("Claude Code", .{});
return;
};
defer parsed.deinit();
const root = parsed.value;
// Extract model name
const model_name = if (root.object.get("model")) |model_obj|
if (model_obj.object.get("display_name")) |name| name.string else "Claude"
else
"Claude";
// Extract current directory
const current_dir = if (root.object.get("workspace")) |workspace_obj|
if (workspace_obj.object.get("current_dir")) |dir| dir.string else ""
else if (root.object.get("cwd")) |cwd| cwd.string else "";
// Get current time
const timestamp = std.time.timestamp();
const epoch_seconds = @as(u64, @intCast(timestamp));
const seconds_today = epoch_seconds % std.time.s_per_day;
const hours = seconds_today / std.time.s_per_hour;
const minutes = (seconds_today % std.time.s_per_hour) / std.time.s_per_min;
const seconds = seconds_today % std.time.s_per_min;
// Get username
const username_result = std.ChildProcess.run(.{
.allocator = allocator,
.argv = &[_][]const u8{"whoami"},
}) catch {
std.debug.print("\x1b[2m{d:0>2}:{d:0>2}:{d:0>2}\x1b[0m \x1b[2;35m[{s}]\x1b[0m", .{ hours, minutes, seconds, model_name });
return;
};
defer allocator.free(username_result.stdout);
defer allocator.free(username_result.stderr);
const username = std.mem.trim(u8, username_result.stdout, " \t\n\r");
// Get hostname
const hostname_result = std.ChildProcess.run(.{
.allocator = allocator,
.argv = &[_][]const u8{ "hostname", "-s" },
}) catch {
std.debug.print("\x1b[2m{d:0>2}:{d:0>2}:{d:0>2}\x1b[0m \x1b[2;32m{s}\x1b[0m \x1b[2;35m[{s}]\x1b[0m", .{ hours, minutes, seconds, username, model_name });
return;
};
defer allocator.free(hostname_result.stdout);
defer allocator.free(hostname_result.stderr);
const hostname = std.mem.trim(u8, hostname_result.stdout, " \t\n\r");
// Get short path
const home = std.posix.getenv("HOME") orelse "";
var short_path: []const u8 = current_dir;
var path_buf: [256]u8 = undefined;
if (home.len > 0 and std.mem.startsWith(u8, current_dir, home)) {
const relative = current_dir[home.len..];
if (relative.len == 0) {
short_path = "~";
} else {
short_path = try std.fmt.bufPrint(&path_buf, "~{s}", .{relative});
}
}
// Build status line without git for now
std.debug.print("\x1b[2m{d:0>2}:{d:0>2}:{d:0>2}\x1b[0m \x1b[2;32m{s}@{s}\x1b[0m \x1b[2;34m{s}\x1b[0m \x1b[2;35m[{s}]\x1b[0m", .{ hours, minutes, seconds, username, hostname, short_path, model_name });
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment