Commit Graph

23 Commits

Author SHA1 Message Date
menachembadichi-blip 229d2d34fb Track CLI usage (#178)
AIAG-980
2026-08-04 16:47:19 +03:00
Jakub Majak 76b07668e4 chore(incidents): replace incidents with cases (#143)
https://coralogix.atlassian.net/browse/CX-40636
2026-06-26 15:07:04 +02:00
Yonatan Beker a5e61665d8 Fix incidents list filters and pagination (#117)
## Context
`cx incidents list` was producing frequent 400s because the v5 list
endpoint expects repeated filter fields, fully qualified incident enum
values, and paginated request/response shapes. The CLI was sending
several filters as scalar strings and did not bound or paginate list
responses, which made both API errors and oversized responses likely.

## Linked Issues

https://linear.app/coralogix/issue/AIAPP-1882/fix-incidents-list-endpoint

## Design
The list command now builds a typed `ListIncidentsOptions` object from
clap arguments, converts that into the v5 JSON request body in one
helper, and loops through `pagination.nextPageToken` until the requested
limit is reached. The API layer accepts the v5 `pagination` response
while retaining compatibility with older top-level `nextPageToken`.
Rendering stays unchanged after the command has accumulated incidents
across selected profiles.

## Key Decisions
The CLI accepts short user-facing values such as `CRITICAL`,
`TRIGGERED`, and `created_at`, then normalizes them to v5 enum values
like `INCIDENT_SEVERITY_CRITICAL`, `INCIDENT_STATUS_TRIGGERED`, and
`INCIDENTS_FIELDS_CREATED_TIME`. Results are bounded to `--limit 100` by
default to avoid unexpectedly large payloads; callers can opt into
`--all` when they deliberately need every page. When every selected
profile fails, list now exits nonzero instead of silently returning an
empty result, since the previous behavior hid live API failures.

## Changes
- Changes `cx incidents list` filters from scalar request fields to v5
repeated fields for status, severity, state, assignee, application, and
subsystem filters.
- Adds list flags for state, application/subsystem, contextual labels,
query targeting, muted/unmuted, created and duration ranges, ordering,
page size/token, bounded limits, and explicit `--all` pagination.
- Parses v5 pagination responses and fetches additional pages up to the
requested limit.
- Validates contextual labels and `--query` target selection before
sending malformed requests.
- Updates incident-management skill guidance to recommend bounded
queries and the supported filter set.
- Extends ignored live e2e coverage and adds a wiremock integration test
for request shape and pagination.

## Testing
- `cargo test --lib incidents --locked`
- `cargo test --test incidents --locked`
- `cargo test incidents --locked`
- `cargo test --test e2e incidents --locked`
- `cargo test --test e2e incidents --locked -- --ignored --nocapture`
- `cargo fmt --check`
- `cargo clippy --locked -- -D warnings`
- Manual live checks with `target/debug/cx incidents list` covering:
`--limit`, status/severity filters, state filter, created range plus
ordering, muted/unmuted, app/subsystem, contextual labels, repeated
status/severity, duration range, and pagination across pages.
- Manual live search checks: contextual-label search and some
`searchQuery.incidentField` values succeeded without 400s; `ID` and
`SEVERITY` incident-field search returned v5 server 500s.

## Risks & Rollout
This changes the public `cx incidents list` interface by making existing
`--status`, `--severity`, and `--assignee` repeatable while preserving
single-use invocations. The default result set is now bounded to 100
incidents, which is safer for agents but may return fewer rows than
before for users who expected an unbounded first response; `--all`
restores full pagination. Rollback is the single commit if the v5
request shape causes unexpected compatibility issues.

## Out of Scope / Follow-ups
Grouping global help options is intentionally left for a separate task.
v5 incident search has server-side inconsistencies: the OpenAPI schema
says `searchQuery.field` is required, the live endpoint rejects that
field, and `searchQuery.incidentField` with `ID` or `SEVERITY` returns
500. This PR avoids known malformed no-target search requests but does
not attempt to work around those server-side search failures.
2026-06-01 10:46:03 +03:00
Yonatan Beker 67b5e85203 feat(metrics): add TOON-encoded agents output for range queries (#102)
## Summary

- Adds `range_samples_to_toon_rows()` to flatten each `(metric,
timestamp, value)` triple from a range query into its own TOON row,
matching the pattern established by `instant_samples_to_toon_rows()`
- Splits the `OutputFormat::Agents` arm in `run_query_range()` away from
`OutputFormat::Json` so `-o agents` produces TOON output instead of raw
JSON
- Epoch timestamps from the PromQL API are converted to ISO-8601 via
`chrono` (e.g. `2024-06-22T00:00:00Z`) to prevent LLM
timestamp-conversion errors
- Column order: sorted metric label keys → optional `profile` →
`timestamp` → `value`

## Tests

- 10 new unit tests for `range_samples_to_toon_rows` covering: empty
input, single/multiple series, differing labels (padding), alphabetical
key sort, ISO-8601 timestamp formatting, profile column
inclusion/exclusion, and column order
- 1 new wiremock integration test (`range_query_agents_output`)
verifying the full API → parse → TOON encode pipeline

## Validation

```
cargo fmt --check   ✓
cargo clippy --locked -- -D warnings   ✓
cargo test --locked   315 passed, 0 failed
```

🤖 Generated with [Claude Code](https://claude.ai/claude-code)

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 17:00:20 +03:00
Veronika Kolin Ambar f0e7ca1410 docs: rewrite Quick Start as step-by-step prompt guide (#86)
## Summary
- Replaces the full interactive session transcript in the Quick Start
with a single copy-paste command and a numbered list of what to fill in
at each prompt
- The old block mixed CLI output with user inputs (`eu2`, `production`,
`file`) making it hard to scan and impossible to copy-paste meaningfully
- Credential storage explanation is now inline in the prompt list
instead of buried in a paragraph after the block

## Before / After

**Before:** a 15-line terminal session transcript showing inputs and
outputs mixed together

**After:**
```sh
cx profiles add
```
Then a numbered list: Authentication method → Region → Label →
Credential storage

## Context
Feedback from Yael Vogel / Niv Hertz via the Coralogix docs team (Slack,
2026-05-06). Tracked in CX-41355.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 09:15:13 +03:00
Liran Hason b35bec9c60 docs: add read-only mode docs, rename allow_costly_commands to olly_enabled (#99)
CXAI-2089

## Summary
- Document `--read-only` flag, `CX_READ_ONLY` env var, and `read_only`
config option in `docs/configuration.md`
- Add previously undocumented `allow_risky_commands` and `olly_enabled`
fields to the global config table and example
- Rename `allow_costly_commands` to `olly_enabled` throughout code,
tests, and docs - the old name was overly generic for what it actually
gates (`olly ask`)

## Test plan
- [x] `cargo fmt` - clean
- [x] `cargo clippy` - no warnings
- [x] `cargo test` - 590 passed
- [x] `cargo test --test risky_costly_gating` - 10 passed (includes
renamed olly gating tests)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-05-14 19:07:17 +03:00
Yonatan Beker 86585e47cb feat: support storing OAuth tokens in profile file (now default) (#72)
## Summary
- OAuth profiles can now persist tokens either inline in the profile
TOML (`credential_storage = "file"`, the new default) or in the OS
keyring (`os_store`), mirroring the existing API-key flow. `cx profiles
add` prompts for the choice.
- Adds `StoredOAuthTokens` to the profile schema (`access_token`,
`refresh_token`, `id_token`, `expiry`), serialized inline only when
`credential_storage = "file"` and skipped otherwise. File-mode profile
TOMLs are still written with `0600` perms.
- `oauth::resolve_token` now takes the chosen storage backend and any
cached file tokens, and returns refreshed tokens to the caller so
`resolve_single` can persist them back to disk after a refresh. Keyring
path is unchanged in behavior.
- Refactors: extracted `unix_now_secs()` helper (replaces 4 inline
`SystemTime` calls); replaced the `&[&str]` storage-options array +
`starts_with` lookup with a paired `&[(&str, CredentialStorage)]` table
and a `select_credential_storage()` helper used by both configure paths.
- Tests: 7 new unit tests in `oauth.rs` covering `tokens_to_stored`
(with/without `expires_in`), `cached_token_is_valid` (expiry path +
JWT-fallback path), and three `resolve_token` File-mode paths
(cached-valid no-network, missing-tokens error, expired-no-refresh
error). New TOML round-trip test for OAuth profiles with file-stored
tokens.
- Docs: `docs/configuration.md` updated (quick-start example output,
OAuth section, profile-fields table, new file-storage example with
sample `[oauth_tokens]`); `README.md` credential-storage paragraph
rewritten.

## Test plan
- [x] `cargo test --lib` (286 + 7 new = 293 passing)
- [x] `cargo fmt`
- [x] `cargo clippy --lib` clean
- [ ] Manual: `cx profiles add` -> OAuth -> pick `file` -> verify TOML
contains `[oauth_tokens]`, run a query, force token expiry, verify
refresh updates the file in place
- [ ] Manual: `cx profiles add` -> OAuth -> pick `os-store` -> verify
TOML has no `[oauth_tokens]`, refresh still works against keyring
- [ ] Manual: re-add an existing profile and switch storage backend in
both directions; verify no stale state in keyring or TOML

## Known follow-up
- Concurrent `cx` invocations on the same file-mode OAuth profile can
race when both find the access token expired and both refresh; the
loser's rotated refresh token gets clobbered by the non-atomic
`fs::write` in `save_profile`. Low likelihood in normal interactive use,
more plausible under fan-out / scripts. Worth a follow-up to use atomic
rename or a file lock.
- If the IdP omits `refresh_token` from a refresh response (some don't
rotate), both backends currently lose the cached refresh token.
Pre-existing bug for the keyring path; file path inherits it.
2026-05-05 17:26:00 +03:00
Veronika Kolin Ambar 00cf07d3df fix: correct DataPrime string quoting in shell examples (#68)
## Summary

Three doc fixes based on customer report and portal QA.

### 1. DataPrime string quoting in shell examples

Shell examples use double quotes for DataPrime string literals, but
DataPrime only accepts single quotes. Running the examples as written
produces:

```
error from profile 'default': API request failed (400): Compilation errors:
 - malformed expression at [0:22:22-0:23:23]: `"`
 - excessive input at [0:28:28-0:29:29]: `"`
```

- Severity comparisons: remove quotes — `ERROR`, `INFO`, etc. are enum
values in DataPrime and don't need quoting
- String comparisons (e.g. `serviceName`): switch to double-quoted outer
shell arg with escaped `$` and single-quoted DataPrime string literal

### 2. `<details open>` → `<details open markdown="1">`

MkDocs Material requires `markdown="1"` on `<details>` elements to
render Markdown content inside them correctly.

### 3. Fix 404 on `skills/README.md` link

The relative `skills/README.md` link in the AI agent skills section
resolves correctly on GitHub but 404s on the Coralogix docs portal (the
`skills/` directory is not synced). Changed to an absolute GitHub URL.

**Files changed:** `README.md`, `docs/multi-profile.md`,
`docs/time-syntax.md`

Reported via Coralogix support (DOCS-23).
2026-05-05 13:48:05 +00:00
Veronika Kolin Ambar 53aee66ee1 ci: trigger documentation sync on README and docs changes (#41) 2026-05-05 11:50:12 +03:00
Liran Hason 13915ea843 Add all cx APIs to CLI with skills and docs (#51)
AIAG-696

## Summary

### Full API coverage
- Implement remaining cx CLI commands covering all Coralogix APIs
(dashboards, views, SLOs, incidents, notifications, webhooks,
enrichments, parsing-rules, TCO, quotas, usage, archive, integrations,
IAM, recording-rules, E2M, search-fields) - 27 command groups total
- Add user-facing skills for all command groups (cx-observability-setup,
cx-cost-optimization, cx-incident-management, cx-data-pipeline,
cx-platform-admin, cx-create-dashboard)
- Rename all skills to cx- prefix for consistency, update
cross-references and docs
- Add integration tests (wiremock) and E2E test scaffolding for all new
commands
- Update CLAUDE.md, README, CODEOWNERS, architecture docs, and
contributor guides
- Bug fixes: data_usage timestamp parsing, users error propagation,
team_groups unused params, dashboard skill API wire values, stale skill
paths

### CLI safety features
- Add `--read-only` global flag that blocks all write operations before
credential resolution - safe for exploration and agent use
- Add agent mode detection (`CX_AGENT_MODE`, `CLAUDECODE`, `CLAUDE_CODE`
env vars) - blocks write operations unless `--yes` is passed
- Wire `confirm_destructive()` to all write subcommands across all 27
command groups (104 call sites) - interactive confirmation for
create/update/delete/enable/disable operations
- Mark `iam` and `archive` as `(risky)` in help output
- Add `[requires --yes]` tags to all write subcommand help text (102
annotations)
- Update skills with read-only and agent mode guidance

### Testing
- 441 tests passing (88 ignored E2E)
- Add `tests/write_command_gating/` - systematic verification that every
write command is gated
- Add `tests/read_only/` - read-only mode enforcement tests
- Add `tests/agent_mode/` - agent mode detection and blocking tests
- Add integration tests (wiremock) for all new command groups
- Add E2E test scaffolding for all commands

## Test plan
- [x] `cargo fmt --check` passes
- [x] `cargo clippy` passes with no warnings
- [x] `cargo test` passes (441 unit + integration tests)
- [ ] `cargo test --test e2e -- --ignored --test-threads=1` passes
against test team (requires CX_API_KEY)
- [ ] `cx schema` outputs updated command tree with all new commands
- [ ] Skills trigger correctly in Claude Code sessions

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-03 13:34:50 +03:00
Niv Hertz 97567eef37 Renamed crate to an available name (coralogix-cli) (#50)
Jira ticket: AIAG-684
2026-04-28 15:04:58 +03:00
Niv Hertz fb6b654692 Add support for auto complete (#44)
Jira ticket: AIAG-662
2026-04-27 18:46:12 +03:00
Yonatan Beker 5cea5f74ab fix: support env-only credentials when no profile file exists (#43) 2026-04-27 18:12:11 +03:00
Yonatan Beker d20b088039 Expand CODEOWNERS with per-domain review gates (#42)
CXAI-2055

## Summary
- Restructure source so each CLI command owns a directory:
`src/commands/<cmd>/{mod.rs,api.rs}` (was `src/commands/<cmd>.rs` +
`src/api/<cmd>.rs`). Rename `src/api/client.rs` → `src/api_client.rs`.
- Restructure tests to mirror the new layout: integration suites become
`tests/<cmd>/main.rs`, e2e suites become `tests/e2e/<cmd>/mod.rs`.
- Replace the single-line `* @coralogix/team-cxai` CODEOWNERS with
per-domain review gates (traces, metrics, dataprime, config-surface,
docs). All domains currently resolve to `@coralogix/team-cxai` as
placeholders — swap in real team handles when domain teams form.
- Update contributor docs and dev skills (`CLAUDE.md`,
`docs/architecture.md`, `docs/adding-a-command.md`,
`.claude/skills/add-command`, `.claude/skills/run-tests`) to reflect the
new per-command layout.
2026-04-27 17:41:43 +03:00
Yonatan Beker 482182250c Add e2e tests (#38) 2026-04-27 17:19:12 +03:00
Veronika Kolin Ambar e9f3ecb6d1 docs: rewrite user-facing reference docs (#36) 2026-04-27 12:49:39 +03:00
Idan Sil 17a8432592 Refine create-dashboard skill: live query verification + cx-CLI deploy (#28)
## Ticket

[AIKN-348](https://coralogix.atlassian.net/browse/AIKN-348)

## Summary

Refines the `create-dashboard` skill and extends the `cx` CLI so the
skill can verify its own queries and deploy the finished dashboard
end-to-end, instead of emitting JSON for the user to paste into the
Coralogix UI.

### Skill (`skills/create-dashboard/`)
- **Workflow expanded to 7 phases** — adds a live-verify phase (every
PromQL / DataPrime query runs through the `cx` CLI before deploy) and a
deploy phase (`cx dashboards create` into a user-chosen folder),
replacing the old "paste into Dashboards → Import" ending.
- **Stops duplicating query-language knowledge.** Phase 1 discovery and
the references now delegate to the sibling `metrics-query`,
`query-logs`, `query-spans`, `dataprime`, and `telemetry-querying`
skills. `references/query-syntax.md` is slimmed to
Coralogix-dashboard-specific gotchas only (``${__range}``,
`promqlQueryType`, widget filter syntax, common PromQL idioms) and
points readers at the sibling skill references for full language docs.
- **Live verification uses the dashboard's own time range.** Phase 5
substitutes ``${__range}`` with a concrete token derived from
`relativeTimeFrame` (e.g. `[48h]` for the default `172800s`) for the CLI
check, then restores ``${__range}`` in the emitted JSON so the dashboard
keeps the injected variable.
- **Prevents invented metric names early.** Phase 1 requires each
proposed metric to appear in `cx metrics search` output before being
used, catching the #1 failure mode before verification has to.
- Deleted `references/workflow.md` (100% redundant with the rewritten
`SKILL.md`).
- Refreshed `references/widget-templates.md` to point at the sibling
skills and Phase 5 live verification.

### CLI (`src/`)
- `src/api/dashboards.rs` — adds `DashboardsApi::create` (`POST
/mgmt/openapi/latest/dashboards/dashboards/v1`) and
`DashboardsApi::folders` (`GET
/mgmt/openapi/latest/dashboards/folders/v1`), plus `DashboardFolderItem`
/ `DashboardFoldersResponse` / `FolderIdValue` types.
- `src/commands/dashboards.rs` — new `run_create` handler (accepts a
bare dashboard JSON or a `{"dashboard": ...}` wrapper from file or
stdin, auto-generates the `requestId` envelope, optionally injects
`folderId` from `--folder`) and `run_folders_list` (table / JSON /
agents output), mirroring the `cx alerts create` pattern.
- `src/main.rs` — extends `DashboardsCmd` with `Create { from_file,
folder }` and `Folders { List }` and wires them through.

New CLI surface:

```
cx dashboards create --from-file <path|-> [--folder <id>]
cx dashboards folders list
```

## Test plan

- [x] `cargo fmt --check`
- [x] `cargo clippy` (no new warnings in changed files; there's a
pre-existing warning in `src/api/dataprime.rs` unrelated to this change)
- [x] `cargo build`
- [x] `cargo test --lib` (89/89 pass locally)
- [x] `cx dashboards create --help` / `cx dashboards folders list
--help` show the new subcommands
- [x] End-to-end: `cx dashboards folders list` against a live profile,
then `cx dashboards create --from-file <dashboard>.json --folder <id>`
returns the new dashboard ID

[AIKN-348]:
https://coralogix.atlassian.net/browse/AIKN-348?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
2026-04-26 18:04:39 +03:00
Yonatan Beker 0455f7deb7 Extract shared rendering helpers into src/render.rs (#34) 2026-04-26 17:40:58 +03:00
Veronika Kolin Ambar 0349f9beea docs: align contributor docs with style guide (#37) 2026-04-26 10:55:11 +03:00
Yonatan Beker 89c5e71057 Add contributor-facing documentation (#27)
## Summary
- Add `CONTRIBUTING.md` with ownership model, PR review process, and
contribution lifecycle
- Add `docs/architecture.md` covering execution flow, key modules,
config, and output modes
- Add `docs/adding-a-command.md` step-by-step guide for implementing new
CLI commands
- Add `docs/adding-a-skill.md` guide for creating Claude Code skill
plugins

These docs are aimed at Coralogix domain teams onboarding to contribute
commands and skills to the cx CLI.

---------
2026-04-23 13:38:14 +03:00
Niv Hertz c736d206f5 Base Working CLI
Co-authored-by: Yonatan Beker <yonatan.beker@coralogix.com>
Co-authored-by: Yonatan Beker <yonbek@users.noreply.github.com>
Co-authored-by: menachembadichi-blip <menachem.badichi@coralogix.com>
2026-04-20 10:27:59 +03:00
Yonatan Beker 6f6983f245 Set up CI/CD pipeline for GitHub-based releases (#2)
## Summary
- Add GitHub Actions CI workflows: lint (fmt + clippy), test
(cross-platform: ubuntu, macos, windows), build verification, and
dependency security audit
- Add release workflow triggered by version tags — builds cross-platform
binaries (macOS x86/ARM, Linux x86/ARM musl), signs artifacts with
cosign, and creates GitHub releases
- Add Homebrew formula template and shell installer script
(`install.sh`) for easy distribution
- Update README with installation instructions (shell, Homebrew, cargo,
pre-built binaries)
- Pin all action SHAs and Rust toolchain version (1.87.0) for
reproducibility

JIRA: AIAG-469
2026-03-30 13:54:07 +03:00
Yonatan Beker e61cc07b72 Set up new cx CLI repository with project scaffolding (#1)
## Summary
- Migrate codebase from old repo: full Rust project scaffold
(`Cargo.toml`, `Cargo.lock`, `src/main.rs`), pinned to Rust 1.87.0
- Add project documentation: `README.md`, `CLAUDE.md`, `SECURITY.md`,
`CODEOWNERS`, `LICENSE` (Apache-2.0)
- Add detailed docs: configuration, agents output, multi-profile
fan-out, time syntax, development guide
- Include Claude Code skills for observability (alerts, metrics,
telemetry querying)
- Add example config and `.gitignore`

JIRA: AIAG-468
2026-03-29 14:57:36 +03:00