Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
ci:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-go@v5
with:
go-version: "1.25"

- name: Vet
run: go vet ./...

- name: Test
run: go test ./... -count=1

- name: Test (race)
run: go test -race ./... -count=1
Comment on lines +23 to +26
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The workflow runs go test ./... (and -race) but the current test suite includes at least one environment-dependent test that will fail on GitHub runners (e.g. internal/gather/gather_test.go uses /Users/kyle/Code/my-projects/vitals and expects it to be a real git repo). This will cause CI to fail for every PR until those tests are rewritten to use a temp git repo fixture (or skipped/guarded appropriately).

Suggested change
run: go test ./... -count=1
- name: Test (race)
run: go test -race ./... -count=1
run: go list ./... | grep -v '/internal/gather' | xargs go test -count=1
- name: Test (race)
run: go list ./... | grep -v '/internal/gather' | xargs go test -race -count=1

Copilot uses AI. Check for mistakes.
6 changes: 6 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
repos:
- repo: https://github.com/dnephin/pre-commit-golang
rev: v0.5.1
hooks:
- id: go-fmt
- id: go-vet
20 changes: 10 additions & 10 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@ vitals is a Go binary that renders a terminal statusline for Claude Code session

## Build & Test

Uses `just` (justfile) for all tasks:
Uses `make` for all tasks:

```sh
just # default: run tests
just build # go install ./cmd/vitals
just test # go test ./... -count=1
just test-race # go test -race ./... -count=1
just bench # go test -bench=. -benchmem ./internal/... -count=1
just check # fmt + vet + test
just dump # build + render from current session's transcript
just run-sample # pipe testdata/sample-stdin.json through the binary
make # default: run tests
make build # go install ./cmd/vitals
make test # go test ./... -count=1
make test-race # go test -race ./... -count=1
make bench # go test -bench=. -benchmem ./internal/... -count=1
make check # fmt + vet + test
make dump # build + render from current session's transcript
make run-sample # pipe testdata/sample-stdin.json through the binary
```

Run a single test:
Expand All @@ -38,7 +38,7 @@ stdin → gather → render → stdout

3. **render** (`internal/render`): Walks configured lines, calls each widget's `RenderFunc` from the registry, joins non-empty results with the separator, and ANSI-truncates to terminal width.

4. **widget** (`internal/render/widget`): 16 registered widgets (model, context, cost, directory, git, project, duration, tools, agents, todos, tokens, lines, messages, speed, permission, usage). Each is a pure function: `(RenderContext, Config) -> WidgetResult`. Returns empty when it has nothing to show.
4. **widget** (`internal/render/widget`): 18 registered widgets (model, context, cost, directory, git, project, service, duration, tools, agents, todos, tokens, lines, messages, speed, permission, usage, worktree). Each is a pure function: `(RenderContext, Config) -> WidgetResult`. Returns empty when it has nothing to show.

## Key Design Decisions

Expand Down
118 changes: 0 additions & 118 deletions Justfile

This file was deleted.

36 changes: 36 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
.DEFAULT_GOAL := test

.PHONY: build test test-race bench fmt vet check dump run-sample eval clean

build:
go install ./cmd/vitals

test:
go test ./... -count=1

test-race:
go test -race ./... -count=1

bench:
go test -bench=. -benchmem ./internal/... -count=1

fmt:
go fmt ./...

vet:
go vet ./...

check: fmt vet test

dump: build
vitals --dump-current

run-sample:
cat testdata/sample-stdin.json | go run ./cmd/vitals

eval:
go test ./internal/eval/ -run TestDesignEval -v -count=1

clean:
rm -rf bin/
rm -f $$(go env GOPATH)/bin/vitals
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

A terminal statusline for [Claude Code](https://docs.anthropic.com/en/docs/claude-code) sessions.

![vitals demo](demo.gif)

## Install

```bash
Expand All @@ -25,6 +23,17 @@ Add to `~/.claude/settings.json`:

To customize, run `vitals --init` to generate a config at `~/.config/vitals/config.toml`.

## Development

```bash
# Install pre-commit hooks
pip install pre-commit
pre-commit install

# Run tests
make test
```

## License

[MIT](LICENSE)
1 change: 0 additions & 1 deletion VERSION

This file was deleted.

22 changes: 2 additions & 20 deletions cmd/vitals/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
"github.com/Jason-Adam/vitals/internal/preset"
"github.com/Jason-Adam/vitals/internal/render"
"github.com/Jason-Adam/vitals/internal/stdin"
"github.com/Jason-Adam/vitals/internal/version"
"github.com/lucasb-eyer/go-colorful"
)

Expand All @@ -37,9 +36,6 @@ func main() {
case "hook":
runHook()
return
case "version", "--version", "-version", "-v":
fmt.Println(version.String())
return
case "update":
runUpdate()
return
Expand Down Expand Up @@ -428,7 +424,7 @@ func isLightColor(c color.Color) bool {
// interpreted by the terminal. Useful for verifying that threshold colors,
// powerline backgrounds, and other ANSI styling are actually present.
func printRaw(w io.Writer, data []byte) {
for i := 0; i < len(data); i++ {
for i := range len(data) {
if data[i] == 0x1b {
fmt.Fprint(w, `\x1b`)
} else {
Expand Down Expand Up @@ -467,8 +463,6 @@ func runHook() {

// runUpdate installs the latest version via go install.
func runUpdate() {
current := version.String()
fmt.Printf("Current version: %s\n", current)
fmt.Printf("Installing latest from %s...\n", installPath)

cmd := exec.Command("go", "install", installPath)
Expand All @@ -479,18 +473,7 @@ func runUpdate() {
os.Exit(1)
}

// Run the newly installed binary to get its version.
out, err := exec.Command("vitals", "version").Output()
if err != nil {
fmt.Println("Updated successfully.")
return
}
newVersion := strings.TrimSpace(string(out))
if newVersion == current {
fmt.Printf("Already up to date (%s).\n", current)
} else {
fmt.Printf("Updated %s -> %s\n", current, newVersion)
}
fmt.Println("Updated successfully.")
}

// usage prints help with -- prefixed flags (Go's flag package defaults to single -).
Expand All @@ -499,7 +482,6 @@ func usage() {
fmt.Fprintf(os.Stderr, "Commands:\n")
fmt.Fprintf(os.Stderr, " hook <event> handle a Claude Code hook event\n")
fmt.Fprintf(os.Stderr, " update install the latest version via go install\n")
fmt.Fprintf(os.Stderr, " version print the current version\n")
fmt.Fprintf(os.Stderr, "\nFlags:\n")
flag.VisitAll(func(f *flag.Flag) {
name := f.Name
Expand Down
Binary file removed demo.gif
Binary file not shown.
32 changes: 0 additions & 32 deletions docs/architecture.md

This file was deleted.

30 changes: 0 additions & 30 deletions docs/cli.md

This file was deleted.

Loading
Loading