-
Notifications
You must be signed in to change notification settings - Fork 2
Client API
A guided tour of the public github.com/reeflective/team/client package. Full signatures and
per-method docs: https://pkg.go.dev/github.com/reeflective/team/client. This page tells you
when to reach for each call.
The teamclient core is deliberately minimal: it drives connect/disconnect through a
Dialer, and answers exactly two questions about a (possibly
remote) server — its users and its version. It contains no server-side code.
- Constructor & lifecycle
- Queries
- The Dialer interface
- Configs & TLS
- Logging
- Directories & filesystem
- Options
- Errors
- Command tree & runners
teamclient, err := client.New("myapp", client.WithDialer(dialer))New(app string, opts ...Options) (*Client, error) builds the core (filesystem + loggers
only). It is not connected to any server yet — connection is deferred until a command or
your code needs it.
| Method | What it does |
|---|---|
Connect(opts ...Options) error |
Connect via the dialer. Guarded by a sync.Once (one connect per run). Resolves a config (may load/select from disk and prompt), then dialer.Init + dialer.Dial. No dialer ⇒ no-op, no error.
|
Disconnect() error |
Close the connection (dialer.Close). No-op under WithNoDisconnect(). Resets the connect-once so the client can reconnect. |
Name() string |
The application name. |
The generated commands call Connect()/Disconnect() for you; you only call them directly
when driving the client from your own code. See
Getting Started → a client-only binary.
Three questions, resolved through the team.Client backend (the dialer, or a
WithTeamClient object):
| Method | Notes |
|---|---|
Users() ([]team.User, error) |
Users of the connected server. ErrNoTeamclient if no backend is set. |
VersionServer() (team.Version, error) |
The remote server's version — traverses the transport. ErrNoTeamclient if no backend. |
VersionClient() (team.Version, error) |
The local build info of this client binary. Computed locally from the binary's own version — it never touches the transport and needs no connection. |
The VersionServer vs VersionClient split is the usual source of confusion: version
commands print both so operators can spot a client/server mismatch, but only VersionServer
requires a live connection.
type Dialer interface {
Init(c *Client) error // transport-agnostic prep (read config, build credentials)
Dial() error // transport-specific connect
Close() error // tear down
}Register a dialer with WithDialer. If it also implements team.Client
(Users/VersionServer) — the common case for RPC transports — the core adopts it as the
query backend automatically, so WithDialer(...) alone is enough; no separate
WithTeamClient. Full walkthrough and the gRPC reference dialer:
Writing a Transport.
A Config is the JSON connection file an operator imports (user, host, port, token, CA cert,
client cert + key). The struct is documented in
Users & Authentication → The connection config file.
cfg := teamclient.Config() // current config (empty, not nil, if none loaded yet)
cfgs := teamclient.GetConfigs() // map of configs found on disk (keyed "user@host (digest)")
cfg, err := teamclient.ReadConfig(path)
err = teamclient.SaveConfig(cfg) // ErrConfigNoUser if cfg.User == ""| Method | Notes |
|---|---|
Config() *Config |
The current remote-server config; empty (not nil) if none loaded. |
GetConfigs() map[string]*Config |
Configs in ~/.<app>/teamclient/configs/. Always uses the on-disk FS, even in memory mode. |
ReadConfig(path string) (*Config, error) |
Parse a config file. |
SaveConfig(*Config) error |
Persist a config (rejects an empty User). |
SelectConfig() *Config |
Return the sole config, or prompt to pick one (may block). |
NewTLSConfigFrom(caCert, cert, key string) (*tls.Config, error) |
Build the client-side mutual-TLS config from a config's three credential fields. Used inside a dialer's Init. |
To skip disk lookup and the prompt entirely (automation, tests), construct with
WithConfig(cfg).
Thin façade over the log package; styling and formats in Logging.
| Method | Notes |
|---|---|
NamedLogger(pkg, stream string) *slog.Logger |
Tagged logger; never nil. |
SetLogWriter(stdout, stderr io.Writer) |
Redirect the console streams — how the CLI runners point logging at a cobra command's own stdout/stderr. |
SetLogLevel(level int) |
Adjust console + file levels (no-op for a WithLogger handler). |
SetLogFormat(format log.Format) |
Console stream format: console / text / json. |
| Method | Notes |
|---|---|
HomeDir() / TeamDir() / LogsDir() / ConfigsDir()
|
App directories, created on demand. |
Filesystem() *assets.FS |
On-disk, or in-memory under WithInMemory(). |
Note: config read/write always uses the on-disk filesystem even when the client is in memory mode, so imported server configs survive an in-memory client.
Pass at New(...) (and, for the repeatable ones, at Connect(...)). Full reference table in
Configuration → Client options.
| Option | Purpose |
|---|---|
WithDialer(Dialer) |
The connection backend. If it also implements team.Client, it becomes the query backend too. |
WithTeamClient(team.Client) |
Set the query backend explicitly, when it is a distinct object from the dialer (e.g. server.Self() uses this so a server is a client of itself). |
WithConfig(*Config) |
Use a given config; no disk lookup, no prompt. |
WithInMemory() |
Route the filesystem to memory (also disables file logs). |
WithHomeDirectory(path) / WithTeamDirectory(name)
|
Relocate ~/.<app>/ and the teamclient subdir. |
WithNoLogs(bool) / WithLogFile(path)
|
Silence / relocate file logging. |
WithLogger(slog.Handler) |
Replace the console+file backend (disables runtime level/output knobs). |
WithConsoleOptions(func(*log.ConsoleOptions)) |
Restyle the built-in console, keep the loggers. |
WithLogFormat(log.Format) |
Console stream format: console / text / json. |
WithNoDisconnect() |
For closed-loop / readline apps: don't disconnect after each command. Use with PreRunNoDisconnect. |
Sentinel errors you can match with errors.Is:
ErrNoTeamclient, ErrConfig, ErrNoConfig, ErrConfigNoUser, ErrClient.
root := client_commands.Generate(teamclient) // *cobra.Command: import, users, versionclient/commands.Generate(cli *Client) *cobra.Command returns the teamclient tree. The
package also exports the reusable cobra runners the tree is built from — use them as models
for wiring the teamclient into your own commands:
-
PreRun(cli, opts...)— connect before the command. -
PreRunNoDisconnect(cli, opts...)— connect without arming a post-run disconnect (forWithNoDisconnectapps). -
PostRun(cli)— disconnect after the command.
See Common Workflows → embedded console app and CLI Reference.
Related: Server API → · Writing a Transport → · Users & Authentication → · Configuration →