Use gopsutil for cross-platform process detection
Replace pgrep with gopsutil/v4 for pure Go process detection. Now fully cross-platform (Linux, FreeBSD, macOS, Windows) with zero external exec calls. Add Taskfile and test fixture.
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,6 +1,8 @@
|
||||
/statusline
|
||||
/bin
|
||||
|
||||
/.task
|
||||
|
||||
# Created by https://gitignore.kjanat.com/api/go,linux
|
||||
# Edit at https://gitignore.kjanat.com?templates=go,linux
|
||||
|
||||
|
||||
89
Taskfile.yml
Normal file
89
Taskfile.yml
Normal file
@ -0,0 +1,89 @@
|
||||
# https://taskfile.dev
|
||||
|
||||
version: '3'
|
||||
|
||||
vars:
|
||||
BINARY: statusline
|
||||
LDFLAGS: -s -w
|
||||
|
||||
tasks:
|
||||
default:
|
||||
desc: Build the statusline binary
|
||||
cmds:
|
||||
- task: build
|
||||
|
||||
build:
|
||||
desc: Build with stripped symbols
|
||||
cmds:
|
||||
- go build -ldflags="{{.LDFLAGS}}" -o {{.BINARY}} .
|
||||
sources:
|
||||
- "*.go"
|
||||
- go.mod
|
||||
- go.sum
|
||||
generates:
|
||||
- "{{.BINARY}}"
|
||||
|
||||
build:debug:
|
||||
desc: Build with debug symbols
|
||||
cmds:
|
||||
- go build -o {{.BINARY}} .
|
||||
|
||||
run:
|
||||
desc: Run with test fixture
|
||||
deps: [build]
|
||||
cmds:
|
||||
- cat test/fixture.json | ./{{.BINARY}}
|
||||
|
||||
test:
|
||||
desc: Run with test fixture and show output
|
||||
deps: [build]
|
||||
cmds:
|
||||
- echo "=== Output ==="
|
||||
- cat test/fixture.json | ./{{.BINARY}}
|
||||
- echo ""
|
||||
- echo "=== Timing (single run) ==="
|
||||
- time sh -c 'cat test/fixture.json | ./{{.BINARY}} > /dev/null'
|
||||
|
||||
bench:
|
||||
desc: Benchmark Go vs Shell (100 runs)
|
||||
deps: [build]
|
||||
cmds:
|
||||
- |
|
||||
echo "=== Pure Go (100 runs) ==="
|
||||
time for i in $(seq 1 100); do cat test/fixture.json | ./{{.BINARY}} >/dev/null; done
|
||||
echo ""
|
||||
echo "=== Shell (100 runs) ==="
|
||||
time for i in $(seq 1 100); do cat test/fixture.json | ./statusline.sh >/dev/null; done
|
||||
silent: false
|
||||
|
||||
bench:go:
|
||||
desc: Benchmark Go only (100 runs)
|
||||
deps: [build]
|
||||
cmds:
|
||||
- |
|
||||
echo "=== Pure Go (100 runs) ==="
|
||||
time for i in $(seq 1 100); do cat test/fixture.json | ./{{.BINARY}} >/dev/null; done
|
||||
|
||||
tidy:
|
||||
desc: Run go mod tidy
|
||||
cmds:
|
||||
- go mod tidy
|
||||
|
||||
clean:
|
||||
desc: Remove built binary
|
||||
cmds:
|
||||
- rm -f {{.BINARY}}
|
||||
|
||||
size:
|
||||
desc: Show binary size
|
||||
deps: [build]
|
||||
cmds:
|
||||
- ls -lh {{.BINARY}}
|
||||
|
||||
install:
|
||||
desc: Install to ~/.claude/
|
||||
deps: [build]
|
||||
cmds:
|
||||
- mkdir -p ~/.claude
|
||||
- cp {{.BINARY}} ~/.claude/{{.BINARY}}
|
||||
- echo "Installed to ~/.claude/{{.BINARY}}"
|
||||
8
go.mod
8
go.mod
@ -4,6 +4,7 @@ go 1.24.11
|
||||
|
||||
require (
|
||||
github.com/go-git/go-git/v6 v6.0.0-20251216093047-22c365fcee9c
|
||||
github.com/shirou/gopsutil/v4 v4.25.11
|
||||
golang.org/x/sys v0.39.0
|
||||
)
|
||||
|
||||
@ -12,14 +13,21 @@ require (
|
||||
github.com/ProtonMail/go-crypto v1.3.0 // indirect
|
||||
github.com/cloudflare/circl v1.6.1 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.6.1 // indirect
|
||||
github.com/ebitengine/purego v0.9.1 // indirect
|
||||
github.com/emirpasic/gods v1.18.1 // indirect
|
||||
github.com/go-git/gcfg/v2 v2.0.2 // indirect
|
||||
github.com/go-git/go-billy/v6 v6.0.0-20251209065551-8afc3eb64e4d // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
||||
github.com/kevinburke/ssh_config v1.4.0 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||
github.com/pjbgf/sha1cd v0.5.0 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
|
||||
github.com/sergi/go-diff v1.4.0 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.16 // indirect
|
||||
github.com/tklauser/numcpus v0.11.0 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||
golang.org/x/crypto v0.46.0 // indirect
|
||||
golang.org/x/net v0.48.0 // indirect
|
||||
)
|
||||
|
||||
22
go.sum
22
go.sum
@ -13,6 +13,8 @@ github.com/cyphar/filepath-securejoin v0.6.1/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/ebitengine/purego v0.9.1 h1:a/k2f2HQU3Pi399RPW1MOaZyhKJL9w/xFpKAg4q1s0A=
|
||||
github.com/ebitengine/purego v0.9.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
||||
github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o=
|
||||
github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE=
|
||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||
@ -27,8 +29,13 @@ github.com/go-git/go-git-fixtures/v5 v5.1.2-0.20251205091929-ed656e84d025 h1:24U
|
||||
github.com/go-git/go-git-fixtures/v5 v5.1.2-0.20251205091929-ed656e84d025/go.mod h1:T6lRF5ejdxaYZLVaCTuTG1+ZSvwI/c2oeiTgBWORJ8Q=
|
||||
github.com/go-git/go-git/v6 v6.0.0-20251216093047-22c365fcee9c h1:pR4UmnVFMjNw956fgu+JlSAvmx37qW4ttVF0cu7DL/Q=
|
||||
github.com/go-git/go-git/v6 v6.0.0-20251216093047-22c365fcee9c/go.mod h1:EPzgAjDnw+TaCt1w/JUmj+SXwWHUae3c078ixiZQ10Y=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/kevinburke/ssh_config v1.4.0 h1:6xxtP5bZ2E4NF5tuQulISpTO2z8XbtH8cg1PWkxoFkQ=
|
||||
github.com/kevinburke/ssh_config v1.4.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
||||
@ -36,26 +43,41 @@ github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||
github.com/pjbgf/sha1cd v0.5.0 h1:a+UkboSi1znleCDUNT3M5YxjOnN1fz2FhN48FlwCxs0=
|
||||
github.com/pjbgf/sha1cd v0.5.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw=
|
||||
github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
||||
github.com/shirou/gopsutil/v4 v4.25.11 h1:X53gB7muL9Gnwwo2evPSE+SfOrltMoR6V3xJAXZILTY=
|
||||
github.com/shirou/gopsutil/v4 v4.25.11/go.mod h1:EivAfP5x2EhLp2ovdpKSozecVXn1TmuG7SMzs/Wh4PU=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/tklauser/go-sysconf v0.3.16 h1:frioLaCQSsF5Cy1jgRBrzr6t502KIIwQ0MArYICU0nA=
|
||||
github.com/tklauser/go-sysconf v0.3.16/go.mod h1:/qNL9xxDhc7tx3HSRsLWNnuzbVfh3e7gh/BmM179nYI=
|
||||
github.com/tklauser/numcpus v0.11.0 h1:nSTwhKH5e1dMNsCdVBukSZrURJRoHbSEQjdEbY+9RXw=
|
||||
github.com/tklauser/numcpus v0.11.0/go.mod h1:z+LwcLq54uWZTX0u/bGobaV34u6V7KNlTZejzM6/3MQ=
|
||||
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
||||
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
|
||||
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
|
||||
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
|
||||
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
|
||||
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q=
|
||||
golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg=
|
||||
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
|
||||
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
||||
20
main.go
20
main.go
@ -5,12 +5,12 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/go-git/go-git/v6"
|
||||
"github.com/shirou/gopsutil/v4/process"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
@ -118,10 +118,20 @@ func formatContextInfo(contextSize int, usage *struct {
|
||||
}
|
||||
|
||||
func getGiteaStatus() string {
|
||||
// Check if gitea process is running using pgrep
|
||||
cmd := exec.Command("pgrep", "-x", "gitea")
|
||||
if err := cmd.Run(); err == nil {
|
||||
return green + "●" + reset
|
||||
// Check if gitea process is running using gopsutil (cross-platform)
|
||||
procs, err := process.Processes()
|
||||
if err != nil {
|
||||
return red + "●" + reset
|
||||
}
|
||||
|
||||
for _, p := range procs {
|
||||
name, err := p.Name()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if name == "gitea" {
|
||||
return green + "●" + reset
|
||||
}
|
||||
}
|
||||
return red + "●" + reset
|
||||
}
|
||||
|
||||
36
test/fixture.json
Normal file
36
test/fixture.json
Normal file
@ -0,0 +1,36 @@
|
||||
{
|
||||
"hook_event_name": "Status",
|
||||
"session_id": "abc123def456",
|
||||
"transcript_path": "/tmp/transcript.json",
|
||||
"cwd": "/root/projects/statusline",
|
||||
"model": {
|
||||
"id": "claude-opus-4-5-20251101",
|
||||
"display_name": "Opus 4.5"
|
||||
},
|
||||
"workspace": {
|
||||
"current_dir": "/root/projects/statusline",
|
||||
"project_dir": "/root/projects/statusline"
|
||||
},
|
||||
"version": "1.0.80",
|
||||
"output_style": {
|
||||
"name": "default"
|
||||
},
|
||||
"cost": {
|
||||
"total_cost_usd": 0.01234,
|
||||
"total_duration_ms": 45000,
|
||||
"total_api_duration_ms": 2300,
|
||||
"total_lines_added": 156,
|
||||
"total_lines_removed": 23
|
||||
},
|
||||
"context_window": {
|
||||
"total_input_tokens": 15234,
|
||||
"total_output_tokens": 4521,
|
||||
"context_window_size": 200000,
|
||||
"current_usage": {
|
||||
"input_tokens": 8500,
|
||||
"output_tokens": 1200,
|
||||
"cache_creation_input_tokens": 5000,
|
||||
"cache_read_input_tokens": 2000
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user