Skip to content

CLI v5#222

Open
maximelb wants to merge 65 commits intomasterfrom
cli-v2
Open

CLI v5#222
maximelb wants to merge 65 commits intomasterfrom
cli-v2

Conversation

@maximelb
Copy link
Contributor

Description of the change

Temporary PR to trigger the test validations.

Type of change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

maximelb and others added 30 commits February 11, 2026 14:23
Full rewrite of the LimaCharlie Python SDK and CLI (v2.0.0) with
AI/LLM-first discoverability. All commands follow a consistent
noun-verb pattern with rich help, --explain flags, and multiple
output formats (json/yaml/csv/table/jsonl).

Core infrastructure:
- Click-based CLI with auto-discovered command modules
- HTTP client with JWT auth, retry with backoff, rate limiting
- Config system supporting ~/.limacharlie, env vars, named environments
- Structured error hierarchy with suggestion messages
- Output formatting with jmespath filtering

SDK (31 modules in limacharlie/sdk/):
- Organization, Sensor, D&R Rules, FP Rules, Hive, Outputs
- Artifacts, Payloads, Search, Extensions, Installation/Ingestion Keys
- Users, Groups, API Keys, Billing, Spout, Replay
- Integrity, Exfil, Logging Rules, Configs (sync), AI generation
- Investigations, USP, Jobs, YARA, ARL

CLI (49 command modules in limacharlie/commands/):
- Full CRUD for all resource types
- Hive shortcuts: secret, lookup, playbook, adapter, cloud-sensor, sop, note
- Help system: discover, help topics, cheatsheets, schema
- Streaming, sync, search with LCQL support

Tests:
- 481 unit tests (v2) covering all SDK and core modules
- 25 integration test files (63 tests) for API validation
- Removed 3 obsolete v1 unit tests replaced by v2 equivalents

Packaging:
- Entry point updated to limacharlie.cli:main
- Added click>=8.0 and jmespath dependencies

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- organization.py: service_request now base64-encodes request_data,
  get_urls unwraps data["url"], get_detections/get_audit_logs use
  correct response keys (detects/events) with next_cursor and
  gzip decompression, get_available_services unwraps replicants key,
  get_jobs decompresses compressed response
- sensor.py: get_info extracts data["info"], is_online checks
  data["online"] dict, get_tags handles v1 {sid: {tag: null}} format,
  is_isolated/is_sealed use should_isolate/should_seal fields,
  get_events uses next_cursor with decompression, get_children_events
  decompresses, get_overview extracts overview key
- search.py: adds https:// prefix and /v1 suffix to search URL,
  includes oid in all request bodies, sends times as strings
- extensions.py: rewritten to use correct extension/request/{name}
  endpoint with gzip+base64 encoded gzdata (was incorrectly going
  through service_request)
- configs.py: uses Extensions class directly instead of nonexistent
  org.extension_request method
- artifacts.py: rewritten to use ingestion URL with Basic auth
  headers matching v1 Logs.py upload pattern
- insight.py: search_ioc info param now configurable (was hardcoded),
  batch_search uses form-encoded params matching v1
- replay.py: passes is_async=True matching v1 behavior
- client.py: added unwrap() for gzip+base64 decompression
- cli.py: import errors logged when LC_DEBUG is set
- artifact.py CLI: --type/--start/--end/--limit no longer silently ignored
- sensor.py CLI: fixed --offset+--limit pagination
- _hive_shortcut.py: YAML-first parsing, supports usr_mtd/etag,
  better --confirm error message

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Bug fixes:
- Fix HiveRecord crash from invalid kwargs in _hive_shortcut.py
- Fix org rename() sending wrong query param (newName -> name)
- Fix subscribe/unsubscribe extension not splitting res_cat/res_name
- Fix replay double-serialization of detect/respond via service_request
- Fix on_refresh_auth callback inconsistency (now always passes client)
- Fix sensor set-version --version incorrectly required
- Fix org delete --confirm-token incorrectly required
- Remove sensor upgrade --selector that was silently ignored
- Fix ioc hosts using invalid IOC type instead of find_sensors_by_hostname
- Add defensive .get() for bare resp["key"] in org and sensor SDK
- Fix register_explain using spaces instead of dots in hive shortcuts

