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
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ body:
id: version
attributes:
label: ipcheck version
placeholder: ipcheck 0.8.0
placeholder: ipcheck 0.8.1
validations:
required: true
- type: dropdown
Expand Down
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ All notable changes to ipcheck are documented here. The project follows

## [Unreleased]

## [0.8.1] - 2026-07-23

### Changed

- Refocused the English and Chinese READMEs on quick installation, the
difference from generic speed tests, common commands, and privacy guarantees;
moved scoring, network, and automation details into bilingual reference docs.
- Updated both terminal demos to transition from a healthy network to a
realistically limited proxy route with actionable bottleneck hints.

## [0.8.0] - 2026-07-23

### Added
Expand Down Expand Up @@ -122,6 +132,8 @@ All notable changes to ipcheck are documented here. The project follows
- Homebrew and direct-download packaging.
- Median/P95 TTFB, jitter, reference bandwidth, and macOS `networkQuality`.

[Unreleased]: https://github.com/jacklv-coder/ipcheck/compare/v0.8.1...HEAD
[0.8.1]: https://github.com/jacklv-coder/ipcheck/compare/v0.8.0...v0.8.1
[0.8.0]: https://github.com/jacklv-coder/ipcheck/compare/v0.7.0...v0.8.0
[0.7.0]: https://github.com/jacklv-coder/ipcheck/compare/v0.6.1...v0.7.0
[0.6.1]: https://github.com/jacklv-coder/ipcheck/compare/v0.6.0...v0.6.1
Expand Down
291 changes: 88 additions & 203 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,177 +6,110 @@

[简体中文](README.zh-CN.md)

Know whether your AI coding CLI is slow, blocked, or using the wrong gateway.
Know whether **Codex** or **Claude Code** is slow, blocked, or using the wrong
proxy before it breaks your coding flow.

`ipcheck` is a zero-dependency Bash CLI for the real network paths used by
**Codex** and **Claude Code**. It auto-detects installed clients and safe,
non-secret routing configuration, then reports reachability, median/P95
time-to-first-byte (TTFB), jitter, reference bandwidth, and a clear
`GOOD`, `FAIR`, `POOR`, or `BLOCKED` result. Interactive runs show animated,
color-coded progress, can be cancelled cleanly with `Ctrl+C`, and finish with
an adaptive terminal dashboard plus a rule-based readiness score.
`ipcheck` is a zero-dependency Bash CLI that tests the real service routes used
by AI coding clients. It reports reachability, median/P95 time to first byte,
jitter, reference download/upload speed, and a plain-language readiness score.
It never reads API keys, sends prompts, or makes billable model requests.

![Animated ipcheck terminal demo](assets/ipcheck-demo.gif)
![Animated ipcheck terminal demo showing healthy and limited networks](assets/ipcheck-demo.gif)

```text
$ ipcheck
ipcheck v0.8.0 AI coding network check
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
## Quick start

✓ Ready to code? YES
100/100 ████████████████████ COMFORTABLE

This network is ready for AI-assisted development.

◆ AI service latency
✓ REACH ChatGPT Codex HTTP 401 · median 260 ms
✓ REACH Claude Messages API Claude Code HTTP 403 · median 220 ms

◆ AI service results
● Codex GOOD · ● Claude Code GOOD

◆ Network bandwidth
Download 80.0 Mbps FAST Cloudflare, up to 2 MB
Upload 16.0 Mbps FAST Cloudflare, up to 1 MB zero-filled
```bash
brew install jacklv-coder/tap/ipcheck
ipcheck
```

## Why ipcheck

- Tests the routes the clients actually use, including Claude-compatible
`${ANTHROPIC_BASE_URL}/v1/messages` gateways.
- Detects Codex `config.toml`, custom model providers, Claude Code
`settings.json`, `ANTHROPIC_BASE_URL`, and `ANTHROPIC_MODEL`.
- Understands OpenAI, Anthropic, LiteLLM-style gateways, and Alibaba Cloud
Model Studio/DashScope Anthropic-compatible routes.
- Reports each client separately, so one healthy service cannot hide another
blocked service.
- Never extracts, stores, prints, or sends API keys; never sends a prompt or
creates a billable model request.
- Produces human, Markdown, and stable versioned JSON output for support tickets
and automation.
- Runs on the Bash and curl already available on macOS and Linux.

For coding agents, TTFB, failures, and jitter usually matter more than peak
download bandwidth. `ipcheck` scores the service path separately from its
optional Cloudflare reference download.

## Install

### Homebrew
Already installed?

```bash
brew tap jacklv-coder/tap
brew install ipcheck
brew upgrade ipcheck
```

### Direct download
<details>
<summary>Install without Homebrew</summary>

```bash
mkdir -p "$HOME/.local/bin"
curl -fsSL https://raw.githubusercontent.com/jacklv-coder/ipcheck/v0.8.0/bin/ipcheck \
curl -fsSL https://raw.githubusercontent.com/jacklv-coder/ipcheck/v0.8.1/bin/ipcheck \

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Publish v0.8.1 before linking to it

The direct-install command now fetches the v0.8.1 tag, but this reviewed repository has no such tag or ref. Until that tag is published, users following the documented non-Homebrew installation path receive a 404 and cannot install the tool; publish the tag together with this change or point the command at an existing immutable ref.

Useful? React with 👍 / 👎.

-o "$HOME/.local/bin/ipcheck"
chmod +x "$HOME/.local/bin/ipcheck"
```

Make sure `$HOME/.local/bin` is on `PATH`.

## Usage
</details>

Auto-detect installed clients:
## Why not just use Speedtest?

```bash
ipcheck
ipcheck --quick
```
| Tool | What it tells you |
| --- | --- |
| Speedtest | Peak bandwidth to a nearby test server |
| `ping` / `curl` | Basic reachability to one address |
| `ipcheck` | Codex/Claude routes, proxy path, TTFB, P95, jitter, failures, bandwidth, and coding readiness |

Select a client explicitly:
For coding agents, a 500 Mbps connection can still feel slow when the first byte
takes five seconds or the proxy route is unstable. `ipcheck` measures those
interactive bottlenecks directly.

```bash
ipcheck codex
ipcheck claude
ipcheck all
ipcheck --service claude
```
## What makes it useful

Create shareable reports:
- Tests each detected client separately, so one healthy route cannot hide a
broken one.
- Understands OpenAI, Anthropic, LiteLLM-style gateways, and Alibaba Cloud
Model Studio/DashScope Anthropic-compatible routes.
- Explains whether the main problem is reachability, TTFB, P95, jitter,
download speed, or upload speed.
- Produces human, Markdown, and stable versioned JSON reports.
- Shows animated progress, adapts to narrow terminals, and exits cleanly with
status `130` when cancelled with `Ctrl+C`.

```bash
ipcheck --json > ipcheck-report.json
ipcheck --markdown > ipcheck-report.md
```
## Supported clients and routes

Explain every score component:
| Client | Configuration detected | Route tested |
| --- | --- | --- |
| Codex | `$CODEX_HOME/config.toml`, `model`, `openai_base_url`, custom provider | ChatGPT/OpenAI defaults or configured `/v1/responses` |
| Claude Code | `settings.json`, `ANTHROPIC_BASE_URL`, `ANTHROPIC_MODEL` | Configured `${ANTHROPIC_BASE_URL}/v1/messages` |
| Custom | `--endpoint`, `IPCHECK_ENDPOINTS` | User-provided HTTP/HTTPS endpoint |

```bash
ipcheck --explain-score
```
## Common commands

Tune or override a check:
| Command | Purpose |
| --- | --- |
| `ipcheck` | Auto-detect installed clients and run the standard check |
| `ipcheck --quick` | One sample, shorter timeout, no bandwidth transfer |
| `ipcheck codex` / `ipcheck claude` | Test only one client |
| `ipcheck all` | Test Codex and Claude Code together |
| `ipcheck --explain-score` | Show every score component |
| `ipcheck --json` | Emit structured output for automation |
| `ipcheck --markdown` | Create a shareable support report |
| `ipcheck --system` | Add macOS `networkQuality` measurements |
| `ipcheck --no-bandwidth` | Skip capped Cloudflare download/upload checks |

```bash
ipcheck --samples 10
ipcheck --timeout 30
ipcheck --system
ipcheck --explain-score
ipcheck --endpoint https://your-gateway.example.com/health
ipcheck --lang zh
ipcheck --no-progress --no-color
ipcheck --no-upload
```
Run `ipcheck --help` for every option and environment variable.

The human and Markdown reports default to the terminal/system language.
English and Simplified Chinese are currently supported. Any unsupported system
language falls back to English. Override detection with
`--lang en`, `--lang zh`, or `IPCHECK_LANG=en|zh`. JSON field names, enum values,
and diagnostic reasons remain stable English for automation. Progress is written
to stderr only for human output and can be controlled with
`IPCHECK_PROGRESS=auto|always|never`.

Interactive progress starts with `Press Ctrl+C to cancel at any time.` An
interrupt clears the live progress line, prints `Cancelled.`, removes temporary
files, and exits with the conventional status `130`.

The service table measures time to first byte and jitter; it is not a transfer
speed test. The separate bandwidth section downloads up to 2 MB and uploads up to 1 MB of
zero-filled data through the reported proxy/network path. It rates throughput
for common development work without allowing bandwidth to hide a slow or
unstable AI service. Use `--no-upload` to skip only the upload or
`--no-bandwidth` to skip both directions.

Bandwidth ratings use development-oriented thresholds: download is `FAST` at
25 Mbps or higher and `ADEQUATE` from 5 Mbps; upload is `FAST` at 10 Mbps or
higher and `ADEQUATE` from 2 Mbps. Lower measurements are `SLOW`. The optional
`--system` test delegates to macOS `networkQuality`, which can transfer
substantially more data than ipcheck's capped Cloudflare checks.

The readiness score is a transparent heuristic, not a claim about user
percentiles. Rule v2 gives the least healthy detected client up to 90
service-path points: reachability and success rate contribute 35, median TTFB
35, P95 10, and jitter 10. Each bandwidth direction adds 5 points when fast,
3 when adequate, deducts 5 when slow, and stays neutral when unavailable; an
incomplete sample deducts 2 more without hiding its measured speed class.
Usable-but-delayed paths are capped at 89, temporarily unavailable or poor
paths at 64, and blocked paths at 0. Score labels are `COMFORTABLE` from 90,
`GOOD` from 75, `USABLE` from 65, and `LIMITED` below 65. JSON exposes `score`,
`score_label`, `score_method`, and the per-component `score_breakdown` for
automation.

Run `ipcheck --help` for the complete option and environment-variable list.
## Reading the result

## Supported clients and routes
| Result | Meaning |
| --- | --- |
| `GOOD` | Reachable with comfortable first-byte latency and stability |
| `FAIR` | Usable, but delayed, intermittent, rate-limited, or temporarily unhealthy |
| `POOR` | Very slow, unstable, mostly unavailable, or using an invalid API route |
| `BLOCKED` | No service response, or the proxy rejected the request first |

| Client | Configuration detected | Network route tested |
| --- | --- | --- |
| Codex | `$CODEX_HOME/config.toml`, `model`, `openai_base_url`, selected custom provider | ChatGPT/OpenAI defaults or the configured `/v1/responses` route |
| Claude Code | `$CLAUDE_CONFIG_DIR/settings.json`, `~/.claude/settings.json`, `ANTHROPIC_BASE_URL`, `ANTHROPIC_MODEL` | Configured `${ANTHROPIC_BASE_URL}/v1/messages` route |
| Custom | `--endpoint`, `IPCHECK_ENDPOINTS` | User-provided GET endpoint(s) |
HTTP `401` and `403` count as reachable because DNS, proxying, TLS, and HTTP
reached the API route. HTTP `407` means the proxy blocked the request.

Legacy `CODEX_NETWORK_ENDPOINTS` remains supported. Claude-specific endpoint
overrides can use `CLAUDE_NETWORK_ENDPOINTS`.
The 0–100 score is a transparent rule, not a user percentile. It prioritizes
service reachability and latency over peak bandwidth. See
[Scoring and result rules](docs/scoring.md) for the exact calculation.

### Alibaba Cloud + Claude Code
## Claude Code gateway example

This common Claude Code configuration is auto-detected:
This configuration is auto-detected:

```json
{
Expand All @@ -188,86 +121,38 @@ This common Claude Code configuration is auto-detected:
}
```

`ipcheck claude` probes
`https://dashscope.aliyuncs.com/apps/anthropic/v1/messages` with an empty,
unauthenticated protocol check. It does not read `ANTHROPIC_AUTH_TOKEN`.

## Proxy behavior

`HTTPS_PROXY`, `HTTP_PROXY`, `ALL_PROXY`, and lowercase variants are reported
with credentials redacted. Claude probes intentionally ignore `ALL_PROXY` when
neither `HTTPS_PROXY` nor `HTTP_PROXY` is configured, matching Claude Code's
documented support boundary. On macOS, Codex and custom checks can fall back to
the configured system HTTPS proxy when an HTTPS proxy environment variable is
absent.

Claude Code supports `HTTPS_PROXY`, `HTTP_PROXY`, and `NO_PROXY`, but does not
support SOCKS proxies. `ipcheck` warns when its detected proxy configuration is
incompatible or likely to behave differently from curl or Codex. See Anthropic's
[corporate proxy documentation](https://docs.anthropic.com/en/docs/claude-code/corporate-proxy).

## Results

| Result | Meaning |
| --- | --- |
| `GOOD` | Every primary sample succeeded with acceptable TTFB and jitter. |
| `FAIR` | Reachable, but latency is elevated, samples failed, or the API is rate-limited/unhealthy. |
| `POOR` | Mostly unavailable, very slow/unstable, or the configured API route returned HTTP 404. |
| `BLOCKED` | No primary endpoint returned an HTTP response, or the proxy returned HTTP 407. |

HTTP 401 and 403 count as network-reachable because they prove DNS, proxying,
TLS, and HTTP reached the API route. HTTP 407 does not count because the proxy
rejected the request first. A 404 on a configured `/v1/messages` or
`/v1/responses` route is reported as `POOR` with a base-URL hint.

The default thresholds are:

- `GOOD`: 100% primary success, median TTFB below 800 ms, jitter below 1,000 ms.
- `FAIR`: all samples succeed and median TTFB is below 3,000 ms, or the path is
otherwise reachable with a recoverable warning.
- `POOR`: primary success below 60%, median TTFB at least 3,000 ms, or an invalid
configured API route.

## Privacy and security

`ipcheck` is intentionally a network-layer diagnostic:
`ipcheck claude` safely probes the corresponding `/v1/messages` route without
reading or sending `ANTHROPIC_AUTH_TOKEN`.

- The settings parser selects only named routing/model fields. Authentication
values are never extracted into shell variables or temporary files.
- API keys, bearer tokens, and cookies are never printed or passed to curl.
- Every curl invocation starts with `-q`, so user-level `.curlrc` files cannot
inject headers, cookies, credentials, or alternate routes.
- Claude/OpenAI protocol probes use an empty JSON object and cannot invoke a
model successfully without authentication.
- Proxy credentials are masked. Endpoint URLs are restricted to credential-free
HTTP/HTTPS paths; URL userinfo, query strings, and fragments are rejected.
- Temporary metrics are deleted on exit.
## Privacy by design

Please report vulnerabilities privately as described in [SECURITY.md](SECURITY.md).
- Authentication values never enter shell variables or temporary files.
- API keys, bearer tokens, cookies, and prompts are never sent to curl.
- Proxy credentials are redacted; unsafe endpoint URLs are rejected.
- Every curl invocation ignores user `.curlrc` files.
- Temporary metrics are removed on normal exit and cancellation.

## JSON and exit codes
See [SECURITY.md](SECURITY.md) for private vulnerability reporting.

JSON output includes `schema_version`, per-service results, per-endpoint
measurements, privacy guarantees, warnings, bandwidth, and optional macOS
network quality. Additive fields may appear without changing the schema version;
breaking field changes increment it.
## Documentation

- `0`: at least one selected primary service path was reachable.
- `1`: every selected primary service path was blocked/unavailable.
- `2`: invalid invocation or missing dependency.
- [Scoring and result rules](docs/scoring.md)
- [Routes, proxies, and bandwidth](docs/network.md)
- [Reports, automation, and exit codes](docs/reporting.md)
- [Release history](CHANGELOG.md)

## Requirements

- macOS or Linux
- Bash 3.2+
- curl
- awk, sed, sort
- curl, awk, sed, sort
- Optional on macOS: `networkQuality`

## Contributing

Issues and pull requests are welcome. Start with [CONTRIBUTING.md](CONTRIBUTING.md)
and the [Code of Conduct](CODE_OF_CONDUCT.md). See [CHANGELOG.md](CHANGELOG.md)
for release history.
Issues and pull requests are welcome. Start with
[CONTRIBUTING.md](CONTRIBUTING.md) and the
[Code of Conduct](CODE_OF_CONDUCT.md).

## License

Expand Down
Loading