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
25 changes: 25 additions & 0 deletions rust/crates/sift_cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,31 @@ This project adheres to [Semantic Versioning](http://semver.org/).

### What's New

- `config update` without field flags no longer prints `Nothing to update.`
and exits 0. In a terminal, it now opens an interactive editor. Outside a
terminal, it exits with status 2. Scripts that call it with no flags now
fail.
- `config update` stops with a pointer to `config create` when the config file
is missing. When `--profile` names a profile that does not exist, the
interactive editor stops the same way. Field flags still create a new named
profile.
- `config create` now prompts for the profile values in a terminal. It also
creates new profiles: `sift-cli --profile staging config create`, or, without
`--profile`, it asks for a name when the default profile is already set up.
Outside a terminal, it still creates only an empty file.
- The interactive editor lists named profiles to pick from and shows the
current value of each field. Type a new value to change a field, or leave it
blank to keep the current value. The API key is not
shown while you type it. Before it saves, the editor lists only the changed
fields, with the key masked to its last four characters. It writes nothing
when no field changed. The confirmation now defaults to yes.
- `--profile default` now selects the top-level profile in every command. Before,
it looked for a `[default]` table, so `sift-cli --profile default ping`
failed on a file with only top-level keys. A file that has a `[default]`
table still uses that table.
- `config update` with field flags prints the fields that changed. It reports
`No changes` and does not write the file when the values are already set.

## [v0.7.6] - October 26, 2026

### What's New
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Each CLI profile needs four values:
| `grpc_uri` | Base gRPC endpoint for Sift | `https://grpc-api.siftstack.com` |
| `rest_uri` | Base REST endpoint for Sift | `https://api.siftstack.com` |
| `app_uri` | Required web app origin from your browser | `https://app.siftstack.com` |
| `apikey` | Your Sift API key | `sift_...` |
| `api_key` | Your Sift API key | `sift_...` |

For Sift Cloud, use the gRPC and REST values in the table. For other
environments, use the endpoints from your administrator. See
Expand Down Expand Up @@ -43,24 +43,73 @@ sift-cli config where

## Bootstrapping your credentials

The fastest way to get set up is the interactive flow. First create the file,
then fill it in:
Run `config create` in a terminal. It creates the config file and prompts for
the values of the `default` profile:

```sh
sift-cli config create
sift-cli config update --interactive
```

The interactive prompt asks for the profile, API URLs, API key, and app origin.
The prompt shows the result before it writes the file. A blank profile selects
the `default` profile.
```text
Creating a config file at '~/Library/Application Support/sift.toml'.

Editing profile 'default'. Enter a value for each field.

gRPC URL: https://grpc-api.siftstack.com
REST URL: https://api.siftstack.com
API key:

App URL
suggested: https://app.siftstack.com (leave blank to use it)
new:

Changes to 'default':
grpc_uri (unset) -> https://grpc-api.siftstack.com
rest_uri (unset) -> https://api.siftstack.com
api_key (unset) -> ****a91f
app_uri (unset) -> https://app.siftstack.com
Apply? [Y/n]:
Saved profile 'default'.
Run 'sift-cli ping' to check the connection.
```

The terminal does not show the API key while you type it. The change list shows
only its last four characters. The command writes nothing until you confirm.

### Editing a profile

Run `config update` without field flags to edit a profile interactively:

```sh
sift-cli config update
```

If the file has named profiles, the command first asks which profile to edit.
Use `--profile <name>` to skip that question. Each field shows its current
value:

```text
Editing profile 'staging'.
To change a field, type a new value and press Enter. To keep the current value, leave it blank and press Enter.

gRPC URL
current: https://grpc-api.staging.example.net
new:
```

The command lists only the fields you changed. If nothing changed, it writes
nothing.

`config update` edits existing profiles only. If the config file or the named
profile does not exist, the command stops and tells you to run `config create`.

### Non-interactive setup

To configure everything in one command (useful for scripts and CI), pass the
values as flags:
Outside a terminal, `config create` only creates an empty config file. To set
the values in one command (for scripts and CI), pass them as flags:

```sh
sift-cli config create
sift-cli config update \
--grpc-uri https://grpc-api.siftstack.com \
--rest-uri https://api.siftstack.com \
Expand All @@ -69,12 +118,16 @@ sift-cli config update \
```

Short forms are `-g` for gRPC, `-r` for REST, and `-k` for the API key.
Omitted fields stay unchanged. You can update one value at a time:
Omitted fields stay unchanged. The command prints the fields that changed. You
can update one value at a time:

```sh
sift-cli config update --api-key "$SIFT_API_KEY"
```

Without field flags outside a terminal, `config update` exits with status 2,
because it cannot prompt.

## Inspecting the config

```sh
Expand All @@ -88,7 +141,7 @@ A configured `default` profile looks like this:
grpc_uri = "https://grpc-api.siftstack.com"
rest_uri = "https://api.siftstack.com"
app_uri = "https://app.siftstack.com"
apikey = "sift_..."
api_key = "sift_..."
```

## Disabling TLS
Expand Down
51 changes: 38 additions & 13 deletions rust/crates/sift_cli/assets/docs/src/getting-started/profiles.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,35 @@ re-editing your config.
## The default profile

When you do not name a profile, settings are read from and written to the top
level of the config file. This is the `default` profile:
level of the config file. This is the `default` profile. `--profile default`
also selects it:

```toml
grpc_uri = "https://grpc-api.siftstack.com"
rest_uri = "https://api.siftstack.com"
app_uri = "https://app.siftstack.com"
apikey = "sift_prod_..."
api_key = "sift_prod_..."
```

## Adding a named profile

Pass `--profile <name>` to `config update`. The profile is created as its own
TOML table:
In a terminal, pass the new name to `config create`. It prompts for each value
of the new profile:

```sh
sift-cli config update --profile mission \
--grpc-uri https://api.staging.example.com \
sift-cli --profile staging config create
```

Without `--profile`, `config create` asks for a name when the `default` profile
is already set up. If the profile already exists, the command tells you to use
`config update` instead.

For scripts, pass `--profile <name>` and field flags to `config update`. A name
that does not exist yet is created:

```sh
sift-cli --profile staging config update \
--grpc-uri https://grpc-api.staging.example.com \
--rest-uri https://api.staging.example.com \
--app-uri https://sift.staging.example.com \
--api-key "$SIFT_STAGING_API_KEY"
Expand All @@ -35,29 +47,42 @@ The resulting file:
grpc_uri = "https://grpc-api.siftstack.com"
rest_uri = "https://api.siftstack.com"
app_uri = "https://app.siftstack.com"
apikey = "sift_prod_..."
api_key = "sift_prod_..."

[staging]
grpc_uri = "https://grpc-api.staging.example.com"
rest_uri = "https://api.staging.example.com"
app_uri = "https://sift.staging.example.com"
apikey = "sift_staging_..."
api_key = "sift_staging_..."
```

Each profile is stored as its own TOML table.

## Editing a named profile

Run `config update` without field flags. The command lists the profiles and
asks which one to edit:

```text
Select a profile to edit:
1) default
2) staging
Profile [1]: 2
```

The interactive flow also supports profiles. When prompted for a profile name,
enter `staging` instead of leaving it blank:
Enter a number or a profile name. To skip the list, name the profile:

```sh
sift-cli config update --interactive
sift-cli --profile staging config update
```

## Using a profile

`--profile` is a global flag, so it goes on any command that talks to Sift:

```sh
sift-cli --profile mission ping
sift-cli --profile mission import csv ./telemetry.csv --asset rover-1
sift-cli --profile staging ping
sift-cli --profile staging import csv ./telemetry.csv --asset rover-1
```

Omit `--profile` to use the default profile.
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ sift-cli --disable-tls ping

| Symptom | Likely cause and fix |
| ----------------------------------------- | ------------------------------------------------------------------------------------ |
| `expected to find 'sift.toml'` | No config file yet. Run `sift-cli config create`, then `config update`. |
| `expected to find 'sift.toml'` | No config file yet. Run `sift-cli config create`. |
| `Expected value of 'apikey' to be present`| The profile is missing a field. Re-run `sift-cli config update` with the missing value. |
| `Profile '<name>' not found` | The named profile does not exist. Check `sift-cli config show`. |
| Authentication or permission errors | The API key is wrong or lacks access. Generate a new key in the Sift web app. |
Expand Down
4 changes: 2 additions & 2 deletions rust/crates/sift_cli/assets/docs/src/reference/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ Manage CLI configuration. See [Configuration](../getting-started/configuration.m

| Command | Description |
| ----------------------- | ------------------------------------------------- |
| `config create` | Create a new (empty) config file. |
| `config create` | Create the config file or a new profile, then prompt for its values. |
| `config show` | Print the current config file. |
| `config where` | Print the path to the config file. |
| `config update` | Set connection, app, or key fields. Use `--interactive` for prompts. |
| `config update` | Edit an existing profile. Prompts when run without field flags. |

## `import`

Expand Down
15 changes: 12 additions & 3 deletions rust/crates/sift_cli/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -370,16 +370,25 @@ pub enum ConfigCmd {
/// Show the path to the current config file
Where,

/// Create a new config file (fails if one already exists)
/// Create the config file or a new profile, then prompt for its values.
///
/// Without --profile, sets up the default profile, or asks for a new
/// profile name when the default is already set up. Outside a terminal,
/// only creates an empty config file.
Create,

/// Update fields in the existing config file
/// Update fields of an existing profile.
///
/// With field flags, sets those fields without prompting. A new --profile
/// name is created. Without field flags in a terminal, prompts for each
/// value and shows the current one. Without field flags outside a
/// terminal, exits with status 2.
Update(ConfigUpdateArgs),
}

#[derive(clap::Args)]
pub struct ConfigUpdateArgs {
/// Edit or create a profile interactively (ignores other flags)
/// Prompt for each value even when field flags are given (ignores them)
#[arg(short, long)]
pub interactive: bool,

Expand Down
Loading
Loading