cometapi-cli 0.1.0__tar.gz → 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. cometapi_cli-0.2.0/.github/ISSUE_TEMPLATE/bug_report.yml +46 -0
  2. cometapi_cli-0.2.0/.github/ISSUE_TEMPLATE/feature_request.yml +25 -0
  3. cometapi_cli-0.2.0/.github/PULL_REQUEST_TEMPLATE.md +14 -0
  4. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/.github/workflows/publish.yml +7 -1
  5. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/AGENTS.md +17 -5
  6. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/CHANGELOG.md +3 -3
  7. cometapi_cli-0.2.0/CODE_OF_CONDUCT.md +54 -0
  8. cometapi_cli-0.2.0/CONTRIBUTING.md +48 -0
  9. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/PKG-INFO +29 -7
  10. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/README.md +24 -2
  11. cometapi_cli-0.2.0/SECURITY.md +27 -0
  12. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/docs/commands/init.md +29 -8
  13. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/pyproject.toml +5 -5
  14. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/src/cometapi_cli/__init__.py +1 -1
  15. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/src/cometapi_cli/app.py +2 -2
  16. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/src/cometapi_cli/commands/account.py +1 -1
  17. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/src/cometapi_cli/commands/balance.py +1 -1
  18. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/src/cometapi_cli/commands/chat.py +3 -3
  19. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/src/cometapi_cli/commands/config_cmd.py +77 -11
  20. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/src/cometapi_cli/commands/doctor.py +1 -1
  21. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/src/cometapi_cli/commands/logs.py +19 -48
  22. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/src/cometapi_cli/commands/models.py +1 -1
  23. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/src/cometapi_cli/commands/repl.py +1 -1
  24. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/src/cometapi_cli/commands/stats.py +1 -1
  25. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/src/cometapi_cli/commands/tasks.py +2 -2
  26. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/src/cometapi_cli/commands/tokens.py +1 -1
  27. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/tests/test_logs.py +0 -14
  28. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/.github/workflows/ci.yml +0 -0
  29. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/.gitignore +0 -0
  30. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/LICENSE +0 -0
  31. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/SKILL.md +0 -0
  32. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/docs/README.md +0 -0
  33. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/docs/authentication.md +0 -0
  34. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/docs/commands/account.md +0 -0
  35. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/docs/commands/balance.md +0 -0
  36. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/docs/commands/chat.md +0 -0
  37. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/docs/commands/config.md +0 -0
  38. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/docs/commands/doctor.md +0 -0
  39. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/docs/commands/logs.md +0 -0
  40. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/docs/commands/models.md +0 -0
  41. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/docs/commands/repl.md +0 -0
  42. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/docs/commands/stats.md +0 -0
  43. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/docs/commands/tasks.md +0 -0
  44. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/docs/commands/tokens.md +0 -0
  45. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/docs/configuration.md +0 -0
  46. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/docs/errors.md +0 -0
  47. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/docs/installation.md +0 -0
  48. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/docs/output-formats.md +0 -0
  49. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/skills/live-test/SKILL.md +0 -0
  50. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/src/cometapi_cli/client.py +0 -0
  51. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/src/cometapi_cli/commands/__init__.py +0 -0
  52. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/src/cometapi_cli/commands/chat_repl.py +0 -0
  53. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/src/cometapi_cli/config.py +0 -0
  54. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/src/cometapi_cli/console.py +0 -0
  55. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/src/cometapi_cli/constants.py +0 -0
  56. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/src/cometapi_cli/errors.py +0 -0
  57. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/src/cometapi_cli/formatters.py +0 -0
  58. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/src/cometapi_cli/main.py +0 -0
  59. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/tests/__init__.py +0 -0
  60. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/tests/conftest.py +0 -0
  61. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/tests/test_account.py +0 -0
  62. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/tests/test_balance.py +0 -0
  63. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/tests/test_chat.py +0 -0
  64. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/tests/test_config.py +0 -0
  65. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/tests/test_doctor.py +0 -0
  66. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/tests/test_errors.py +0 -0
  67. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/tests/test_formatters.py +0 -0
  68. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/tests/test_help.py +0 -0
  69. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/tests/test_models.py +0 -0
  70. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/tests/test_stats.py +0 -0
  71. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/tests/test_tasks.py +0 -0
  72. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/tests/test_tokens.py +0 -0
  73. {cometapi_cli-0.1.0 → cometapi_cli-0.2.0}/uv.lock +0 -0
@@ -0,0 +1,46 @@
1
+ name: Bug Report
2
+ description: Report a bug in CometAPI CLI
3
+ labels: ["bug"]
4
+ body:
5
+ - type: textarea
6
+ id: description
7
+ attributes:
8
+ label: Description
9
+ description: A clear description of the bug.
10
+ validations:
11
+ required: true
12
+ - type: textarea
13
+ id: steps
14
+ attributes:
15
+ label: Steps to Reproduce
16
+ description: How can we reproduce this?
17
+ placeholder: |
18
+ 1. Run `cometapi ...`
19
+ 2. ...
20
+ validations:
21
+ required: true
22
+ - type: textarea
23
+ id: expected
24
+ attributes:
25
+ label: Expected Behavior
26
+ description: What did you expect to happen?
27
+ validations:
28
+ required: true
29
+ - type: textarea
30
+ id: actual
31
+ attributes:
32
+ label: Actual Behavior
33
+ description: What actually happened? Include any error output.
34
+ validations:
35
+ required: true
36
+ - type: textarea
37
+ id: environment
38
+ attributes:
39
+ label: Environment
40
+ description: Version and platform info.
41
+ placeholder: |
42
+ - CLI version: (cometapi --version)
43
+ - Python version:
44
+ - OS:
45
+ validations:
46
+ required: true
@@ -0,0 +1,25 @@
1
+ name: Feature Request
2
+ description: Suggest a new feature or improvement
3
+ labels: ["enhancement"]
4
+ body:
5
+ - type: textarea
6
+ id: problem
7
+ attributes:
8
+ label: Problem
9
+ description: What problem does this feature solve?
10
+ validations:
11
+ required: true
12
+ - type: textarea
13
+ id: solution
14
+ attributes:
15
+ label: Proposed Solution
16
+ description: How should this work?
17
+ validations:
18
+ required: true
19
+ - type: textarea
20
+ id: alternatives
21
+ attributes:
22
+ label: Alternatives Considered
23
+ description: Any other approaches you've considered?
24
+ validations:
25
+ required: false
@@ -0,0 +1,14 @@
1
+ ## Description
2
+
3
+ <!-- What does this PR do? -->
4
+
5
+ ## Related Issues
6
+
7
+ <!-- Link related issues: Fixes #123, Closes #456 -->
8
+
9
+ ## Checklist
10
+
11
+ - [ ] Tests pass (`uv run pytest -v`)
12
+ - [ ] Lint passes (`uv run ruff check src/ tests/`)
13
+ - [ ] CHANGELOG.md updated (if user-facing change)
14
+ - [ ] Documentation updated (if applicable)
@@ -6,7 +6,7 @@ on:
6
6
  - "v*"