New features:
- Add OAuth browser-based login: limacharlie auth login --oauth
- Support Google and Microsoft providers with --provider flag
- Support headless OAuth with --no-browser flag
- MFA/2FA handled automatically via existing infrastructure

Documentation:
- Rewrite README with comprehensive CLI reference for all command groups
- Add accurate Python SDK examples matching actual v2 API patterns
- Document both API key and OAuth authentication flows
- Add SDK class reference table
- Move legacy v1 docs to bottom, v2 content first

Tests:
- Add tests for rename, subscribe/unsubscribe param splitting
- Add tests for get_all_tags defensive .get() and find_sensors_by_hostname
- Add tests for on_refresh_auth callback consistency
- Add tests for HiveRecord raw dict construction
- Add test for replay non-double-serialization

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
SDK fixes discovered by running integration tests against the live API:
- organization.py: fix add_api_key param (permissions→perms, json→join)
- organization.py: add default start/end time for get_jobs()
- artifacts.py: add required start/end params to list() with defaults
- search.py: add required startTime/endTime defaults to validate()
- integrity.py: replace non-existent get_rule action with list+filter
- logging_rules.py: same get_rule fix as integrity
- exfil.py: fix all action names, split delete into delete_event/delete_watch

CLI fixes:
- commands/exfil.py: add --type option to delete for event vs watch rules
- commands/integrity.py: handle None return from get() with error message
- commands/logging_cmd.py: same not-found handling as integrity
- commands/artifact.py: pass start/end to SDK, remove redundant filtering

Tests: 65 CLI integration tests covering all command groups (63 pass,
2 skip due to missing hive permissions on test API key).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove deprecated REST endpoints (GET/POST/DELETE /rules/{oid} and
/fp/{oid}) from the SDK and rewrite CLI commands to use the Hive API.
Rename `limacharlie rule` to `limacharlie dr` with namespace-to-hive
mapping (general→dr-general, managed→dr-managed, service→dr-service).
Replace FP commands with a 3-line hive shortcut backed by the fp hive.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix Click command naming: add explicit @group.command("set") in dr.py
  and hive.py to prevent Click deriving "set-cmd"/"set-record" names
- Fix HiveRecord construction crash in extension.py config-set (use
  raw= pattern instead of invalid kwargs)
- Fix payloads SDK: implement two-step signed URL pattern for upload
  and download matching v1 behavior
- Fix OAuth token persistence: save refreshed tokens to config file
- Fix exception swallowing in dr_rules.py/fp_rules.py: only catch
  ApiError with 404 status, re-raise other errors
- Fix insight.py: decompress response when is_compressed=true is set
- Fix hive.py rename: remove double URL encoding of new_name
- Update payload CLI download command to handle raw bytes from SDK
- Add test for non-404 errors propagating in DR rules get

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New `limacharlie auth signup` command that lets users create a brand
new LimaCharlie account and organization directly from the CLI.

The flow: OAuth authentication -> user profile creation via the signUp
Cloud Function -> new organization creation -> credentials saved.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New `limacharlie download` command group with sensor, adapter, and list
subcommands. Downloads pre-built binaries from downloads.limacharlie.io
for all supported platforms (Windows, Linux, macOS, Chrome, AIX,
FreeBSD, OpenBSD, NetBSD, Solaris) with sensible default filenames,
auto-executable permissions, and stdout piping support.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Modernize the CLI v2 codebase with three major improvements:

- Add `from __future__ import annotations` and full type annotations to
  all 80+ Python files (core, SDK, and command modules)
- Convert LimaCharlieContext and HiveRecord to @DataClass, add
  Credentials TypedDict to config.py
- Migrate packaging from setup.py/setup.cfg/requirements.txt to
  pyproject.toml with setuptools backend, add PEP 561 py.typed marker
