Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
2c6fcc5
accept full URL in NewAuthorizedClient, default scheme to https
l-hellmann May 13, 2026
b66c389
add CLAUDE.md
l-hellmann May 13, 2026
8478239
add RunRootCmd entry with injectable stdout/stderr and exit code return
l-hellmann May 13, 2026
33e52b1
add integration harness with version and login tests
l-hellmann May 13, 2026
3fd1a6a
allow zcli.yml path override and route config-file notices through in…
l-hellmann May 13, 2026
1c77055
isolate integration tests from user zcli.yml
l-hellmann May 13, 2026
aac7b2f
ignore empty ZEROPS_TOKEN env override
l-hellmann May 13, 2026
7168824
add project list integration test
l-hellmann May 13, 2026
e03b769
expose yamlReader.ResetCache for in-process test isolation
l-hellmann May 13, 2026
d04ccdc
reset yamlReader cache per integration test
l-hellmann May 13, 2026
5eceaea
add service push happy-path integration test
l-hellmann May 13, 2026
49a2242
extend service push tests with setup flag and version-name cases
l-hellmann May 13, 2026
2b6250c
document --setup precedence bug via skipped regression test
l-hellmann May 13, 2026
bc63092
add tier 1 push/deploy tests: error paths, process failure, deploy va…
l-hellmann May 13, 2026
eed4c37
document confirmed nil-deref bug in push log-streaming callback
l-hellmann May 13, 2026
5c032aa
split push/deploy integration tests across files and add tier 2 cases
l-hellmann May 13, 2026
70faee9
switch integration tests to testify assert/require
l-hellmann May 13, 2026
902d614
add tier 3 git archive tests: not-init/no-commits errors, workspace-c…
l-hellmann May 13, 2026
c4b1c79
add workspace-state staged/all, project-flag, and saved-scope tests
l-hellmann May 13, 2026
a4c18d6
document all integration tests in a package-doc test file
l-hellmann May 13, 2026
d5356d2
test interactive selector model via teatest
l-hellmann May 13, 2026
01ce12f
test prompt, input, and selector filter via teatest
l-hellmann May 13, 2026
64e2ea9
test multi-select selector: spacebar toggles, ctrl+a/d, GetOneSelecte…
l-hellmann May 13, 2026
4df5878
test table render, body/row indexing, and cell pretty-flag
l-hellmann May 13, 2026
3b46af0
fix CI lint: gofmt constants, nolint containedctx on RunOptions, t.Co…
l-hellmann May 13, 2026
ea5ddf1
inline integration test docs into each test, drop doc_test.go
l-hellmann May 18, 2026
6ad3eee
expand half-line multiline call formatting in integration tests
l-hellmann May 18, 2026
ea00ca3
use realistic 22-char base64 UUID IDs in push/deploy test fixtures
l-hellmann May 18, 2026
a9a77d9
refactor RunRootCmd to take context arg and use functional options
l-hellmann May 18, 2026
fa17e47
fix lint exposed by RunRootCmd ctx refactor
l-hellmann May 18, 2026
9ab7e39
add section about comments the CLAUDE.md
tikinang May 18, 2026
c31c14c
fix: honor --setup flag over auto-match by service name
l-hellmann May 13, 2026
e17e0ad
fix: nil-guard apiProcess.AppVersion in push log-streaming callback
l-hellmann May 13, 2026
da1f3ed
reject unknown --setup client-side before any API call
l-hellmann May 13, 2026
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
114 changes: 114 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Overview

`zcli` is the Zerops CLI written in Go (module `github.com/zeropsio/zcli`, Go 1.24). The entrypoint is `cmd/zcli/main.go`, which delegates to `src/cmd.ExecuteCmd()`. All implementation lives under `src/`.

## Common commands

- `make test` — runs `go test -v ./cmd/... ./src/...`. Run a single test with `go test -v -run TestName ./src/<pkg>/...`.
- `make lint` — runs `golangci-lint` for darwin/arm64, linux/amd64, and windows/amd64 in turn via the `gomodrun` wrapper. Config: `.golangci.yaml`.
- `make all` — cross-builds binaries for windows-amd, linux-amd, darwin-amd, darwin-arm. Single-target builds: `make linux-amd` etc. Builds go through `tools/build.sh`, which sets the version via `-ldflags` from `git rev-parse`/`git describe`, uses build tag `devel`, and writes to `bin/`.
- `make showcase` — runs `src/uxBlock/showcase/main.go` to preview UI elements.
- `gomodrun` (`tools/gomodrun.go`) executes binaries from `./bin` relative to the nearest `go.mod`; the lint target relies on it to find a pinned `golangci-lint`.

