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
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ Install the skills for your agent:
npx skills add stefanosala/vc-cli
```

Agent-facing command guidance lives in `skills/vc-cli/SKILL.md` (the repo `@skills` entry for this CLI).

## Quick Start

1. Log in with Volvo OAuth:
Expand All @@ -33,6 +35,14 @@ npx skills add stefanosala/vc-cli
vc-cli auth login
```

For headless hosts (agents/servers), use:

```bash
vc-cli auth login --headless
```

This prints an authorization URL. Open it in any browser, complete login, then paste the redirected callback URL back into the CLI.

If developer credentials are missing, the command shows the Volvo developer account URL and redirect URI to use, then waits for you to return and enter the API key, client ID, and client secret.

2. Discover your vehicles:
Expand Down Expand Up @@ -68,12 +78,23 @@ vc-cli auth whoami
vc-cli location get
```

## Agent Skills

If you are using an AI agent (for example via Cursor skills), install:

```bash
npx skills add stefanosala/vc-cli
```

Then reference `skills/vc-cli/SKILL.md` for command map, auth workflows, and safety notes (including headless login guidance).

## Notes

- Command output is JSON by default.
- Configuration is loaded from `~/.config/vc-cli/config` in env variable format before CLI parsing.
- Profile/session/VIN state is stored locally per profile in SQLite.
- `auth login` starts a temporary local HTTP listener for the OAuth redirect.
- `auth login --headless` skips browser/listener setup, prints the authorize URL, and prompts for the redirected callback URL.
- `auth login` prompts for missing `VCC_API_KEY`, `VOLVO_CLIENT_ID`, and `VOLVO_CLIENT_SECRET`, then saves them to `~/.config/vc-cli/config`.
- `auth login` requests all Connected Vehicle, Energy, and Location scopes by default. Use `--scopes` or `VOLVO_SCOPES` to override the requested scope set.

Expand Down
13 changes: 11 additions & 2 deletions skills/vc-cli/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ cargo run -- <command> [flags]

## Command Map

- `auth login` - Start browser-based OAuth login and persist session tokens.
- `auth login` - Start OAuth login (browser listener by default, or headless pasteback with `--headless`) and persist session tokens.
- `auth token-set` - Persist tokens directly (script/manual token flow).
- `auth whoami` - Print current session identity info.
- `auth logout` - Clear local auth session.
Expand Down Expand Up @@ -110,7 +110,7 @@ vc-cli vehicle vin default --vin <VIN> --api-key "$VCC_API_KEY"
### `auth login`

```bash
vc-cli auth login [--scopes <space-separated-scopes>] [--auth-issuer <url>] [--client-id <id>] [--client-secret <secret>] [--redirect-uri <uri>] [--auth-listen-timeout-seconds <seconds>]
vc-cli auth login [--headless] [--scopes <space-separated-scopes>] [--auth-issuer <url>] [--client-id <id>] [--client-secret <secret>] [--redirect-uri <uri>] [--auth-listen-timeout-seconds <seconds>]
```

| Flag | Required | Description |
Expand All @@ -121,13 +121,22 @@ vc-cli auth login [--scopes <space-separated-scopes>] [--auth-issuer <url>] [--c
| `--client-secret` | prompted if missing | Volvo OAuth client secret (`VOLVO_CLIENT_SECRET`) |
| `--redirect-uri` | no | Registered local redirect URI (`VOLVO_REDIRECT_URI` default is `http://127.0.0.1:1410/callback`) |
| `--auth-listen-timeout-seconds` | no | Local callback listener timeout |
| `--headless` | no | Skip browser open + local callback listener; print auth URL and prompt for pasted callback URL |

`auth login` also prompts for missing `VCC_API_KEY`. If any of `VCC_API_KEY`, `VOLVO_CLIENT_ID`, or `VOLVO_CLIENT_SECRET` is missing, it first tells the user to create and publish a Volvo app at `https://developer.volvocars.com/account/`, shows the redirect URI to configure, and asks them to return to the terminal after publishing. Newly provided values are saved to `~/.config/vc-cli/config`.

Headless flow details:

1. Run `vc-cli auth login --headless` on the agent/server.
2. Open the printed authorization URL in any browser and complete login/consent.
3. Browser redirects to the configured localhost callback (for example `http://127.0.0.1:1410/callback?...`) and likely shows a connection error because no listener is running.
4. Copy the full redirected URL from the browser address bar and paste it into the CLI prompt.

Example:

```bash
vc-cli auth login
vc-cli auth login --headless
vc-cli auth login --redirect-uri http://localtest.me:1410/callback
```

Expand Down
10 changes: 10 additions & 0 deletions src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ struct AuthLoginCliArgs {
default_value_t = crate::config::DEFAULT_AUTH_LISTEN_TIMEOUT_SECONDS
)]
auth_listen_timeout_seconds: u64,

#[arg(long)]
headless: bool,
}

#[derive(Debug, Args)]
Expand Down Expand Up @@ -407,6 +410,7 @@ pub async fn run_with_config_dir(config_dir: PathBuf) -> Result<()> {
client_secret: login.client_secret,
redirect_uri: login.redirect_uri,
auth_listen_timeout_seconds: login.auth_listen_timeout_seconds,
headless: login.headless,
},
)
.await?;
Expand Down Expand Up @@ -975,6 +979,12 @@ mod tests {
assert!(parsed.is_ok());
}

#[test]
fn auth_login_parses_headless_mode() {
let parsed = Cli::try_parse_from(["vc-cli", "auth", "login", "--headless"]);
assert!(parsed.is_ok());
}

#[test]
fn energy_tree_parses() {
let state = Cli::try_parse_from(["vc-cli", "energy", "state", "get"]);
Expand Down
Loading
Loading