- Update Dockerfile and CI (cloudbuild) for new packaging
- Add tests for dataclass conversions, type infrastructure, and packaging

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add consistent type annotations to _make_explain_callback inner
  functions across all 15 command files that were missing them
- Remove unused imports (signal, sys, os) from stream.py, artifact.py,
  output_cmd.py
- Fix spotcheck.py register_explain key from space to dot separator
- Fix test_packaging.py tomllib import for Python 3.9/3.10 compat
- Add tomli backport to pyproject.toml dev dependencies

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Current PyPI latest is 4.11.3, so 2.0.0 would be a downgrade.
Version 5.0.0 signals the major rewrite and sorts above 4.x.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix AI methods: remove spurious {oid} from paths, use "query" not "description"
- Fix org param names: "permission"->"perm", "email"->"member_email"
- Fix groups set_permissions: "permissions" dict -> "perm" list
- Rewrite investigations SDK to use Hive for CRUD operations
- Remove non-existent endpoints: artifacts.get, billing.get_sku_definitions,
  ingestion_keys.configure_usp, insight.get_object_timeline,
  insight.get_host_count_per_platform, org.find_sensors_by_ip,
  org.configure_usp_key, org.convert_extension_rules
- Remove CLI commands for removed endpoints (artifact get, billing skus,
  extension convert-rules)
- Update investigation CLI commands to use --name with Hive-based SDK
- Update tests for new investigation Hive interface

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update README.md investigation examples and all _EXPLAIN_* texts in
investigation.py to use --name instead of --id, matching the Hive-based
CLI commands.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Previously only ~8% of SDK methods had tests verifying actual HTTP
contracts (URL paths, methods, param names, body fields). This led to
bugs shipping undetected (wrong param names, wrong paths, wrong body
fields). Now every SDK method has a unit test verifying its full HTTP
contract.

- 16 new test files for ai, artifacts, billing, exfil, extensions,
  firehose, fp_rules, insight, integrity, investigations, jobs,
  logging_rules, payloads, replay, wrappers, yara
- Expanded organization (17→107 tests), sensor (13→27), spout, dr_rules,
  hive tests with full contract verification
- Slimmed test_sdk_misc.py to only ARL/USP/downloads (moved rest to
  dedicated files)
- Total: 814 passing tests (up from ~564)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
SDK fixes:
- config.py: Clear stale uid from config when explicit api_key provided
- Manager.py: Only inherit GLOBAL_UID when api_key also from globals
- organization.py: get_all_tags handles null, unwrap api_keys/installation_keys
- exfil.py: Split string path into list for service request
- usp.py: Wrap single json_input dict in list

Integration test fixes:
- Fix exfil/hive/artifacts/outputs/search/AI/groups/replay tests
- Handle user-only auth endpoints gracefully
- Use valid FP rule data for hive CRUD test
- Fix CLI command names for search tests

Unit test updates:
- Update exfil path and USP json_input assertions to match SDK fixes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Table output now auto-truncates large dicts ({N keys}) and long lists
([N items]) to fit the terminal. --wide/-W disables truncation, and
--filter applies a JMESPath expression to transform output data.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds ~40 new tests across two files:
- test_output.py: truncation, max_value_width, _table_value, wide mode,
  module-level filter expr, and detect_output_format tests
- test_cli_commands.py: CliRunner tests for global --wide/--filter flags,
  auth (whoami, test, list-envs), org (info, urls, errors), sensor (list,
  get, delete without confirm), DR (list), and --explain flag

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove the infrastructure-service code path and use_extension toggle from
Configs — all sync now goes through ext-infrastructure.  Drop the legacy
--rules / --fps CLI flags (and sync_rules / sync_fps SDK params) in favor
of hive flags (--hive-dr-general, --hive-fp, etc.) matching the old v1 CLI.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…unknown api key"

When users login with OAuth but don't set a default org, org-scoped commands
would fail with the cryptic JWT endpoint error "unknown api key". Now we catch
the missing OID before hitting the network and suggest use-org, --oid flag
placement, or LC_OID env var.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two issues caused OAuth login to fail with "unknown api key":