## Architecture

### Command layer (`src/cmd`, `src/cmdBuilder`)

Commands are not declared directly against Cobra. Instead, `src/cmdBuilder` wraps Cobra with a fluent builder (`cmdBuilder.NewCmd().Use(...).Arg(...).StringFlag(...).LoggedUserRunFunc(...)`) and `buildCobraCmd.go` translates it into a `*cobra.Command`. The root command lives in `src/cmd/root.go` and registers all subcommands via `AddChildrenCmd`.

Two run-function flavors are central to how commands behave:

- `GuestRunFunc(func(ctx, *GuestCmdData) error)` — runs when there is no auth token. Has access to `CliStorage`, `UxBlocks`, parsed `Args`/`Params`, `Stdout`/`Stderr` printers.
- `LoggedUserRunFunc(func(ctx, *LoggedUserCmdData) error)` — runs when a token is present (from `cliStorage` or the `CliTokenEnvVar` env var). Embeds `*GuestCmdData` and adds `RestApiClient` (a `zeropsRestApiClient.Handler` pointed at the configured region/host), plus optional resolved `Project`/`Service` entities and a `ProjectSelector`.

If only `GuestRunFunc` is defined, it runs for logged-in users too. If only `LoggedUserRunFunc` is defined and no token is set, the command exits with `UnauthenticatedUser`. Implementation: `src/cmdBuilder/createRunFunc.go`.

### Scope levels (`src/cmdBuilder/scopeProject.go`, `scopeService.go`)

Commands that operate on a project or service set `.ScopeLevel(cmdBuilder.ScopeProject(...))` or `.ScopeLevel(cmdBuilder.ScopeService(...))`. The scope level adds the relevant flags/args and, before the run function executes, resolves the target by ID/name into `LoggedUserCmdData.Project` / `.Service` — possibly creating a new project/service interactively when `WithCreateNewProject()` / `WithCreateNewService()` are passed (see `serviceDeploy.go` for an example). Persisted "scope" (saved project) is read from `CliStorage.Data().ScopeProjectId`.

### Flag normalization

`ExecuteRootCmd` sets a Cobra normalization function that converts camelCase flag names to kebab-case (`src/cmdBuilder/executeRootCmd.go`). Flags can be defined as camelCase in code and used as kebab-case on the CLI.

### Persistent state and config

- `cliStorage` (`src/cliStorage`) wraps `storage.New[Data]` (`src/storage`) — a JSON-backed file used to persist the login token, region selection, saved project scope, and VPN key registry. Path comes from `constants.CliDataFilePath()`.
- `constants` exposes platform-specific paths, env var names (e.g. `CliTokenEnvVar`), and the default region (used when no region is configured).
- Log file path comes from `constants.LogFilePath()`; loggers (`src/logger`) split human output from a debug file logger that captures `LogDebug`/error traces.

### UX layer (`src/uxBlock`, `src/uxHelpers`, `src/printer`, `src/terminal`)

All terminal output and interactive prompts go through `uxBlock.Blocks` (constructed in `executeRootCmd.go`). It owns the loggers, terminal size, an `isTerminal` flag, and a cancel function wired to SIGINT/SIGTERM. `uxBlock/models` provides Bubble Tea TUI models (selectors, spinners, tables); `uxHelpers` wraps common flows like `ProjectSelector`. `printer` is the lower-level line printer used directly by commands (`cmdData.Stdout.PrintLines(...)`). `styles` centralizes lipgloss styles, including the custom Cobra help template defined in `src/cmd/root.go`.

### API client and entities

- `src/zeropsRestApiClient` constructs an authorized client around `github.com/zeropsio/zerops-go`. The host comes from the user's saved `RegionData.Address` or `constants.DefaultRegion`, prefixed with `https://`.
- `src/entity` defines domain types (`Project`, `Service`, `AppVersion`, `Container`, `Process`, `Location`, `Org`, `VpnKey`). `src/entity/repository` contains query helpers (`GetProjectById`, etc.) layered on the REST client.
- Errors from the API are unwrapped in `executeRootCmd.printError`: user-facing `errorsx.UserError`, structured `apiError.Error` (printed with YAML-formatted metadata), and Ctrl-C cancellations are each handled distinctly.

### Other notable packages

