Skip to content

feat: ABsmartly CLI and API client#2

Merged
joalves merged 352 commits into
mainfrom
feat/api-client
Apr 11, 2026
Merged

feat: ABsmartly CLI and API client#2
joalves merged 352 commits into
mainfrom
feat/api-client

Conversation

@joalves
Copy link
Copy Markdown
Collaborator

@joalves joalves commented Mar 24, 2026

Summary

Complete CLI tool and API client for the ABsmartly A/B testing platform.

Core features

  • 200+ API methods covering experiments, metrics, goals, teams, users, segments, events, and admin resources
  • Branded types (ExperimentId, MetricId, etc.) with runtime validation for type-safe API calls
  • Experiment lifecycle — create, update, start, stop, restart, archive with full template support
  • Metric results with CI visualization, effect-based coloring, and segment breakdowns
  • Unix pipe compositionabs experiments list --state running | abs experiments stop | abs experiments archive
  • Action dialog fields — notes use dashboard-configured defaults, required validation, and -i interactive prompts
  • Multiple output formats — table, json (syntax highlighted), yaml, markdown, rendered, vertical, plain
  • Global --raw flag — bypass all summarization and transformations
  • Markdown templates — export/import experiments as markdown, round-trip fidelity
  • Interactive editor — step-by-step experiment creation wizard
  • Activity feed — rendered markdown notes with inline images (iTerm2/Kitty/Sixel)
  • Dynamic CLI options — custom fields from API cache appear as --help flags
  • Keytar + file fallback — OS keychain with automatic fallback and security warnings

Pipe composition

abs experiments list --state running | abs experiments stop --reason other | abs experiments archive
abs experiments list --search e2e- | wc -l
  • List outputs IDs when piped, action commands read stdin and pass IDs through
  • --pass-through forwards failed IDs for downstream retry
  • Per-ID error handling — failures don't abort the chain

Quality

  • 1202 tests passing (vitest), works in both mock (MSW) and live API modes
  • Stateful MSW handlers for realistic test isolation
  • Security: credential directory permissions, masked API keys, keytar write error handling
  • Auto-disables colors when not a TTY (Claude Code, CI, pipes)

Test plan

  • npx vitest run — 1202 passing, 0 failing
  • npx tsc --noEmit — clean
  • Live API: pipe chain list | stop | archive verified
  • Live API: USE_LIVE_API=1 roundtrip and client tests pass
  • Mock mode: stateful MSW handlers, same assertions as live
  • Manual: test abs experiments create -i interactive mode
  • Manual: test abs experiments refresh-fields on fresh profile

Summary by CodeRabbit

  • New Features
    • Full ABSmartly CLI: comprehensive experiment workflows (create/clone/restart/start/stop/archive/bulk/full‑on/development), metrics/results, exports, activity feed, access control, alerts, annotations, follow/unfollow, recommendations, diffing and templating (export/import, generate, round‑trip) with screenshot support and shell completion.
  • Documentation
    • Complete README and MIT licence added.
  • Chores
    • Package manifest, formatting config and VCS/npm ignore files added.

joalves added 30 commits March 12, 2026 21:11
…ompatibility

The parser's section key-value regex can't handle YAML list syntax in
markdown body sections. Moving these to YAML frontmatter ensures
gray-matter parses them as proper arrays, enabling template round-trips.

Also adds comprehensive e2e test covering create -> export -> modify -> re-create.
Also fixes three bugs discovered during e2e testing:
- parser: prevent \s* from matching newlines in key-value pattern, causing YAML list items to be merged into values
- parser: add list parsing for YAML-style list fields in markdown body sections
- builder: gracefully skip screenshot files that cannot be resolved instead of throwing
joalves added 26 commits March 28, 2026 00:03
…t coverage

Security:
- Fix TOCTOU race in keyring credential file writes (mode 0o600)
- Fix SSRF bypass via double-encoded paths in rawRequest
- Validate HTTP methods in rawRequest instead of unsafe cast
- Rename --show-key to --show-full-key with clear warning
- Mask token display in config --detailed to last 4 chars
- Add warning before --as-curl output containing API key
- Set restrictive permissions on cache files

Error handling:
- Add try-catch to getPassword/deletePassword for keytar failures
- Throw on corrupted credentials file instead of silent empty return
- Log warning on screenshot image dimension detection failure
- Add fetch timeout (30s) for screenshot URL resolution
- Log auth errors in avatar fetch instead of silently skipping
- Add 429 rate-limit retry support to axios adapter
- Set process.exitCode=1 on partial failure in experiment commands

Tests:
- Add resolveExperimentId branching tests (7 scenarios)
- Add updateExperiment merge-preserves-fields test
- Add non-idempotent PUT retry exclusion test
- Add 429 retry behavior test
- Add network error (ECONNREFUSED) message test
- Use single scope 'mcp:access' (backend doesn't support space-separated)
- Use page.on('request') to capture OAuth code from redirect URL
- Bind callback server to 'localhost' instead of '127.0.0.1'
Prompts for old and new password instead of using admin reset endpoint.
Uses PUT /auth/current-user with old_password + new_password.
Wraps POST /experiments/estimate/max_participants. Accepts unit type and
applications by name or ID (resolved via listUnitTypes/listApplications),
an optional --from date (defaults to 30d), and an optional --audience JSON
filter. Prints a human-readable participant count summary by default; use
-o json/yaml for the raw columnar response.
- Make --application optional (omit from payload when not provided,
  skip listApplications call entirely)
- Validate --audience JSON client-side with a clear error message
- Fix timestamp display: show field whenever column exists in response,
  use formatTimestampMs(0) -> 'N/A' instead of silent suppression
- Warn explicitly when unit_count column is absent from response
- Warn when API returns multiple rows (only first is shown)
- Improve estimateMaxParticipants response validation: use createAPIError
  with response context, individual checks per field with key diagnostics
- Fix printFormatted mock in tests to use top-level vi.mock factory
- Add tests: no-application, ISO date --from, zero timestamp, missing
  unit_count column, multiple rows warning, invalid audience JSON,
  yaml output branch, exposure timestamp output lines
Adds tests in resources.test.ts following the same pattern as other
resource tests: uses msw handlers in mock mode, hits the real API in
live mode (USE_LIVE_API=1). Covers the happy path with/without
applications, and an error-case test (skipIf live) for invalid
response shape.
…s, screenshot labels, and various improvements

- Add power matrix command to statistics with participant/MDE formatting and table output
- Make group sequential fields conditional on analysis_type instead of always included
- Support markdown image syntax with labels for variant screenshots
- Convert APIError from interface to class with proper constructor
- Consolidate branded type constructors into generic helper
- Add new experiment creation options (MDE, baseline metric stats)
- Improve OAuth token refresh, auth commands, and axios adapter
- Add url utility, oauth-refresh tests, build-from-options tests, and live vitest runner
- Expand test coverage for statistics, metrics, units, parser, serializer, and builder
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.

1 participant