Metadata-Version: 2.5
Name: tarnished-cli
Version: 0.2.2
Summary: Command-line interface for Tarnished
Project-URL: Homepage, https://markoonakic.github.io/tarnished/
Project-URL: Repository, https://github.com/markoonakic/tarnished
Project-URL: Documentation, https://markoonakic.github.io/tarnished/how-to/use-the-cli/
License-Expression: MIT
License-File: LICENSE
Requires-Python: >=3.12
Requires-Dist: email-validator>=2.0.0
Requires-Dist: httpx>=0.28.1
Requires-Dist: keyring>=25.7.0
Requires-Dist: pydantic>=2.12.0
Requires-Dist: typer>=0.23.1
Requires-Dist: tzlocal>=5.3.1
Description-Content-Type: text/markdown

# Tarnished CLI

Command-line interface for Tarnished, version **0.2.2**. Use a matching Tarnished backend.

**Documentation:** https://markoonakic.github.io/tarnished/

For the user-facing CLI guide, see:
- https://markoonakic.github.io/tarnished/how-to/use-the-cli/

## Install

Install version 0.2.2 from PyPI once that release is available:

```bash
uv tool install tarnished-cli==0.2.2
```

To install this checkout, including before a release is published, run from the repository root:

```bash
uv tool install ./cli
```

Homebrew convenience path (the tap can lag the PyPI release):

```bash
brew tap markoonakic/tap
brew install tarnished-cli
```

To install a downloaded wheel:

```bash
uv tool install ./dist/tarnished_cli-<version>-py3-none-any.whl
```

## Authentication

Tarnished CLI is API-key-first.

1. Create or rotate the API key in the Tarnished web app.
2. Prefer the **CLI** preset so the key includes the scopes the CLI expects.
3. Validate and store the key locally:

```bash
tarnished auth init --api-key '...'
```

4. Run the auth doctor to confirm the stored key, live auth check, and required
   CLI scopes all pass:

```bash
tarnished auth doctor
tarnished auth whoami
```

5. Clear the locally stored key when needed:

```bash
tarnished auth api-key clear
```

The web app remains the source of truth for API keys. The CLI does **not**
create, rotate, revoke, or otherwise manage remote API keys.

The CLI uses the system keyring when available. Otherwise, it stores the key in
a private file in the CLI config directory. `TARNISHED_API_KEY` overrides stored
credentials. Clearing a stored key does not unset this environment variable.

## Usage

Global options go before the command:

```bash
tarnished --base-url https://tarnished.example.com auth status
tarnished --profile work --json applications list
tarnished applications --help
```

Create `config.json` in `~/.config/tarnished` (or
`$XDG_CONFIG_HOME/tarnished`) to set profiles:

```json
{
  "default_profile": "default",
  "profiles": {
    "default": { "base_url": "http://127.0.0.1:5577", "output": "json" },
    "work": { "base_url": "https://tarnished.example.com", "output": "json" }
  }
}
```

`--config-dir` and `TARNISHED_CONFIG_DIR` override this directory. Server URL
precedence is `--base-url`, then `TARNISHED_BASE_URL`, then the selected profile.
Use a trusted server: URL overrides send the selected profile's key to that server.
The CLI follows same-origin redirects but rejects cross-origin or
credential-bearing URLs. Use the final server URL where possible.

JSON is the default output. Set the profile's output to `text` or use
`TARNISHED_OUTPUT=text` for text output; `--json` overrides both. API and local
configuration errors exit with code 1. JSON errors go to stdout; text errors go
to stderr. Invalid command arguments use Typer's standard error output.

Imports, reports, and transcriptions support `--wait`, `--poll-interval`, and
`--timeout-seconds`. A local wait timeout does not cancel server work. Report
waits stop if another job replaces the submitted job. Review the saved state
before retrying an AI or speech request, which can incur provider charges.

## Development

```bash
cd cli
uv sync
uv run tarnished --help
uv run pytest -q
uv run ruff check .
uv run ruff format --check .
uv run pyright
uv build
```

## Release

The repository release workflow builds CLI distributions, uploads them to the
GitHub release, and publishes the CLI to PyPI by default. Homebrew tap updates
run in the separate `homebrew-tap.yml` workflow after Homebrew's 24-hour PyPI
resource-resolution cooldown window has elapsed.

### One-Time PyPI Trusted Publishing Setup

1. Create the `tarnished-cli` project on PyPI.
2. In the PyPI project settings, add a Trusted Publisher for this GitHub repository.
3. Use these values:
   - Owner: `markoonakic`
   - Repository: `tarnished`
   - Workflow name: `release.yml`
   - Environment name: `pypi`

### One-Time Homebrew Tap Automation Setup

1. Create a write-enabled deploy key for `markoonakic/homebrew-tap`.
2. Add the private key to this repository as the `HOMEBREW_TAP_DEPLOY_KEY` secret.
3. The dedicated `homebrew-tap.yml` workflow will:
   - wait until the target PyPI release is older than Homebrew's 24-hour Python resource cooldown window
   - update `Formula/tarnished-cli.rb` from PyPI metadata
   - refresh Python resource blocks with `brew update-python-resources`
   - build the formula from source and run `brew test tarnished-cli`
   - push the tap update to `markoonakic/homebrew-tap`

Why separate from the main release workflow?

- Homebrew's Python dependency resolver intentionally excludes PyPI uploads from the last 24 hours when refreshing resource blocks.
- Keeping tap sync separate avoids false-negative release failures while still following Homebrew's documented Python-formula workflow.

### Release Outputs

`release.yml` publishes:

- `cli/dist/*.whl`
- `cli/dist/*.tar.gz`

to the GitHub release and publishes the package to PyPI.

`homebrew-tap.yml` then updates the Homebrew tap separately once the published
sdist is old enough for `brew update-python-resources` to resolve safely.

## License

MIT. The wheel and source distribution include the LICENSE file.