- `src/archiveClient` — packs source for `service deploy`/`service push`, honoring `.gitignore` and a `deploy-git-folder` flag.
- `src/yamlReader` — reads `zerops.yaml` (or a path passed via `--zerops-yaml-path`).
- `src/wg` + `src/nettools` — WireGuard interface management for `zcli vpn` (`InterfaceExists`, key handling, etc.); requires the `wireguard` and `ping` binaries on the host.
- `src/serviceLogs` — streaming/log retrieval used by `zcli service log`.
- `src/i18n` — message catalog (`en.go`); all user-visible strings use `i18n.T(i18n.<Key>, args...)`. Add new strings to `en.go` rather than inlining literals.
- `src/flagParams` — typed param reader (`Params.GetBool/GetString/...`) bound from Cobra flags inside the run func.
- `src/optional``Null[T]` type used by `LoggedUserCmdData.Project`/`Service`.
- `src/gn` — small generic helpers (`TransformSlice`, etc.).

## Adding a new command

1. Create `src/cmd/<name>.go` exporting a `*cmdBuilder.Cmd` constructor.
2. Wire flags/args, choose `ScopeLevel` if it targets a project/service, and provide `LoggedUserRunFunc` (and/or `GuestRunFunc`).
3. Register it in `rootCmd()` in `src/cmd/root.go` (or as a child of an existing parent like `serviceCmd`, `projectCmd`, `vpnCmd`).
4. Add any new user-facing strings to `src/i18n/en.go` and reference them via `i18n.T(...)`.

## Code style

### Multiline function calls

When breaking a function call across lines, do not use the "half line" form (some arguments on the opening line, the rest continued below). Either keep everything on one line, or put `func(` alone on the opening line, every argument on its own line with a trailing comma, and `)` on its own closing line. Printf-style format strings may keep their format args on the same line as the format string — treat that group as a single argument block.

```go
// good — single line
require.Equal(t, 0, res.ExitCode)

// good — fully expanded, each arg on its own line, trailing commas
require.NotEqualf(
t,
0,
res.ExitCode,
"expected non-zero exit\n--- stderr ---\n%s\n--- stdout ---\n%s", res.Stderr, res.Stdout,
)

// bad — half-line: first args ride on the opening line, rest spill below
require.NotEqualf(t, 0, res.ExitCode,
"expected non-zero exit: %s", res.Stderr)
```

## Distribution

Released via GitHub Actions (`.github/workflows/`) and republished to npm as `@zerops/zcli` (`tools/npm`). Install scripts: `install.sh` (Linux/macOS), `install.ps1` (Windows). Nix flake (`flake.nix`, `default.nix`) supports `nix develop`/`nix build`.

## Comments

Default: no comment. Add one only when the *why* is non-obvious (constraint, workaround, surprising invariant) or the *what* is genuinely hard to parse from the code (nested data shape, non-trivial algorithm). Lead *why* comments with the motivation, not a "what" preamble.

Write comments as natural prose, wrapping at thought boundaries, never at column boundaries. Do NOT break lines at 80 or 100 columns mid-sentence. A comment line should read like a sentence you'd speak aloud: it ends where the thought ends, not where a column counter fires.

Short related clauses that flow (a consequence, an addendum, a clarification) stay on the same line, even past a period, as long as they're part of the same thought. A new line means a new thought. Don't split one thought across lines AND don't pack unrelated thoughts onto one line. When enumerating parallel items in prose, join them with commas, not periods.

Target line length is 160-175 chars. Lines may extend to 180 chars when cutting shorter would break mid-clause, but 180 is a hard ceiling, not a target. If a thought doesn't fit in 180 chars, split at a natural clause boundary and continue on a new `//` line.

Don't use em-dashes (``) anywhere in comments, use a normal dash (`-`). Don't use semicolons (`;`) as thought separators. End the first thought with a period and start a new sentence. Semicolons for tight lists inside a single thought are fine.

```go
// Value caches the first successful fetch result. Errors are not cached, so the next Get retries.
// Fetch is passed at Get time (not at construction), so callers can close over per-call context without storing it on the struct.
```
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
define helpMessage
possible targets:
- test
- test-integration
- lint
- all
- windows-amd
Expand All @@ -19,6 +20,9 @@ help:
test:
go test -v ./cmd/... ./src/...

test-integration:
go test -v -tags devel ./src/cmd/...

lint:
GOOS=darwin GOARCH=arm64 gomodrun golangci-lint run ./cmd/... ./src/... --verbose
GOOS=linux GOARCH=amd64 gomodrun golangci-lint run ./cmd/... ./src/... --verbose
Expand Down
17 changes: 10 additions & 7 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
module github.com/zeropsio/zcli

go 1.24
go 1.24.0

require github.com/zeropsio/zerops-go v1.0.18