1. All _get_org helpers double-resolved credentials — they called
   resolve_credentials() then re-passed api_key explicitly to Client(),
   which cleared OAuth creds inside Client's own resolve_credentials().
   Fix: let Client resolve credentials once from oid + environment.

2. OAuth login preserved any stale api_key already in the config file.
   Fix: clear api_key from config on successful OAuth login.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ut help text

- adapter.py now uses "external adapter" noun to distinguish from cloud adapters
- Hive shortcut factory uses proper a/an article for nouns starting with vowels
- Subcommand help text uses the noun instead of generic "records"
- Group help drops the internal hive name for cleaner output

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Mock resolve_credentials so the test doesn't pick up api_key from
the developer's ~/.limacharlie config file.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ud adapters

The bare 'adapter' name was ambiguous — cloud sensors are often called
"cloud adapters". Now 'ext-adapter' and 'cloud-sensor' are clearly distinct.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rename 'ext-adapter' to 'external-adapter' for clarity, and rename
'cloud-sensor' to 'cloud-adapter' so both adapter types use consistent
naming.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reflect the cloud-sensor → cloud-adapter and adapter → external-adapter
renames in the hive shortcuts section.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Strip top-level wrapper keys (payloads, users, user_permissions, groups,
errors) so CLI output shows useful data directly instead of a single
wrapper object. Follows the existing resp.get("key", resp) pattern
already used by get_api_keys, get_installation_keys, get_outputs, etc.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement _is_list_of_dicts() to detect dict-of-dicts data (e.g.
payloads keyed by name) and flatten it into a list-of-dicts for proper
columnar table display. Adds a "name" column from the dict key when
values don't already contain one.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The seal/unseal subcommands have nothing to do with network policy;
'endpoint-policy' better describes the full scope of the command group
(network isolation + configuration sealing).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a unified --ai-help flag that generates compact markdown help at
three levels (top-level overview, command group, individual command).
Remove the per-command --explain boilerplate from all 40 command files
(-1,407 lines) while keeping the explain text registry that feeds
--ai-help context.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
maximelb and others added 28 commits February 15, 2026 19:59
Previously --sid was required, so the command could only check a single
sensor. Now it lists all online sensor IDs by default, matching user
expectations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Drop the `sensor online` command which only returned bare SIDs,
forcing LLMs to make N individual GET calls per sensor. Instead, add
--online flag (is_online_only server-side filter) and --selector
(bexpr expression) to `sensor list`, so queries like "online Windows
sensors" become a single `sensor list --online --selector 'plat == windows'`.

The --ai-help explain text now documents the full selector syntax
(fields, operators, examples) for LLM discoverability.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Users and LLMs can easily pass millisecond timestamps (13 digits) instead
of seconds (10 digits). This adds a shared validator that rejects values
above 10^12 with a helpful suggestion, and fixes the artifact list
explain text to clarify the unit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Covers thin-wrapper classes (users, groups, keys, billing, outputs),
rule management (D&R, FP, logging, integrity, exfil, YARA), AI generation,
extensions, payloads, jobs, sensor properties, hive, and client properties.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
dr import, hive import, and sync push now exit with the number of
errors (capped at 125) instead of silently returning 0 on partial
failure. hive import also gains per-record error handling so a single
failure no longer aborts the entire import. Configs.push() now returns
backend errors alongside operation results.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds `limacharlie completion <shell>` that outputs a completion script
using Click's built-in shell_completion module. Users can eval the
output in their shell profile for tab-completion of all commands,
subcommands, and options.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tables with many columns (e.g. output list with heterogeneous config
keys) could far exceed terminal width causing line wraps. Now columns
are selected greedily by fill density — sparsest columns are dropped
first — and a footer hints at hidden fields with -W / --output json.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The v2 SDK and CLI are fully independent of the legacy v1 code.
This removes all legacy modules to make a clean break for the 5.0
release.

