Confer is a small Go CLI for checking URL health from the terminal. It fetches multiple URLs concurrently, records HTTP status codes, measures response time, handles timeouts, and prints a styled summary table.
- Concurrent URL checks with goroutines
- Configurable request timeout
- URL input from command-line arguments or a file
- Stable output order matching the input order
- Styled terminal UI with Lip Gloss and Bubbles
- Summary stats for successful, failed, fastest, and slowest requests
Run with the default sample URLs:
go run .Check specific URLs:
go run . https://example.com https://github.comSet a timeout:
go run . -timeout=2s https://example.com https://github.comRead URLs from a file:
go run . -file=urls.txt -timeout=3sExample urls.txt:
https://example.com
https://github.com
https://cloudflare.com
From this project directory:
go install .Make sure Go's bin directory is in your PATH:
export PATH="$HOME/go/bin:$PATH"Then run confer from anywhere:
confer -timeout=2s https://example.com https://github.comIf this repository is pushed to GitHub, other users can install it with:
go install github.com/vedantlavale/confer@latestconfer/
├── main.go
├── fetcher/
│ └── fetcher.go
├── go.mod
├── go.sum
└── README.md
flowchart TD
Root["confer module"] --> Main["main.go<br/>CLI, flags, output rendering"]
Root --> Fetcher["fetcher/fetcher.go<br/>HTTP request logic"]
Root --> Mod["go.mod<br/>module and dependencies"]
Root --> Sum["go.sum<br/>dependency checksums"]
Main -->|"calls"| Fetcher
Main -->|"uses"| Lipgloss["lipgloss<br/>styles and panels"]
Main -->|"uses"| Bubbles["bubbles/table<br/>terminal table"]
Main -->|"uses"| Term["golang.org/x/term<br/>terminal width"]
Fetcher -->|"uses"| NetHTTP["net/http<br/>HTTP client"]
At a high level, main.go handles input and presentation, while fetcher does the HTTP work.
flowchart LR
Start([Start CLI]) --> Flags["Parse flags<br/>-timeout, -file"]
Flags --> URLs["Collect URLs<br/>file + args + defaults"]
URLs --> FetchAll["fetchAll(urls, timeout)"]
FetchAll --> RenderTable["Render results table"]
RenderTable --> RenderSummary["Render summary panel"]
RenderSummary --> Done([Done])
fetchAll uses a fan-out/fan-in pattern:
- Fan out: launch one goroutine per URL
- Work: each goroutine calls
fetcher.FetchWithTimeout - Fan in: each goroutine sends its result into a channel
- Wait: a
sync.WaitGroupcloses the channel after all goroutines finish - Order: results are sorted back into the original input order
sequenceDiagram
participant Main as main goroutine
participant WG as sync.WaitGroup
participant CH as results channel
participant G1 as goroutine: URL 1
participant G2 as goroutine: URL 2
participant GN as goroutine: URL N
Main->>WG: Add one task per URL
Main->>G1: start FetchWithTimeout
Main->>G2: start FetchWithTimeout
Main->>GN: start FetchWithTimeout
G1->>CH: send indexed result
G1->>WG: Done
G2->>CH: send indexed result
G2->>WG: Done
GN->>CH: send indexed result
GN->>WG: Done
Main->>WG: Wait
WG-->>Main: all done
Main->>CH: close channel
Main->>Main: sort results by original index
The fetcher package exposes two functions:
func Fetch(url string) FetchResultUses the default 5s timeout.
func FetchWithTimeout(url string, timeout time.Duration) FetchResultUses a caller-provided timeout.
The returned struct contains everything needed for reporting:
type FetchResult struct {
URL string
StatusCode int
Duration time.Duration
Err error
}flowchart TD
URL["URL string"] --> Request["HTTP GET request"]
Request --> Response{"Request succeeded?"}
Response -->|"yes"| Status["StatusCode<br/>Duration<br/>Err=nil"]
Response -->|"no"| Error["URL<br/>Duration<br/>Err"]
Status --> Result["FetchResult"]
Error --> Result
Result --> Table["Styled table row"]
Result --> Summary["Summary stats"]
Format code:
gofmt -w main.go fetcher/fetcher.goRun tests:
go test ./...Run the CLI:
go run . -timeout=2s https://example.comgithub.com/charmbracelet/lipglossfor styling terminal outputgithub.com/charmbracelet/bubbles/tablefor table renderinggolang.org/x/termfor terminal width detection- Go standard library packages like
net/http,sync,flag, andtime