7
7
 
8
8
  permissions:
9
- contents: read
9
+ contents: write
10
10
  id-token: write
11
11
 
12
12
  jobs:
@@ -28,3 +28,9 @@ jobs:
28
28
 
29
29
  - name: Publish to PyPI
30
30
  uses: pypa/gh-action-pypi-publish@release/v1
31
+
32
+ - name: Create GitHub Release
33
+ uses: softprops/action-gh-release@v2
34
+ with:
35
+ generate_release_notes: true
36
+ files: dist/*
@@ -82,24 +82,36 @@ Package name: `cometapi-cli`. Triggered automatically by pushing a `v*` tag to G
82
82
  ### Release SOP
83
83
 
84
84
  ```bash
85
- # 1. Bump version in TWO places (must match):
85
+ # 1. Update CHANGELOG.md with the new version section
86
+
87
+ # 2. Bump version in TWO places (must match):
86
88
  # - pyproject.toml: version = "X.Y.Z"
87
89
  # - src/cometapi_cli/__init__.py: __version__ = "X.Y.Z"
88
90
 
89
- # 2. Commit and push
90
- git add -A
91
- git commit -m "release: vX.Y.Z"
91
+ # 3. Merge dev → main
92
+ git checkout main
93
+ git merge dev
92
94
  git push origin main
93
95
 
94
- # 3. Tag and push — triggers publish.yml automatically
96
+ # 4. Tag and push — triggers publish.yml automatically
97
+ # (publishes to PyPI + creates GitHub Release with auto-generated notes)
95
98
  git tag vX.Y.Z
96
99
  git push origin vX.Y.Z
100
+
101
+ # 5. Switch back to dev
102
+ git checkout dev
97
103
  ```
98
104
 
99
105
  ### Verify
100
106
 
101
107
  ```bash
108
+ # Check PyPI
102
109
  open https://pypi.org/project/cometapi-cli/
110
+
111
+ # Check GitHub Release
112
+ open https://github.com/cometapi-dev/cometapi-cli/releases
113
+
114
+ # Install and test
103
115
  pip install cometapi-cli==X.Y.Z
104
116
  cometapi --version
105
117
  ```
@@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
- ## [0.2.0] — 2026-04-09
8
+ ## [0.2.0] — 2026-04-13
9
9
 
10
10
  ### Added
11
11
 
@@ -18,11 +18,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
18
18
  - **Config management**: `config show/set/unset/path` subcommands, TOML config at `~/.config/cometapi/config.toml`
19
19
  - **Persistent output_format**: set default output format in `config.toml`
20
20
  - **Doctor diagnostics**: connectivity, auth, SDK, and config health checks
21
- - **Setup wizard**: `cometapi init` with API key validation
21
+ - **Setup wizard**: `cometapi init` with API key validation, existing config detection, and reconfiguration flow
22
22
  - **Shell completion**: bash, zsh, fish, powershell
23
23
  - **Error handling**: structured exit codes (sysexits.h compatible), user-friendly messages
24
24
  - **Security**: credential masking, 0600 file permissions, creation URL guidance
25
- - **CI/CD**: GitHub Actions for testing (Python 3.10–3.13) and PyPI publishing
25
+ - **CI/CD**: GitHub Actions for testing (Python 3.10–3.13), PyPI publishing, and GitHub Releases
26
26
 
27
27
  ### Changed
28
28
 
@@ -0,0 +1,54 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in our
6
+ community a harassment-free experience for everyone, regardless of age, body
7
+ size, visible or invisible disability, ethnicity, sex characteristics, gender
8
+ identity and expression, level of experience, education, socio-economic status,
9
+ nationality, personal appearance, race, caste, color, religion, or sexual
10
+ identity and orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to a positive environment:
15
+
16
+ - Using welcoming and inclusive language
17
+ - Being respectful of differing viewpoints and experiences
18
+ - Gracefully accepting constructive criticism
19
+ - Focusing on what is best for the community
20
+ - Showing empathy towards other community members
21
+
22
+ Examples of unacceptable behavior:
23
+
24
+ - The use of sexualized language or imagery, and sexual attention or advances of any kind
25
+ - Trolling, insulting or derogatory comments, and personal or political attacks
26
+ - Public or private harassment
27
+ - Publishing others' private information without explicit permission
28
+ - Other conduct which could reasonably be considered inappropriate in a professional setting
29
+
30
+ ## Enforcement Responsibilities
31
+
32
+ Community leaders are responsible for clarifying and enforcing our standards of
33
+ acceptable behavior and will take appropriate and fair corrective action in
34
+ response to any behavior that they deem inappropriate, threatening, offensive,
35
+ or harmful.
36
+
37
+ ## Scope
38
+
39
+ This Code of Conduct applies within all community spaces, and also applies when
40
+ an individual is officially representing the community in public spaces.
41
+
42
+ ## Enforcement
43
+
44
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
45
+ reported to the community leaders responsible for enforcement at
46
+ **support@cometapi.com**.
47
+
48
+ All complaints will be reviewed and investigated promptly and fairly.
49
+
50
+ ## Attribution
51
+
52
+ This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/),
53
+ version 2.1, available at
54
+ <https://www.contributor-covenant.org/version/2/1/code_of_conduct.html>.
@@ -0,0 +1,48 @@
1
+ # Contributing to CometAPI CLI
2
+
3
+ Thank you for your interest in contributing! Here's how to get started.
4
+
5
+ ## Development Setup
6
+
7
+ ```bash
8
+ git clone https://github.com/cometapi-dev/cometapi-cli.git
9
+ cd cometapi-cli
10
+ uv sync --extra dev
11
+ ```
12
+
13
+ ## Making Changes
14
+
15
+ 1. **Fork** the repository and create a feature branch from `main`.
16
+ 2. **Write or update tests** for your change.
17
+ 3. **Run tests and lint** before submitting:
18
+ ```bash
19
+ uv run pytest -v
20
+ uv run ruff check src/ tests/
21
+ ```
22
+ 4. **Open a pull request** with a clear description of the change.
23
+
24
+ ## Code Style
25
+
26
+ - Follow [Ruff](https://docs.astral.sh/ruff/) defaults (configured in `pyproject.toml`).
27
+ - Keep the code typed — use type hints for all public functions.
28
+ - All network calls go through `CometClient` — never use raw HTTP in commands.
29
+
30
+ ## Reporting Bugs
31
+
32
+ Open an issue using the **Bug Report** template. Include:
33
+ - CLI version (`cometapi --version`)
34
+ - Python version
35
+ - OS
36
+ - Steps to reproduce
37
+
38
+ ## Suggesting Features
39
+
40
+ Open an issue using the **Feature Request** template.
41
+
42
+ ## Code of Conduct
43
+
44
+ This project follows the [Contributor Covenant Code of Conduct](CODE_OF_CONDUCT.md). By participating, you agree to abide by its terms.
45
+
46
+ ## License
47
+
48
+ By contributing, you agree that your contributions will be licensed under the [MIT License](LICENSE).
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cometapi-cli
3
- Version: 0.1.0
3
+ Version: 0.2.0
4
4
  Summary: CometAPI CLI — official command-line interface for the CometAPI AI gateway
5
- Project-URL: Homepage, https://github.com/CometAPI/cometapi-cli
6
- Project-URL: Repository, https://github.com/CometAPI/cometapi-cli
5
+ Project-URL: Homepage, https://github.com/cometapi-dev/cometapi-cli
6
+ Project-URL: Repository, https://github.com/cometapi-dev/cometapi-cli
7
7
  Project-URL: Documentation, https://docs.cometapi.com
8
- Project-URL: Changelog, https://github.com/CometAPI/cometapi-cli/blob/main/CHANGELOG.md
9
- Project-URL: Issues, https://github.com/CometAPI/cometapi-cli/issues
8
+ Project-URL: Changelog, https://github.com/cometapi-dev/cometapi-cli/blob/main/CHANGELOG.md
9
+ Project-URL: Issues, https://github.com/cometapi-dev/cometapi-cli/issues
10
10
  Author-email: CometAPI <support@cometapi.com>
11
11
  License: MIT
12
12
  License-File: LICENSE
@@ -164,6 +164,20 @@ cometapi config unset api_key # Remove a value
164
164
  cometapi config path # Show config file path
165
165
  ```
166
166
 
167
+ ### Examples
168
+
169
+ ```bash
170
+ # Switch default output to JSON (all commands)
171
+ cometapi config set output_format json
172
+
173
+ # Change default model
174
+ cometapi config set default_model claude-sonnet-4-6
175
+
176
+ # Override per-command (regardless of config)
177
+ cometapi models --format yaml
178
+ cometapi balance --json
179
+ ```
180
+
167
181
  **Priority**: CLI flags > config file > environment variables > defaults
168
182
 
169
183
  | Key | Env Variable | Description |
@@ -186,7 +200,7 @@ CometAPI CLI is designed to be agent-friendly:
186
200
  ## Development
187
201
 
188
202
  ```bash
189
- git clone https://github.com/CometAPI/cometapi-cli.git
203
+ git clone https://github.com/cometapi-dev/cometapi-cli.git
190
204
  cd cometapi-cli
191
205
  uv sync --extra dev
192
206
 
@@ -199,7 +213,7 @@ uv run cometapi --version # verify
199
213
  <summary>Without uv (pip)</summary>
200
214
 
201
215
  ```bash
202
- git clone https://github.com/CometAPI/cometapi-cli.git
216
+ git clone https://github.com/cometapi-dev/cometapi-cli.git
203
217
  cd cometapi-cli
204
218
  pip install -e ".[dev]"
205
219
  pytest -v
@@ -223,6 +237,14 @@ pytest -v
223
237
  | `Connection failed` | Run `cometapi doctor` to diagnose connectivity |
224
238
  | `Access token not configured` | Only needed for `account`/`stats` commands — run `cometapi init` to add one |
225
239
 
240
+ ## Contributing
241
+
242
+ Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
243
+
244
+ ## License
245
+
246
+ This project is licensed under the [MIT License](LICENSE).
247
+
226
248
  ## License
227
249
 
228
250
  MIT
@@ -126,6 +126,20 @@ cometapi config unset api_key # Remove a value
126
126
  cometapi config path # Show config file path
127
127
  ```
128
128
 
129
+ ### Examples
130
+
131
+ ```bash
132
+ # Switch default output to JSON (all commands)
133
+ cometapi config set output_format json
134
+
135
+ # Change default model
136
+ cometapi config set default_model claude-sonnet-4-6
137
+
138
+ # Override per-command (regardless of config)
139
+ cometapi models --format yaml
140
+ cometapi balance --json
141
+ ```
142
+
129
143
  **Priority**: CLI flags > config file > environment variables > defaults
130
144
 
131
145
  | Key | Env Variable | Description |
@@ -148,7 +162,7 @@ CometAPI CLI is designed to be agent-friendly:
148
162
  ## Development
149
163
 
150
164
  ```bash
151
- git clone https://github.com/CometAPI/cometapi-cli.git
165
+ git clone https://github.com/cometapi-dev/cometapi-cli.git
152
166
  cd cometapi-cli
153
167
  uv sync --extra dev
154
168
 
@@ -161,7 +175,7 @@ uv run cometapi --version # verify
161
175
  <summary>Without uv (pip)</summary>
162
176
 
163
177
  ```bash
164
- git clone https://github.com/CometAPI/cometapi-cli.git
178
+ git clone https://github.com/cometapi-dev/cometapi-cli.git
165
179
  cd cometapi-cli
166
180
  pip install -e ".[dev]"
167
181
  pytest -v
@@ -185,6 +199,14 @@ pytest -v
185
199
  | `Connection failed` | Run `cometapi doctor` to diagnose connectivity |
186
200
  | `Access token not configured` | Only needed for `account`/`stats` commands — run `cometapi init` to add one |
187
201
 
202
+ ## Contributing
203
+
204
+ Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
205
+
206
+ ## License
207
+
208
+ This project is licensed under the [MIT License](LICENSE).
209
+
188
210
  ## License
189
211
 
190
212
  MIT
@@ -0,0 +1,27 @@
1
+ # Security Policy
2
+
3
+ ## Supported Versions
4
+
5
+ | Version | Supported |
6
+ |---------|-----------|
7
+ | 0.2.x | ✅ |
8
+ | < 0.2 | ❌ |
9
+
10
+ ## Reporting a Vulnerability
11
+
12
+ If you discover a security vulnerability, please report it responsibly:
13
+
14
+ 1. **Do NOT open a public issue.**
15
+ 2. Email **support@cometapi.com** with details of the vulnerability.
16
+ 3. Include steps to reproduce, if possible.
17
+
18
+ We will acknowledge receipt within 48 hours and aim to provide a fix or mitigation plan within 7 days.
19
+
20
+ ## Security Practices
21
+
22
+ - API keys and access tokens are **never** logged or displayed in full — only the last 4 characters are shown.
23
+ - Config files are stored with restrictive permissions (`0600`).
24
+ - Credentials should **never** be committed to version control.
25
+ - Create credentials at:
26
+ - API Key: https://www.cometapi.com/console/token
27
+ - Access Token: https://www.cometapi.com/console/personal
@@ -18,14 +18,16 @@ No credentials required — this command sets them up.
18
18
 
19
19
  ## Wizard Flow
20
20
 
21
- 1. **Security notice** — displays a warning about credential handling and links to creation pages.
22
- 2. **API key prompt** — asks for `COMETAPI_KEY`. Shows current value (masked) as default if already configured.
23
- 3. **Connectivity test** — if an API key is provided, tests connectivity by calling `models.list()`.
24
- 4. **Access token prompt** — asks whether to configure `COMETAPI_ACCESS_TOKEN` (optional). Shows current value (masked) as default.
25
- 5. **Default model** — asks for the default model to use with `chat` (default: `gpt-5.4`).
26
- 6. **Save** — writes configuration to `~/.config/cometapi/config.toml` with `0600` permissions.
21
+ 1. **Existing config check** — if a config file exists, displays a summary of current settings (secrets masked) and asks whether to continue with reconfiguration. User can abort to keep config unchanged.
22
+ 2. **Security notice** — displays a warning about credential handling and links to creation pages.
23
+ 3. **API key prompt** — asks for `COMETAPI_KEY`. Shows current value (masked) as default if already configured. Displays `(Enter to keep)` hint when a value exists.
24
+ 4. **Connectivity test** — if an API key is provided, tests connectivity by calling `models.list()`.
25
+ 5. **Access token prompt** — asks whether to configure `COMETAPI_ACCESS_TOKEN` (optional). Shows current value (masked) as default. Displays `(Enter to keep)` hint when a value exists.
26
+ 6. **Default model** — asks for the default model to use with `chat` (default: `gpt-5.4`).
27
+ 7. **Default output format** — asks for the default output format (default: `table`).
28
+ 8. **Save** — writes configuration to `~/.config/cometapi/config.toml` with `0600` permissions. If no values were changed, skips writing and displays "No changes made."
27
29
 
28
- ## Example Session
30
+ ## Example Session (First Run)
29
31
 
30
32
  ```
31
33
  🚀 Welcome
@@ -49,6 +51,7 @@ Configure access token? (for account/stats commands) [y/n]: y
49
51
  Access Token (COMETAPI_ACCESS_TOKEN): pat-...
50
52
 
51
53
  Default model [gpt-5.4]: gpt-5.4
54
+ Default output format (table, json, yaml, csv, markdown) [table]: table
52
55
 
53
56
  ✅ Setup Complete
54
57
  Configuration saved to /Users/you/.config/cometapi/config.toml
@@ -62,7 +65,25 @@ Next steps:
62
65
 
63
66
  ## Re-Running Init
64
67
 
65
- Running `init` again shows current masked values as defaults. Press Enter to keep existing values, or type a new value to replace.
68
+ When a configuration file already exists, `init` displays a summary of current settings and prompts for confirmation before proceeding:
69
+
70
+ ```
71
+ 📋 Current Config
72
+ Existing configuration found:
73
+
74
+ api_key = ****abcd
75
+ access_token = ****wxyz
76
+ default_model = gpt-5.4
77
+ output_format = table
78
+
79
+ Press Enter on each prompt to keep the current value.
80
+
81
+ Continue with reconfiguration? [Y/n]:
82
+ ```
83
+
84
+ - Press **Enter** or **y** to proceed — each prompt shows `(Enter to keep)` so you can skip unchanged fields.
85
+ - Press **n** to abort — config file remains untouched.
86
+ - If you go through all prompts without changing anything, the wizard prints "No changes made" and does not rewrite the file.
66
87
 
67
88
  ## Credential Links
68
89
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "cometapi-cli"
3
- version = "0.1.0"
3
+ version = "0.2.0"
4
4
  description = "CometAPI CLI — official command-line interface for the CometAPI AI gateway"
5
5
  readme = "README.md"
6
6
  license = { text = "MIT" }
@@ -40,11 +40,11 @@ dev = [
40
40
  ]
41
41
 
42
42
  [project.urls]
43
- Homepage = "https://github.com/CometAPI/cometapi-cli"
44
- Repository = "https://github.com/CometAPI/cometapi-cli"
43
+ Homepage = "https://github.com/cometapi-dev/cometapi-cli"
44
+ Repository = "https://github.com/cometapi-dev/cometapi-cli"
45
45
  Documentation = "https://docs.cometapi.com"
46
- Changelog = "https://github.com/CometAPI/cometapi-cli/blob/main/CHANGELOG.md"
47
- Issues = "https://github.com/CometAPI/cometapi-cli/issues"
46
+ Changelog = "https://github.com/cometapi-dev/cometapi-cli/blob/main/CHANGELOG.md"
47
+ Issues = "https://github.com/cometapi-dev/cometapi-cli/issues"
48
48
 
49
49
  [project.scripts]
50
50
  cometapi = "cometapi_cli.app:app"
@@ -1,3 +1,3 @@
1
1
  """CometAPI CLI — professional terminal interface for CometAPI."""
2
2
 
3
- __version__ = "0.1.0"
3
+ __version__ = "0.2.0"
@@ -33,11 +33,11 @@ def main(
33
33
  ctx: typer.Context,
34
34
  version: Annotated[
35
35
  bool | None,
36
- typer.Option("--version", "-V", help="Show version and exit.", callback=_version_callback, is_eager=True),
36
+ typer.Option("--version", "-V", "-v", help="Show version and exit.", callback=_version_callback, is_eager=True),
37
37
  ] = None,
38
38
  output_format: Annotated[
39
39
  OutputFormat,
40
- typer.Option("--format", "-f", help="Output format."),
40
+ typer.Option("--format", "-f", help="Output format (table, json, yaml, csv, markdown)."),
41
41
  ] = OutputFormat.TABLE,
42
42
  json_output: Annotated[
43
43
  bool,
@@ -14,7 +14,7 @@ from ..formatters import OutputFormat, output, resolve_format
14
14
  @handle_errors
15
15
  def account(
16
16
  ctx: typer.Context,
17
- output_format: Annotated[OutputFormat | None, typer.Option("--format", "-f", help="Output format.")] = None,
17
+ output_format: Annotated[OutputFormat | None, typer.Option("--format", "-f", help="Output format (table, json, yaml, csv, markdown).")] = None,
18
18
  json_output: Annotated[bool, typer.Option("--json", help="Output as JSON.")] = False,
19
19
  ) -> None:
20
20
  """Show your CometAPI account profile (requires access token)."""
@@ -18,7 +18,7 @@ def balance(
18
18
  str | None,
19
19
  typer.Option("--source", "-s", help="Data source: 'account' (full account) or 'token' (current API key)."),
20
20
  ] = None,
21
- output_format: Annotated[OutputFormat | None, typer.Option("--format", "-f", help="Output format.")] = None,
21
+ output_format: Annotated[OutputFormat | None, typer.Option("--format", "-f", help="Output format (table, json, yaml, csv, markdown).")] = None,
22
22
  json_output: Annotated[bool, typer.Option("--json", help="Output as JSON.")] = False,
23
23
  ) -> None:
24
24
  """Show your CometAPI account balance.
@@ -17,12 +17,12 @@ from ..formatters import OutputFormat, resolve_format
17
17
  def chat(
18
18
  ctx: typer.Context,
19
19
  message: Annotated[str | None, typer.Argument(help="Message to send. Omit to enter interactive REPL.")] = None,
20
- model: Annotated[str | None, typer.Option("--model", "-m", help="Model to use.")] = None,
20
+ model: Annotated[str | None, typer.Option("--model", "-m", help="Model to use (default: from config or gpt-5.4).")] = None,
21
21
  system: Annotated[str | None, typer.Option("--system", "-s", help="System prompt.")] = None,
22
- temperature: Annotated[float | None, typer.Option("--temperature", "-t", help="Sampling temperature.")] = None,
22
+ temperature: Annotated[float | None, typer.Option("--temperature", "-t", help="Sampling temperature (0.0–2.0).")] = None,
23
23
  max_tokens: Annotated[int | None, typer.Option("--max-tokens", help="Max tokens in response.")] = None,
24
24
  stream: Annotated[bool, typer.Option("--stream/--no-stream", help="Stream output.")] = True,
25
- output_format: Annotated[OutputFormat | None, typer.Option("--format", "-f", help="Output format.")] = None,
25
+ output_format: Annotated[OutputFormat | None, typer.Option("--format", "-f", help="Output format (table, json, yaml, csv, markdown).")] = None,
26
26
  json_output: Annotated[bool, typer.Option("--json", help="Output as JSON.")] = False,
27
27
  ) -> None:
28
28
  """Send a chat message, or start interactive REPL (no args)."""
@@ -13,7 +13,12 @@ from ..console import console, err_console
13
13
  from ..errors import handle_errors
14
14
  from ..formatters import OutputFormat, output, resolve_format
15
15
 
16
- config_app = typer.Typer(name="config", help="Manage CLI configuration.")
16
+ config_app = typer.Typer(
17
+ name="config",
18
+ help="Manage CLI configuration.",
19
+ no_args_is_help=True,
20
+ context_settings={"help_option_names": ["-h", "--help"]},
21
+ )
17
22
 
18
23
 
19
24
  @handle_errors
@@ -31,6 +36,34 @@ def init(ctx: typer.Context) -> None:
31
36
  )
32
37
  )
33
38
 
39
+ cfg = load_config()
40
+ has_existing = bool(cfg)
41
+
42
+ # Show existing config summary and let user decide
43
+ if has_existing:
44
+ summary_lines = []
45
+ for key in ("api_key", "access_token", "default_model", "output_format", "base_url"):
46
+ val = cfg.get(key)
47
+ if val:
48
+ display = mask_secret(str(val)) if key in ("api_key", "access_token") else val
49
+ summary_lines.append(f" [bold]{key}[/bold] = {display}")
50
+ if summary_lines:
51
+ console.print(
52
+ Panel(
53
+ "[bold yellow]Existing configuration found:[/bold yellow]\n\n"
54
+ + "\n".join(summary_lines)
55
+ + "\n\n[dim]Press Enter on each prompt to keep the current value.[/dim]",
56
+ title="📋 Current Config",
57
+ border_style="yellow",
58
+ )
59
+ )
60
+ if not Confirm.ask(
61
+ "[bold]Continue with reconfiguration?[/bold]",
62
+ default=True,
63
+ ):
64
+ console.print("[dim]Aborted. Config unchanged.[/dim]")
65
+ return
66
+
34
67
  console.print(
35
68
  Panel(
36
69
  "[bold yellow]⚠ Security Notice[/bold yellow]\n\n"
@@ -43,17 +76,19 @@ def init(ctx: typer.Context) -> None:
43
76
  )
44
77
  )
45
78
 
46
- cfg = load_config()
79
+ changed = False
47
80
 
48
81
  # API Key
49
82
  current_key = cfg.get("api_key", "")
50
83
  default_display = mask_secret(current_key) if current_key else None
84
+ hint = " [dim](Enter to keep)[/dim]" if current_key else ""
51
85
  api_key = Prompt.ask(
52
- "[bold]API Key[/bold] (COMETAPI_KEY)",
86
+ f"[bold]API Key[/bold] (COMETAPI_KEY){hint}",
53
87
  default=default_display,
54
88
  )
55
89
  if api_key and api_key != default_display:
56
90
  cfg["api_key"] = api_key
91
+ changed = True
57
92
 
58
93
  # Validate connectivity
59
94
  if cfg.get("api_key"):
@@ -75,22 +110,45 @@ def init(ctx: typer.Context) -> None:
75
110
  default=bool(current_token),
76
111
  ):
77
112
  default_token_display = mask_secret(current_token) if current_token else None
113
+ hint = " [dim](Enter to keep)[/dim]" if current_token else ""
78
114
  access_token = Prompt.ask(
79
- "[bold]Access Token[/bold] (COMETAPI_ACCESS_TOKEN)",
115
+ f"[bold]Access Token[/bold] (COMETAPI_ACCESS_TOKEN){hint}",
80
116
  default=default_token_display,
81
117
  )
82
118
  if access_token and access_token != default_token_display:
83
119
  cfg["access_token"] = access_token
120
+ changed = True
84
121
 
85
122
  # Default model
86
123
  console.print()
124
+ current_model = cfg.get("default_model", "")
125
+ model_default = current_model or get_default_model()
87
126
  default_model = Prompt.ask(
88
127
  "[bold]Default model[/bold]",
89
- default=cfg.get("default_model", get_default_model()),
128
+ default=model_default,
129
+ )
130
+ if default_model != current_model:
131
+ cfg["default_model"] = default_model
132
+ changed = True
133
+
134
+ # Default output format
135
+ console.print()
136
+ current_format = cfg.get("output_format", "")
137
+ format_default = current_format or "table"
138
+ output_format = Prompt.ask(
139
+ "[bold]Default output format[/bold] (table, json, yaml, csv, markdown)",
140
+ default=format_default,
90
141
  )
91
- cfg["default_model"] = default_model
142
+ if output_format != current_format:
143
+ cfg["output_format"] = output_format
144
+ changed = True
92
145
 
93
146
  # Save
147
+ if has_existing and not changed:
148
+ console.print()
149
+ console.print("[dim]No changes made. Config unchanged.[/dim]")
150
+ return
151
+
94
152
  save_config(cfg)
95
153
 
96
154
  console.print()
@@ -113,7 +171,7 @@ def init(ctx: typer.Context) -> None:
113
171
  @handle_errors
114
172
  def config_show(
115
173
  ctx: typer.Context,
116
- output_format: Annotated[OutputFormat | None, typer.Option("--format", "-f", help="Output format.")] = None,
174
+ output_format: Annotated[OutputFormat | None, typer.Option("--format", "-f", help="Output format (table, json, yaml, csv, markdown).")] = None,
117
175
  json_output: Annotated[bool, typer.Option("--json", help="Output as JSON.")] = False,
118
176
  ) -> None:
119
177
  """Display current configuration (secrets are masked)."""
@@ -137,10 +195,18 @@ def config_show(
137
195
  @config_app.command("set")
138
196
  @handle_errors
139
197
  def config_set(
140
- key: Annotated[str, typer.Argument(help="Configuration key.")],
141
- value: Annotated[str, typer.Argument(help="Configuration value.")],
198
+ key: Annotated[str, typer.Argument(help="Configuration key (api_key, access_token, base_url, default_model, output_format).")],
199
+ value: Annotated[str, typer.Argument(help="Value to set. For output_format: table, json, yaml, csv, markdown.")],
142
200
  ) -> None:
143
- """Set a configuration value."""
201
+ """Set a configuration value.
202
+
203
+ Valid keys: api_key, access_token, base_url, default_model, output_format.
204
+
205
+ Examples:
206
+ cometapi config set output_format json
207
+ cometapi config set default_model claude-sonnet-4-6
208
+ cometapi config set api_key sk-xxx
209
+ """
144
210
  if key not in VALID_KEYS:
145
211
  err_console.print(f"[red bold]Error:[/] Unknown key '{key}'. Valid keys: {', '.join(sorted(VALID_KEYS))}")
146
212
  raise typer.Exit(code=2)
@@ -155,7 +221,7 @@ def config_set(
155
221
  @config_app.command("unset")
156
222
  @handle_errors
157
223
  def config_unset(
158
- key: Annotated[str, typer.Argument(help="Configuration key to remove.")],
224
+ key: Annotated[str, typer.Argument(help="Configuration key to remove (api_key, access_token, base_url, default_model, output_format).")],
159
225
  ) -> None:
160
226
  """Remove a configuration value."""
161
227
  cfg = load_config()
@@ -25,7 +25,7 @@ def _warn_mark() -> str:
25
25
  @handle_errors
26
26
  def doctor(
27
27
  ctx: typer.Context,
28
- output_format: Annotated[OutputFormat | None, typer.Option("--format", "-f", help="Output format.")] = None,
28
+ output_format: Annotated[OutputFormat | None, typer.Option("--format", "-f", help="Output format (table, json, yaml, csv, markdown).")] = None,
29
29
  json_output: Annotated[bool, typer.Option("--json", help="Output as JSON.")] = False,
30
30
  ) -> None:
31
31
  """Check CLI configuration and API connectivity."""
@@ -162,10 +162,9 @@ def logs(
162
162
  str | None,
163
163
  typer.Option("--type", help="Filter by type: consume, topup, error, refund, manage, system."),
164
164
  ] = None,
165
- search: Annotated[str | None, typer.Option("--search", "-s", help="[deprecated] Search logs by keyword.")] = None,
166
165
  start: Annotated[str | None, typer.Option("--start", help="Start date (YYYY-MM-DD, ISO 8601, or Unix ts).")] = None,
167
166
  end: Annotated[str | None, typer.Option("--end", help="End date (YYYY-MM-DD, ISO 8601, or Unix ts).")] = None,
168
- group: Annotated[str | None, typer.Option("--group", "-g", help="Filter by group.")] = None,
167
+ group: Annotated[str | None, typer.Option("--group", "-g", help="Filter by API key group name.")] = None,
169
168
  request_id: Annotated[
170
169
  str | None,
171
170
  typer.Option("--request-id", help="Look up cost by request ID (X-Cometapi-Request-Id header)."),
@@ -177,7 +176,7 @@ def logs(
177
176
  page: Annotated[int, typer.Option("--page", "-p", help="Page number.")] = 1,
178
177
  limit: Annotated[int, typer.Option("--limit", "-l", help="Results per page.")] = 20,
179
178
  export: Annotated[bool, typer.Option("--export", help="Export logs as CSV to stdout.")] = False,
180
- output_format: Annotated[OutputFormat | None, typer.Option("--format", "-f", help="Output format.")] = None,
179
+ output_format: Annotated[OutputFormat | None, typer.Option("--format", "-f", help="Output format (table, json, yaml, csv, markdown).")] = None,
181
180
  json_output: Annotated[bool, typer.Option("--json", help="Output as JSON.")] = False,
182
181
  ) -> None:
183
182
  """Show your usage logs (requires access token)."""
@@ -247,52 +246,24 @@ def logs(
247
246
  sys.stdout.buffer.write(csv_bytes)
248
247
  return
249
248
 
250
- if search:
251
- err_console.print(
252
- "[yellow]Warning:[/] --search only matches log type codes on the server, "
253
- "not keywords. Use --request-id, --model, or --token-name for filtering."
254
- )
255
- ignored = []
256
- if model:
257
- ignored.append("--model")
258
- if token_name:
259
- ignored.append("--token-name")
260
- if log_type:
261
- ignored.append("--type")
262
- if start:
263
- ignored.append("--start")
264
- if end:
265
- ignored.append("--end")
266
- if group:
267
- ignored.append("--group")
268
- if page != 1:
269
- ignored.append("--page")
270
- if limit != 20:
271
- ignored.append("--limit")
272
- if ignored:
273
- err_console.print(
274
- f"[yellow]Warning:[/] --search ignores other filters: {', '.join(ignored)}"
275
- )
276
- resp = client.search_logs(keyword=search)
277
- else:
278
- type_int = None
279
- if log_type:
280
- type_int = LOG_TYPE_MAP.get(log_type.lower())
281
- if type_int is None:
282
- valid = ", ".join(LOG_TYPE_MAP.keys())
283
- err_console.print(f"[red]Invalid log type:[/] {log_type}. Valid types: {valid}")
284
- raise typer.Exit(code=2)
249
+ type_int = None
250
+ if log_type:
251
+ type_int = LOG_TYPE_MAP.get(log_type.lower())
252
+ if type_int is None:
253
+ valid = ", ".join(LOG_TYPE_MAP.keys())
254
+ err_console.print(f"[red]Invalid log type:[/] {log_type}. Valid types: {valid}")
255
+ raise typer.Exit(code=2)
285
256
 
286
- resp = client.list_logs(
287
- page=page,
288
- page_size=limit,
289
- log_type=type_int,
290
- model_name=model,
291
- token_name=token_name,
292
- start_timestamp=start_ts,
293
- end_timestamp=end_ts,
294
- group=group,
295
- )
257
+ resp = client.list_logs(
258
+ page=page,
259
+ page_size=limit,
260
+ log_type=type_int,
261
+ model_name=model,
262
+ token_name=token_name,
263
+ start_timestamp=start_ts,
264
+ end_timestamp=end_ts,
265
+ group=group,
266
+ )
296
267
 
297
268
  data = extract_items(resp)
298
269
 
@@ -16,7 +16,7 @@ def models(
16
16
  ctx: typer.Context,
17
17
  search: Annotated[str | None, typer.Option("--search", "-s", help="Filter models by name.")] = None,
18
18
  limit: Annotated[int | None, typer.Option("--limit", "-l", help="Max number of models to show.")] = None,
19
- output_format: Annotated[OutputFormat | None, typer.Option("--format", "-f", help="Output format.")] = None,
19
+ output_format: Annotated[OutputFormat | None, typer.Option("--format", "-f", help="Output format (table, json, yaml, csv, markdown).")] = None,
20
20
  json_output: Annotated[bool, typer.Option("--json", help="Output as JSON.")] = False,
21
21
  ) -> None:
22
22
  """List available models."""
@@ -71,7 +71,7 @@ def run_repl() -> None:
71
71
  completer = WordCompleter(
72
72
  REPL_COMMANDS + [
73
73
  "--json", "--format", "--model", "--system",
74
- "--search", "--limit", "--help", "--page",
74
+ "--limit", "--help", "--page",
75
75
  "--type", "--token-name", "--start", "--end",
76
76
  "--group", "--export", "--platform", "--task-id",
77
77
  "--status", "--action",
@@ -14,7 +14,7 @@ from ..formatters import OutputFormat, output, resolve_format
14
14
  @handle_errors
15
15
  def stats(
16
16
  ctx: typer.Context,
17
- output_format: Annotated[OutputFormat | None, typer.Option("--format", "-f", help="Output format.")] = None,
17
+ output_format: Annotated[OutputFormat | None, typer.Option("--format", "-f", help="Output format (table, json, yaml, csv, markdown).")] = None,
18
18
  json_output: Annotated[bool, typer.Option("--json", help="Output as JSON.")] = False,
19
19
  ) -> None:
20
20
  """Show your CometAPI usage statistics (requires access token)."""
@@ -61,12 +61,12 @@ def tasks(
61
61
  str | None,
62
62
  typer.Option("--status", "-s", help=f"Filter by status: {', '.join(VALID_STATUSES)}."),
63
63
  ] = None,
64
- action: Annotated[str | None, typer.Option("--action", "-a", help="Filter by action type.")] = None,
64
+ action: Annotated[str | None, typer.Option("--action", "-a", help="Filter by action type (platform-dependent, e.g. generate, upscale, vary).")] = None,
65
65
  start: Annotated[str | None, typer.Option("--start", help="Start date (YYYY-MM-DD, ISO 8601, or Unix ts).")] = None,
66
66
  end: Annotated[str | None, typer.Option("--end", help="End date (YYYY-MM-DD, ISO 8601, or Unix ts).")] = None,
67
67
  page: Annotated[int, typer.Option("--page", help="Page number.")] = 1,
68
68
  limit: Annotated[int, typer.Option("--limit", "-l", help="Results per page.")] = 20,
69
- output_format: Annotated[OutputFormat | None, typer.Option("--format", "-f", help="Output format.")] = None,
69
+ output_format: Annotated[OutputFormat | None, typer.Option("--format", "-f", help="Output format (table, json, yaml, csv, markdown).")] = None,
70
70
  json_output: Annotated[bool, typer.Option("--json", help="Output as JSON.")] = False,
71
71
  ) -> None:
72
72
  """Show your async task logs — Suno, MJ, Luma, Kling, etc. (requires access token)."""
@@ -46,7 +46,7 @@ def tokens(
46
46
  search: Annotated[str | None, typer.Option("--search", "-s", help="Search tokens by name or key.")] = None,
47
47
  page: Annotated[int, typer.Option("--page", "-p", help="Page number.")] = 1,
48
48
  limit: Annotated[int, typer.Option("--limit", "-l", help="Results per page.")] = 20,
49
- output_format: Annotated[OutputFormat | None, typer.Option("--format", "-f", help="Output format.")] = None,
49
+ output_format: Annotated[OutputFormat | None, typer.Option("--format", "-f", help="Output format (table, json, yaml, csv, markdown).")] = None,
50
50
  json_output: Annotated[bool, typer.Option("--json", help="Output as JSON.")] = False,
51
51
  ) -> None:
52
52
  """List and search your API keys (requires access token)."""
@@ -61,11 +61,6 @@ class TestLogsTable:
61
61
  start_timestamp=None, end_timestamp=None, group=None,
62
62
  )
63
63
 
64
- def test_logs_search(self, cli_runner, patched_client):
65
- result = cli_runner("logs", "--search", "claude")
66
- assert result.exit_code == 0
67
- patched_client.search_logs.assert_called_once_with(keyword="claude")
68
-
69
64
  def test_logs_filter_start_date(self, cli_runner, patched_client):
70
65
  result = cli_runner("logs", "--start", "2024-01-15")
71
66
  assert result.exit_code == 0
@@ -226,12 +221,3 @@ class TestLogsDetail:
226
221
  data = json.loads(result.output)
227
222
  assert len(data) == 2
228
223
 
229
-
230
- class TestLogsSearchDeprecation:
231
- """Test --search deprecation warning."""
232
-
233
- def test_logs_search_deprecation_warning(self, cli_runner, patched_client):
234
- result = cli_runner("logs", "--search", "anything")
235
- assert result.exit_code == 0
236
- patched_client.search_logs.assert_called_once_with(keyword="anything")
237
- # Warning should still be emitted (may be on stderr).
File without changes
File without changes
File without changes
File without changes