- Delete 26 legacy PascalCase domain modules (Manager.py, Sensor.py, etc.)
- Delete 6 legacy-only utility files (utils.py, request_utils.py, etc.)
- Rewrite __init__.py to only re-export __version__ from client.py
- Delete 9 legacy unit tests and 8 legacy integration tests
- Update test_user_agent.py to use build_user_agent() directly
- Rename integration test_v2_*.py → test_*.py
- Remove legacy v1 SDK section and migration table from README
- Update CLAUDE.md to reflect single-SDK architecture

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The v2 SDK and CLI are fully independent of the legacy v1 code.
This removes all legacy modules to make a clean break for the 5.0
release.

- Delete 26 legacy PascalCase domain modules (Manager.py, Sensor.py, etc.)
- Delete 6 legacy-only utility files (utils.py, request_utils.py, etc.)
- Rewrite __init__.py to only re-export __version__ from client.py
- Delete 9 legacy unit tests and 8 legacy integration tests
- Update test_user_agent.py to use build_user_agent() directly
- Rename integration test_v2_*.py → test_*.py
- Remove legacy v1 SDK section and migration table from README
- Update CLAUDE.md to reflect single-SDK architecture

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* Add `limacharlie api` raw API command

Adds a generic escape-hatch command (like `gh api`) for making
authenticated HTTP requests to any LimaCharlie API endpoint,
useful for accessing unwrapped endpoints, scripting, and debugging.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix ctx.exit() code propagation in standalone_mode=False

With standalone_mode=False, Click catches Exit exceptions internally and
returns the exit code as a return value. main() was not checking this,
so non-zero exit codes from ctx.exit() were silently lost.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix cloudbuild_pr.yaml: use `--version` flag instead of `version` subcommand

The v2 CLI uses `limacharlie --version` (a Click version flag), not
`limacharlie version` (the old v1 subcommand). The sanity check steps
were still using the old form, causing build failures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix cloudbuild_pr.yaml parallel step race on build/ directory

Test steps and wheel/sdist steps all wrote to /workspace/build/
concurrently, causing intermittent ENOENT failures during wheel
builds. Fix by having test steps copy source to container-local
/tmp/src before pip install, so each step builds in isolation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix integration tests: subscribe required services, fix sync assertion

- Add session-scoped conftest fixture that subscribes the test org to
  required replicant services (integrity, exfil, logging, yara) before
  tests run, and removes only newly-added subscriptions at teardown.
- Fix test_sync assertion: configs.push() returns a tuple, not a list.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Remove replicant-dependent integration tests

Replicant services (integrity, exfil, logging, yara, replay) have been
superseded by Extensions. Remove integration tests that depend on these
services and the conftest fixture that auto-subscribed them.

SDK classes and their unit tests are kept — unit tests mock
service_request so they don't require live replicant subscriptions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Address PR review: form-encoded default, path safety, TTY guard

Addresses all 5 inline review comments from @tomaz-lc:

1. OID path injection (line 211): URL-encode the OID value via
   urllib.parse.quote() when expanding {oid} placeholders.

2. @file path traversal (line 101): New _safe_read_file() resolves
   symlinks via os.path.realpath() and rejects non-regular files.

3. stdin TTY guard (line 100): New _read_stdin() checks sys.stdin.isatty()
   and prints guidance before blocking on terminal input.

4. Content-type override (line 234): New --content-type flag for
   explicit control over --input body content type.

5. Form-encoded body support (line 244): Fields from -f/-F now default
   to form-encoded body (matching LC API conventions). New --json flag
   sends as JSON instead, preserving typed -F coercion.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Add documentation for `limacharlie api` command and `Client.raw_request()`

Document the new raw API escape-hatch command in CLI docs (other-commands.md)
with full usage examples, options table, and exit codes. Add SDK docs for
Client.raw_request() method. Update index tables to include the api command.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: dzimine-lc <dmitri@limacharlie.io>
Investigations are moving to Ticketing, so the dedicated CLI command
group, SDK module, and associated tests are no longer needed.

