Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
112 commits
Select commit Hold shift + click to select a range
b2fcc34
Add CLI & SDK v2.0.0 - complete rewrite with Click framework
maximelb Feb 11, 2026
7aad8ad
Fix critical SDK bugs: align v2 with v1 API patterns
maximelb Feb 11, 2026
a316a1a
Fix SDK bugs, add OAuth CLI login, rewrite README
maximelb Feb 12, 2026
7264a72
Fix SDK bugs and add comprehensive CLI integration tests
maximelb Feb 12, 2026
3eba7a7
Migrate D&R rules and FP rules from legacy REST API to Hive API
maximelb Feb 12, 2026
4e98a70
Fix critical bugs found during PR review
maximelb Feb 12, 2026
6b85a82
Add CLI account signup via OAuth
maximelb Feb 12, 2026
e46c70f
Add CLI commands to download sensor installers and adapter binaries
maximelb Feb 12, 2026
1d18ce2
Add type annotations, dataclasses, and migrate to pyproject.toml
maximelb Feb 12, 2026
7b7661b
Fix code review issues: consistent annotations, unused imports, compat
maximelb Feb 12, 2026
65d5d19
Bump version from 2.0.0 to 5.0.0 for PyPI release
maximelb Feb 12, 2026
d9dbd33
Fix SDK API mismatches found by auditing against Go backend
maximelb Feb 12, 2026
b1b4fa7
Fix stale --id references in investigation docs and explain texts
maximelb Feb 12, 2026
abaf3c4
Add comprehensive HTTP contract tests for all SDK methods
maximelb Feb 13, 2026
7d5ec5b
Fix SDK bugs and integration tests found by live API testing
maximelb Feb 13, 2026
2eb438b
Add --wide and --filter global CLI flags, smart table truncation
maximelb Feb 13, 2026
28cd509
Auth check tweak
maximelb Feb 13, 2026
162f950
Add comprehensive CLI and output helper test coverage
maximelb Feb 13, 2026
30c7260
Sync: use ext-infrastructure only, replace legacy rules/fps with hives
maximelb Feb 13, 2026
9f74f48
Detect missing OID early with actionable error instead of confusing "…
maximelb Feb 15, 2026
84b86e3
Fix OAuth auth shadowed by stale API key in CLI commands
maximelb Feb 15, 2026
c1dd28e
Clarify adapter command as "external adapter" and improve hive shortc…
maximelb Feb 15, 2026
93ee9af
Fix test_creates_with_jwt leaking real config credentials
maximelb Feb 15, 2026
6f67725
Rename 'adapter' command to 'ext-adapter' to avoid confusion with clo…
maximelb Feb 15, 2026
d592778
Rename adapter commands to 'external-adapter' and 'cloud-adapter'
maximelb Feb 15, 2026
26d0c48
Update README with renamed adapter commands
maximelb Feb 15, 2026
f014ac9
Unwrap useless API wrapper keys in SDK responses
maximelb Feb 15, 2026
3caf73f
Render dict-of-dicts as columnar tables instead of key/JSON pairs
maximelb Feb 15, 2026
57bf3a3
Rename 'net-policy' command to 'endpoint-policy'
maximelb Feb 15, 2026
f159637
Replace --explain with --ai-help for LLM-friendly CLI discoverability
maximelb Feb 15, 2026
cfbc037
Enrich --ai-help explain texts with data structures and examples
maximelb Feb 15, 2026
e9f8c7e
Add rich --ai-help docs to hive shortcut commands
maximelb Feb 15, 2026
d7c7250
Fix task request: broken Spout auth, race condition, stdout pollution…
maximelb Feb 16, 2026
955d0e3
Fix OAuth token never persisted after refresh
maximelb Feb 16, 2026
b81c836
Allow global CLI options to appear anywhere on the command line
maximelb Feb 16, 2026
1d9e58d
Fix use-org positional arg, collision-aware option hoisting, and READ…
maximelb Feb 16, 2026
6e97ac9
Make `sensor online` list all online sensors when --sid is omitted
maximelb Feb 16, 2026
d503a74
Replace `sensor online` with --online and --selector on `sensor list`
maximelb Feb 16, 2026
73ea019
Remove arml from arch values in sensor list help text
maximelb Feb 16, 2026
48fb96c
Add epoch-seconds validation to catch millisecond timestamps in CLI
maximelb Feb 17, 2026
9b78abc
Lots of cleanup.
maximelb Feb 18, 2026
23a61fa
Add docstrings to all public SDK classes, methods, and properties
maximelb Feb 19, 2026
35dcee6
Pin all runtime dependencies to exact versions
maximelb Feb 19, 2026
2c615cc
Propagate error counts as exit codes in batch commands
maximelb Feb 19, 2026
1c24901
Add shell completion command (bash, zsh, fish)
maximelb Feb 19, 2026
74a76ba
Fit table output to terminal width by dropping sparse columns
maximelb Feb 19, 2026
5ef6438
Remove legacy v1 SDK code, tests, and documentation
dzimine-lc Feb 20, 2026
633acde
Revert "Remove legacy v1 SDK code, tests, and documentation"
dzimine-lc Feb 20, 2026
0adde35
Remove legacy v1 SDK code, tests, and documentation (#208)
dzimine-lc Feb 23, 2026
3c49996
Move user-facing docs from README into doc/ folder (#209)
dzimine-lc Feb 23, 2026
8556e4b
Add `limacharlie api` raw API command (#211)
maximelb Feb 24, 2026
807a157
Remove `limacharlie investigation` CLI command (#212)
maximelb Feb 24, 2026
bdf9b72
Fix AI SDK form encoding and add ticketing target alias (#213)
maximelb Feb 25, 2026
46fd304
Add automated PyPI publishing via GitHub Actions
dzimine-lc Feb 25, 2026
4ba360d
Revert "Add automated PyPI publishing via GitHub Actions"
dzimine-lc Feb 25, 2026
b9a4b25
Update cloudbuild-pr image (#215)
dzimine-lc Feb 25, 2026
d8ba82c
Fix incorrect location names in org create CLI help (#216)
maximelb Feb 26, 2026
cebcfe6
Add `installation-key get` CLI command (#217)
maximelb Feb 26, 2026
27abf81
Bump version to 5.0.1 for release (#218)
maximelb Feb 26, 2026
4289fd9
Show web app URL after org create (#219)
maximelb Feb 26, 2026
9085cdf
Add PyPI publishing via GitHub Actions (TestPyPI for now) (#214)
dzimine-lc Feb 26, 2026
72403fa
Switch from TestPyPi to PyPi (#221)
dzimine-lc Feb 26, 2026
066c594
Add dr convert-rules CLI command for mass rule conversion (#220)
maximelb Feb 26, 2026
7b05206
Add --use flag to org create (#223)
maximelb Feb 27, 2026
d199248
Clean up CLI docstrings and standardize SDK documentation (#225)
dzimine-lc Feb 27, 2026
71e0ac2
Fix incorrect LCQL syntax in search help, examples, and tests
maximelb Mar 3, 2026
a2b6774
feat: Add AI session creation via ai_agent Hive definitions (#229)
maximelb Mar 4, 2026
a67175b
Add ticket CLI commands for SOC ticket management (#224)
maximelb Mar 4, 2026
a294488
Add --sid filter to ticket list for cross-detection sensor search (#230)
maximelb Mar 5, 2026
89c0628
Add enable/disable commands for Hive records (#231)
maximelb Mar 5, 2026
75edfb5
Fix enable/disable to preserve existing metadata (#232)
maximelb Mar 5, 2026
a632da1
Fix help topic fallthrough, whoami output, and sync debug logging (#233)
maximelb Mar 5, 2026
f4af318
Fix org list to auto-paginate and return all results (#234)
maximelb Mar 5, 2026
4b9a646
Support full detection object in ticket create and detection add (#235)
maximelb Mar 6, 2026
a9d5144
fix: Don't send null data in metadata-only hive set requests (#236)
maximelb Mar 6, 2026
437df80
Add --data option to ai start-session command (#238)
maximelb Mar 7, 2026
b3166ea
Add --check-perm and --show-perms flags to auth whoami (#239)
maximelb Mar 7, 2026
85d757a
fix: auth whoami without OID falls back to "-" instead of erroring (#…
maximelb Mar 10, 2026
456e859
Rename ticket to case in SDK and CLI (#241)
maximelb Mar 10, 2026
ae48eee
fix: Follow pagination tokens in search SDK to return all result page…
maximelb Mar 11, 2026
7d3b5ee
fix: Update ext-ticketing references to ext-cases (#243)
maximelb Mar 11, 2026
52f4e8f
fix: Clarify key vs json_key in installation key help for AI guidance…
maximelb Mar 12, 2026
a075340
feat: Add AI session lifecycle management and usage tracking (#245)
maximelb Mar 13, 2026
b246742
feat: Add info severity level to cases CLI and SDK (#246)
maximelb Mar 13, 2026
2492108
feat: default search token expiry to 4 hours with config override (#248)
tomaz-lc Mar 13, 2026
91a9b31
feat: include query_id, region, oid in search error messages (#247)
tomaz-lc Mar 13, 2026
dc25653
feat: unwrap search results for human-readable table output (#250)
tomaz-lc Mar 13, 2026
651aaab
feat: add severity to case update and update field documentation (#252)
maximelb Mar 14, 2026
ba7ff7e
feat: On-disk JWT caching for CLI (#251)
tomaz-lc Mar 15, 2026
30a4e2c
fix: enable --debug for all CLI commands with enhanced debug output (…
tomaz-lc Mar 16, 2026
158bd63
feat: search poll retry with exponential backoff and checkpoint/resum…
tomaz-lc Mar 17, 2026
801e04a
Add Cases class and CLI commands to documentation index (#255)
maximelb Mar 17, 2026
6d93a72
feat: streaming output, orjson, and memory-efficient search rendering…
tomaz-lc Mar 18, 2026
8b959dc
chore: set 5.1.0 release date to March 18, 2026 (#256)
tomaz-lc Mar 18, 2026
605eff4
feat: add summary parameter to case create (#262)
maximelb Mar 19, 2026
1ab2967
fix: match help topic names to actual CLI command names (#263)
maximelb Mar 19, 2026
9b13e4a
feat: consolidate config files into ~/.limacharlie.d/ directory (#257)
tomaz-lc Mar 20, 2026
df70bd2
docs: add shell completion setup instructions to README (#260)
tomaz-lc Mar 20, 2026
8331fe7
feat: lazy command loading for faster CLI startup (#261)
tomaz-lc Mar 20, 2026
ba52201
docs: add 5.2.0 changelog (#264)
tomaz-lc Mar 20, 2026
3def0e7
fix: register config command in lazy loading map and add CI workflow …
tomaz-lc Mar 20, 2026
35a6c43
fix: Use correct backend hive name 'org_notes' for note commands (#266)
maximelb Mar 21, 2026
f6aeb40
feat: add ui_actions field to HiveRecord (#267)
maximelb Mar 28, 2026
18bc67c
feat: update cases SDK/CLI for ext-cases data model changes (#268)
maximelb Mar 28, 2026
1057f21
fix: require OID when using --check-perm in auth whoami (#269)
maximelb Mar 29, 2026
1c9bba6
Make --summary required for case create CLI command (#270)
maximelb Mar 29, 2026
038ff32
Fix cases encoding. (#271)
maximelb Mar 30, 2026
9365005
fix: stop double-encoding detection in case create (#272)
maximelb Mar 30, 2026
f4c6ec2
Use org URL for cases API root instead of hardcoded default (#273)
maximelb Mar 30, 2026
604b819
fix: cases CLI/SDK alignment with ext-cases backend (#274)
maximelb Apr 3, 2026
93f864d
feat: add feedback CLI commands for ext-feedback (#275)
maximelb Apr 11, 2026
262e362
fix: send _content params as dicts instead of JSON strings in ext-fee…
maximelb Apr 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file removed .DS_Store
Binary file not shown.
105 changes: 105 additions & 0 deletions .claude/docs/sdk-docstring-conventions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# SDK Docstring Conventions

Rules for docstrings in `limacharlie/sdk/`. Use this as a checklist during code review.

## Format

Google style. Every public method and class must have a docstring.

## Required Sections

| Section | When required |
|---------|--------------|
| Summary line | Always |
| `Args:` | Method takes parameters (excluding `self`) |
| `Returns:` | Method returns a value (not `None`) |
| `Yields:` | Method is a generator (uses `yield`) — use *instead of* `Returns:` |
| `Raises:` | Method raises an exception that callers should handle (auth errors, validation, not-found, etc.) |

## Style Rules

1. **Summary line**: imperative mood, one sentence, no trailing period when single line.
2. **Args**: one line per param — `name: Description.` (sentence case, ends with period).
3. **Returns / Yields**: `type: Description.` Keep it brief; mention key fields for dicts.
4. **Raises**: `ExceptionType: When it is raised.`
5. **Blank line** between summary and first section, and between sections.
6. **Type info in signatures, not docstrings** — the codebase uses type annotations; don't duplicate types in `Args:` descriptions.
7. **No `Returns:` for trivial wrappers** that clearly return "API response dict" — a one-liner docstring like `"""List all X."""` is fine if the return type annotation is `dict[str, Any]` and there is nothing surprising in the response shape.

## Canonical Examples

### Standard CRUD method

```python
def create(self, name: str, description: str = "") -> dict[str, Any]:
"""Create a new resource.

Args:
name: Human-readable name.
description: Optional long description.

Returns:
dict: API response containing the created resource.
"""
```

### Method that returns None

```python
def delete(self, name: str) -> None:
"""Delete a resource by name.

Args:
name: Resource name.
"""
```

### Generator

```python
def get_events(self, start: int, end: int) -> Generator[dict[str, Any], None, None]:
"""Get historical events for this sensor.

Args:
start: Start time (unix seconds).
end: End time (unix seconds).

Yields:
dict: Event records with ``routing`` and ``event`` keys.
"""
```

### Method that raises

```python
def download_binary(kind: str, platform: str, arch: str) -> bytes:
"""Download a sensor installer or adapter binary.

Args:
kind: ``'sensor'`` or ``'adapter'``.
platform: Platform name (e.g. ``'linux'``, ``'windows'``).
arch: Architecture (e.g. ``'64'``, ``'arm64'``).

Returns:
bytes: Raw binary content.

Raises:
ValueError: If the (platform, arch) combination is not valid.
RuntimeError: If the download fails.
"""
```

### Simple one-liner (acceptable for trivial getters)

```python
def get_info(self) -> dict[str, Any]:
"""Get organization details."""
```

## Anti-patterns

- Duplicating type annotations inside `Args:` descriptions (e.g., `name (str): ...`).
- Writing `Returns: dict` without saying what's in it when the shape is non-obvious.
- Using `Returns:` on a generator — use `Yields:` instead.
- Omitting `Args:` when the method has parameters beyond `self`.
- Adding docstrings to private methods (`_foo`) — not required.
47 changes: 47 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: CI

on:
push:
branches:
- master
- cli-v2
pull_request:
branches:
- master
- cli-v2

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

jobs:
test:
name: Unit tests (Python ${{ matrix.python-version }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false
fetch-depth: 0
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v6
with:
python-version: "${{ matrix.python-version }}"
allow-prereleases: true
- name: Install dependencies
run: |
pip install --upgrade pip
pip install ".[dev]"
# Python 3.9 needs tomli for pyproject.toml parsing in tests
if python -c "import sys; sys.exit(0 if sys.version_info < (3, 11) else 1)"; then
pip install "tomli>=1.0"
fi
- name: Run unit tests and microbenchmarks (correctness only)
run: pytest tests/unit/ tests/microbenchmarks/ --benchmark-disable -v --reruns 2 --reruns-delay 5
81 changes: 81 additions & 0 deletions .github/workflows/publish-to-pypi.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
name: Publish to PyPI

on:
push:
tags:
- "[0-9]+.[0-9]+.[0-9]+"

permissions:
contents: read

jobs:
test:
name: Unit tests (Python ${{ matrix.python-version }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false
fetch-depth: 0
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v6
with:
python-version: "${{ matrix.python-version }}"
allow-prereleases: true
- name: Install dependencies
run: |
pip install --upgrade pip
pip install ".[dev]"
# Python 3.9 needs tomli for pyproject.toml parsing in tests
if python -c "import sys; sys.exit(0 if sys.version_info < (3, 11) else 1)"; then
pip install "tomli>=1.0"
fi
- name: Run unit tests and microbenchmarks (correctness only)
run: pytest tests/unit/ tests/microbenchmarks/ --benchmark-disable -v --reruns 2 --reruns-delay 5

build:
name: Build distribution packages
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.11"
- name: Install build
run: pip install build
- name: Build sdist and wheel
run: python -m build
- name: Upload distributions
uses: actions/upload-artifact@v7
with:
name: python-package-distributions
path: dist/

publish:
name: Publish to PyPI
needs: build
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/p/limacharlie
permissions:
id-token: write
attestations: write
contents: read
steps:
- name: Download distributions
uses: actions/download-artifact@v8
with:
name: python-package-distributions
path: dist/
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,6 @@ ENV/

# mypy
.mypy_cache/

# setuptools-scm generated version file
limacharlie/_version.py
Loading