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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@
**/_debug/**

**/key.json
src/kognic/auth/_version.py
src/kognic/auth/_version.py
.claude
127 changes: 115 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,25 +29,59 @@ sess = RequestsAuthSession()
sess.get("https://api.app.kognic.com")
```

## CLI
## CLI (Experimental)

The package provides a command-line interface for generating access tokens and making authenticated API calls.
This is great for LLM use cases, the `kognic-auth call` is a lightweight curl, that hides any complexity of authentication and context management,
so you can just focus on the API call you want to make. This also avoids tokens being leaked to the shell history,
as you can use named contexts and config files to manage your credentials.

The interface is currently marked experimental, and breaking changes may be made without a major version bump. Feedback is welcome to help stabilize the design.

### Configuration file

The CLI can be configured with a JSON file at `~/.config/kognic/config.json`. This lets you define named contexts for different environments, each with its own host, auth server, and credentials.

```json
{
"default_context": "production",
"contexts": {
"production": {
"host": "app.kognic.com",
"auth_server": "https://auth.app.kognic.com",
"credentials": "~/.config/kognic/credentials-prod.json"
},
"demo": {
"host": "demo.kognic.com",
"auth_server": "https://auth.demo.kognic.com",
"credentials": "~/.config/kognic/credentials-demo.json"
}
}
}
```

Each context has the following fields:
- `host` - The API hostname, used by `call` to automatically match a context based on the request URL.
- `auth_server` - The OAuth server URL used to fetch tokens.
- `credentials` *(optional)* - Path to a JSON credentials file. Tilde (`~`) is expanded. If omitted, credentials are read from environment variables.

`default_context` specifies which context to use as a fallback when no `--context` flag is given and no URL match is found.

The package provides a command-line interface for generating access tokens, great for MCP integrations.
### get-access-token

Generate an access token for Kognic API authentication.

```bash
kognic-auth get-access-token [--server SERVER] [--credentials FILE]
kognic-auth get-access-token [--server SERVER] [--credentials FILE] [--context NAME] [--config FILE]
```

**Options:**
- `--server` - Authentication server URL (default: `https://auth.app.kognic.com`)
- `--credentials` - Path to JSON credentials file. If not provided, credentials are read from environment variables.
- `--context` - Use a named context from the config file.
- `--config` - Config file path (default: `~/.config/kognic/config.json`)

The token endpoint is constructed by appending `/v1/auth/oauth/token` to the server URL. For example:
- Default: `https://auth.app.kognic.com/v1/auth/oauth/token`
- Custom: `https://custom.server/v1/auth/oauth/token`

**Exit codes:**
- `0` - Success
- `1` - Error (missing credentials, invalid credentials file, authentication failure, etc.)
When `--context` is provided, the auth server and credentials are resolved from the config file. Explicit `--server` or `--credentials` flags override the context values.

**Examples:**
```bash
Expand All @@ -57,9 +91,78 @@ kognic-auth get-access-token
# Using a credentials file
kognic-auth get-access-token --credentials ~/.config/kognic/credentials.json

# Using a custom authentication server
kognic-auth get-access-token --server https://auth.<env>.kognic.com
# Using a named context
kognic-auth get-access-token --context demo

# Using a context but overriding the server
kognic-auth get-access-token --context demo --server https://custom.server
```

### call

Make an authenticated HTTP request to a Kognic API.

```bash
kognic-auth call URL [-X METHOD] [-d DATA] [-H HEADER] [--format FORMAT] [--context NAME] [--config FILE]
```

**Options:**
- `URL` - Full URL to call
- `-X`, `--request` - HTTP method (default: `GET`)
- `-d`, `--data` - Request body (JSON string)
- `-H`, `--header` - Header in `Key: Value` format (repeatable)
- `--format` - Output format (default: `json`). See [Output formats](#output-formats) below.
- `--context` - Force a specific context (skip URL-based matching)
- `--config` - Config file path (default: `~/.config/kognic/config.json`)

When `--context` is not provided, the context is automatically resolved by matching the request URL's hostname against the `host` field of each context in the config file.

**Examples:**
```bash
# GET request (default method), context auto-resolved from URL hostname
kognic-auth call https://app.kognic.com/v1/projects

# Explicit context
kognic-auth call https://demo.kognic.com/v1/projects --context demo

# POST with JSON body
kognic-auth call https://app.kognic.com/v1/projects -X POST -d '{"name": "test"}'

# Custom headers
kognic-auth call https://app.kognic.com/v1/projects -H "Accept: application/json"
```

#### Output formats

The `--format` option controls how JSON responses are printed. For `jsonl`, `csv`, `tsv`, and `table`, the command automatically extracts the list from responses that are either a top-level JSON array or a JSON object with a single key holding an array (e.g. `{"data": [...]}`). If the response doesn't match this shape, it falls back to pretty-printed JSON.

| Format | Description |
|---------|-------------|
| `json` | Pretty-printed JSON (default) |
| `jsonl` | One JSON object per line ([JSON Lines](https://jsonlines.org/)) |
| `csv` | Comma-separated values with a header row |
| `tsv` | Tab-separated values with a header row |
| `table` | Markdown table with aligned columns |

Nested values (dicts and lists) are JSON-serialized in `csv`, `tsv`, and `table` output.

```bash
# One JSON object per line, useful for piping to jq or grep
kognic-auth call https://app.kognic.com/v1/projects --format=jsonl

# CSV output
kognic-auth call https://app.kognic.com/v1/projects --format=csv

# TSV output, easy to paste into spreadsheets
kognic-auth call https://app.kognic.com/v1/projects --format=tsv

# Markdown table
kognic-auth call https://app.kognic.com/v1/projects --format=table
```

**Exit codes:**
- `0` - Success (HTTP 2xx)
- `1` - Error (HTTP error, missing credentials, invalid input, etc.)

## Changelog
See Github releases from v3.1.0, historic changelog is available in CHANGELOG.md
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,4 @@ line-length = 120
target-version = "py38"

[tool.ruff.lint]
select = ["E", "F", "B", "W", "I001"]
select = ["E", "F", "B", "W", "I001", "PTH"]
72 changes: 0 additions & 72 deletions src/kognic/auth/cli.py

This file was deleted.

38 changes: 38 additions & 0 deletions src/kognic/auth/cli/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from __future__ import annotations

import argparse
import sys
from types import ModuleType

from kognic.auth.cli import call, get_access_token

_SUBCOMMANDS: list[ModuleType] = [get_access_token, call]


def create_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
prog="kognic-auth",
description="Kognic authentication CLI",
)
subparsers = parser.add_subparsers(dest="command", help="Available commands")

for subcommand in _SUBCOMMANDS:
subcommand.register_parser(subparsers)

return parser


def main(args: list[str] | None = None) -> int:
parser = create_parser()
parsed = parser.parse_args(args)

for subcommand in _SUBCOMMANDS:
if parsed.command == subcommand.COMMAND:
return subcommand.run(parsed)

parser.print_help()
return 0


if __name__ == "__main__":
sys.exit(main())
Loading