require (
github.com/charmbracelet/bubbles v0.20.0
github.com/charmbracelet/bubbletea v1.3.4
github.com/charmbracelet/bubbletea v1.3.5
github.com/charmbracelet/lipgloss v1.1.0
github.com/golang/mock v1.6.0
github.com/google/uuid v1.6.0
Expand All @@ -21,17 +21,20 @@ require (
github.com/stretchr/testify v1.10.0
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8
golang.org/x/term v0.28.0
golang.org/x/text v0.21.0
golang.org/x/text v0.28.0
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
gopkg.in/yaml.v3 v3.0.1
)

require (
github.com/atotto/clipboard v0.1.4 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect
github.com/charmbracelet/x/ansi v0.8.0 // indirect
github.com/aymanbagabas/go-udiff v0.3.1 // indirect
github.com/charmbracelet/colorprofile v0.3.2 // indirect
github.com/charmbracelet/x/ansi v0.10.1 // indirect
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect
github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b // indirect
github.com/charmbracelet/x/exp/teatest v0.0.0-20260511125431-fe5d686e0c99 // indirect
github.com/charmbracelet/x/term v0.2.1 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
Expand All @@ -56,7 +59,7 @@ require (
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/crypto v0.32.0 // indirect
golang.org/x/sync v0.11.0 // indirect
golang.org/x/sys v0.30.0 // indirect
golang.org/x/sync v0.16.0 // indirect
golang.org/x/sys v0.35.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
)
16 changes: 16 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,30 @@ github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiE
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8=
github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA=
github.com/aymanbagabas/go-udiff v0.3.1 h1:LV+qyBQ2pqe0u42ZsUEtPiCaUoqgA9gYRDs3vj1nolY=
github.com/aymanbagabas/go-udiff v0.3.1/go.mod h1:G0fsKmG+P6ylD0r6N/KgQD/nWzgfnl8ZBcNLgcbrw8E=
github.com/charmbracelet/bubbles v0.20.0 h1:jSZu6qD8cRQ6k9OMfR1WlM+ruM8fkPWkHvQWD9LIutE=
github.com/charmbracelet/bubbles v0.20.0/go.mod h1:39slydyswPy+uVOHZ5x/GjwVAFkCsV8IIVy+4MhzwwU=
github.com/charmbracelet/bubbletea v1.3.4 h1:kCg7B+jSCFPLYRA52SDZjr51kG/fMUEoPoZrkaDHyoI=
github.com/charmbracelet/bubbletea v1.3.4/go.mod h1:dtcUCyCGEX3g9tosuYiut3MXgY/Jsv9nKVdibKKRRXo=
github.com/charmbracelet/bubbletea v1.3.5 h1:JAMNLTbqMOhSwoELIr0qyP4VidFq72/6E9j7HHmRKQc=
github.com/charmbracelet/bubbletea v1.3.5/go.mod h1:TkCnmH+aBd4LrXhXcqrKiYwRs7qyQx5rBgH5fVY3v54=
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs=
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk=
github.com/charmbracelet/colorprofile v0.3.2 h1:9J27WdztfJQVAQKX2WOlSSRB+5gaKqqITmrvb1uTIiI=
github.com/charmbracelet/colorprofile v0.3.2/go.mod h1:mTD5XzNeWHj8oqHb+S1bssQb7vIHbepiebQ2kPKVKbI=
github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY=
github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30=
github.com/charmbracelet/x/ansi v0.8.0 h1:9GTq3xq9caJW8ZrBTe0LIe2fvfLR/bYXKTx2llXn7xE=
github.com/charmbracelet/x/ansi v0.8.0/go.mod h1:wdYl/ONOLHLIVmQaxbIYEC/cRKOQyjTkowiI4blgS9Q=
github.com/charmbracelet/x/ansi v0.10.1 h1:rL3Koar5XvX0pHGfovN03f5cxLbCF2YvLeyz7D2jVDQ=
github.com/charmbracelet/x/ansi v0.10.1/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE=
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0GVL4jeHEwG5YOXDmi86oYw2yuYUGqz6a8sLwg0X8=
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs=
github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b h1:MnAMdlwSltxJyULnrYbkZpp4k58Co7Tah3ciKhSNo0Q=
github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U=
github.com/charmbracelet/x/exp/teatest v0.0.0-20260511125431-fe5d686e0c99 h1:E+VCvJLc5yu3YSYj9fKT3x0K1g7xLJtvYyU/hMYF63w=
github.com/charmbracelet/x/exp/teatest v0.0.0-20260511125431-fe5d686e0c99/go.mod h1:aPVjFrBwbJgj5Qz1F0IXsnbcOVJcMKgu1ySUfTAxh7k=
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
Expand Down Expand Up @@ -125,6 +135,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand All @@ -135,13 +147,17 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
Expand Down
Loading
Loading