The `investigation_id` parameter used in tasking and streaming is
unrelated and remains unchanged.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
The AI SDK was sending requests with JSON body (Content-Type:
application/json) but the backend only parses form-encoded bodies
(application/x-www-form-urlencoded). This caused all ai commands
(generate-query, generate-detection, generate-response, etc.) to fail
with '{"error": "query is required"}'. Switch all AI methods from
raw_body/content_type to params for proper form encoding.

Also add "ticketing" as a target alias in the api command, mapping to
https://ticketing.limacharlie.io, and update the --ai-help text and
--target help string to document it.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Use setuptools-scm to derive package version from git tags (no hardcoded
version), and add a GHA workflow that runs unit tests, builds, and publishes
to TestPyPI using Trusted Publishers (OIDC). Will switch to production PyPI
in a follow-up PR.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Update cloudbuild-pr image

* fixing image version
* Fix incorrect location names in org create CLI help

The help text and examples listed locations (us, ca, eu, emea) that
don't exist in the API. Updated to match the actual availableLocs
in lc_api-go: usa, canada, europe, uk, india, australia, auto.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Default org create location to auto

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Expose the existing SDK `InstallationKeys.get(iid)` method as a new
`limacharlie installation-key get --iid <IID>` CLI subcommand so users
can retrieve a single key's data without listing all keys.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
After successfully creating an organization, print the web app URL
(https://app.limacharlie.io/orgs/<oid>) so users can quickly navigate
to manage the new org. Suppressed in --quiet mode.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* Switch from TestPyPi to PyPi

* removing old deployment
* Add `dr convert-rules` CLI command for mass rule conversion

Adds a new CLI command that mass-converts external detection rules
(Sigma, Splunk SPL, Elastic KQL, etc.) to LimaCharlie D&R format
using the AI API and creates them in the dr-general hive. Supports
crawling GitHub repositories or local directories for rule files.

Key features:
- GitHub crawler with intelligent file filtering (Trees API + fallback)
- Local directory crawler with same filtering heuristics
- Parallel AI conversion with configurable worker count
- Live progress display with ETA
- Dry-run mode and YAML file output
- Prefix, tagging, and enabled/disabled control for created rules

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Improve dr convert-rules reliability and UX

- Parse ref and path from full GitHub URLs (e.g.
  --github https://github.com/SigmaHQ/sigma/tree/master/rules/network/cisco
  now auto-extracts ref=master, path=rules/network/cisco)
- Prime JWT before spawning parallel workers to avoid redundant OAuth refreshes
- Add pipeline-level retries with jitter for transient errors (429 rate limits,
  500/502/503 server errors, MCP timeouts) so the thundering-herd effect from
  parallel workers doesn't cause permanent failures
- Bump default parallelism from 5 to 10

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* Add --use flag to org create to set new org as default

When passed, the --use flag automatically sets the newly created
organization as the default OID for subsequent commands, saving
an extra `limacharlie auth use-org` call.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Add --get flag to installation-key create for full key details

When passed, the --get flag automatically fetches the full
installation key details after creation, equivalent to a
follow-up `limacharlie installation-key get --iid <IID>`.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Use OID-less client for org create to avoid stale OID errors

The org create endpoint (orgs/new) doesn't require an org-scoped
JWT. Using oid="-" gets a user-only JWT, preventing auth failures
when the previously saved default org has been deleted.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
CLI commands/ (40 files):
- Remove redundant docstrings from ~197 @group.command() functions that
  duplicated _EXPLAIN_* text. --help now shows clean usage + options;
  --ai-help is unchanged.
- Colocate each _EXPLAIN_* string and register_explain() call with its
  command's # --- section instead of bunching them at the top of the file.

SDK sdk/ (20 files):
- Add missing Returns/Yields sections to all public methods that have
  an Args section (~55 additions).
- Add docstrings to 10 bare methods in organization.py (group and
  extension management).
- Fix HiveRecord.from_raw Returns type annotation.
- Add .claude/docs/sdk-docstring-conventions.md for code review reference.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants