# API Reference

Top-level modules that survived the 2026-05 restructure. Removed `scitex_dev.{skills,fix,ci,deploy,versions,docs,search,_discovery,_manifest,_builder}` were absorbed into `_cli/`, `_creds/`, `_ecosystem/`, etc. — see the CLI surface and per-subcommand entry points for the live API.

## CLI entry point

Backward-compat shim — re-exports from scitex_dev._dispatch.

The reusable docs/skills CLI mixins moved to scitex_dev._dispatch in 0.11.0. This shim keeps from scitex_dev.cli import … working for downstream packages (figrecipe, scitex-io, scitex-app, etc.) until they migrate. Will be removed in 0.12.0.

scitex_dev.cli.docs_click_group(package: str, name: str = 'docs')

  Create a Click command group for docs (requires Click installed).

  Usage::

    from scitex_dev.cli import docs_click_group cli.add_command(docs_click_group(package=”scitex-writer”))

scitex_dev.cli.register_docs_subcommand(subparsers: _SubParsersAction, package: str) → ArgumentParser

  Register `docs` with `list` and `get` verb subcommands.

  Usage::

    scitex-stats docs list # List doc pages scitex-stats docs get # Show available pages scitex-stats docs get api # Show specific page

scitex_dev.cli.register_skills_subcommand(subparsers: _SubParsersAction, package: str) → ArgumentParser

  Register `skills` with `list` and `get` verb subcommands.

  Usage::

    scitex-stats skills list # List skill pages scitex-stats skills get # Show main SKILL.md scitex-stats skills get test-selection # Show a reference page

scitex_dev.cli.skills_click_group(package: str, name: str = 'skills')

  Create a Click command group for skills (requires Click installed).

  Usage::

    from scitex_dev.cli import skills_click_group cli.add_command(skills_click_group(package=”scitex-app”))

## CLI subcommand groups

SciTeX-dev CLI package — entry point + reusable subcommand mixins.

Module map: - _root — top-level Click group main (the scitex-dev console script entry point) - _utils — handle_result, run_as_cli, wrap_as_cli, json/dry-run option helpers - _completion — shell tab-completion installer - _doctor — scitex-dev doctor - _stats — scitex-dev ecosystem stats - audit/ — _summary (was _cli_audit), _api, _project, _skills - ecosystem/ — _registry (was _cli_ecosystem) - quality/ — _check (was _cli_quality), _frontmatter - skills/ — _manage (was _cli_skills), _tags

The main callable is the [project.scripts] target — scitex_dev._cli:main must remain importable.

scitex_dev._cli.add_dry_run_argument(parser: Any) → None

  Add `--dry-run` flag to an argparse parser.

scitex_dev._cli.add_json_argument(parser: Any) → None

  Add `--json` flag to an argparse parser.

scitex_dev._cli.dry_run_option(fn: Callable) → Callable

  Click decorator: adds `--dry-run` flag.

  Uses lazy `import click` so scitex-dev stays stdlib-only.

scitex_dev._cli.handle_result(result: Result, as_json: bool = False, file: Any = None) → int

  Format and print a Result, return the exit code.

  Parameters:

    - result (Result) – The structured result to display.

    - as_json (bool) – If True, output full JSON. If False, human-friendly text.

    - file (file-like | None) – Output stream. Defaults to stdout/stderr based on success.

  Returns:

    Exit code suitable for `sys.exit()`.

  Return type:

    int

scitex_dev._cli.json_option(fn: Callable) → Callable

  Click decorator: adds `--json` flag as `as_json` parameter.

  Uses lazy `import click` so scitex-dev stays stdlib-only.

scitex_dev._cli.run_as_cli(fn: Callable, as_json: bool = False, **kwargs: Any) → None

  Call a `@supports_return_as` function and exit with proper code.

  Parameters:

    - fn (Callable) – A function decorated with `@supports_return_as`.

    - as_json (bool) – If True, output full JSON.

    - **kwargs – Arguments to pass to `fn`.

scitex_dev._cli.wrap_as_cli(fn: Callable, as_json: bool = False, **kwargs: Any) → None

  Call any function and display its result via CLI.

  Like `wrap_as_mcp` but for terminal output. Wraps any plain function in Result, formats based on `as_json`, and exits with proper exit code.

  Parameters:

    - fn (Callable) – Any callable returning data or raising exceptions.

    - as_json (bool) – If True, output full JSON Result. If False, human-friendly text.

    - **kwargs – Arguments to pass to `fn`.

## Core

Core glue: config, types, errors, dispatch, discovery, manifests.

## Ecosystem

SciTeX ecosystem registry, dependency graph, and package-state utilities.

Module map: - _core — ECOSYSTEM registry + get_all_packages / get_local_path - _graph — pyproject dependency graph (discover, parse, mermaid/dot, cycles) - _packages — multi-host package SHA collection + audit/sync helpers

scitex_dev._ecosystem.get_all_packages() → List[str]

  Get list of all ecosystem package names.

scitex_dev._ecosystem.get_local_path(package: str) → Path | None

  Get expanded local path for a package.

scitex_dev._ecosystem.should_skip_audit(package: str, auditor: str) → tuple[bool, str]

  Return (skip, reason) for running auditor on package.

  auditor is one of the keys in _CATEGORY_SKIP. Unknown auditors return (False, “”) — fail open so a typo doesn’t silently skip.

  Skip semantics:

  - archived packages are skipped for every auditor.

  - per-auditor categories listed in _CATEGORY_SKIP are skipped.

  - unknown package (not in ECOSYSTEM) is NOT skipped — the auditor’s own not-found path will handle it.

## Credentials

Ecosystem-wide Claude Code credential rotation.

Multiplexes `~/.claude/.credentials.json` to the GitHub Actions secret slot `CLAUDE_CODE_CREDENTIALS_JSON` (with sha256 sidecar variable `CLAUDE_CODE_CREDENTIALS_JSON_SHA256`) across every package in the SciTeX ecosystem registry.

Distinct from the single-repo `sac dev upload-credentials-to-github` command — that one writes the package-prefixed `SAC_…` slot. This module uses the canonical un-prefixed name shared by every scitex package that consumes Claude Code OAuth.

class scitex_dev._creds.RotateResult(package: str, repo: str | None, status: str, message: str = '')

  Per-repo rotation outcome.

  is_error() → bool
  message: str = ''
  package: str
  repo: str | None
  status: str

scitex_dev._creds.rotate_all(*, packages: Iterable[str] | None = None, only: Iterable[str] | None = None, exclude: Iterable[str] | None = None, source_path: Path = PosixPath('/home/runner/.claude/.credentials.json'), dry_run: bool = False, force: bool = False, ecosystem: dict | None = None, local_path_lookup=None) → list[RotateResult]

  Rotate the credential across every (or a filtered set of) repo.

  Returns one `RotateResult` per package processed. Returns an empty list if the source is silently absent/expired — that is the “fresh laptop / expired token” exit-0 path, deliberately quiet.

scitex_dev._creds.validate_source(path: Path = PosixPath('/home/runner/.claude/.credentials.json'), *, now_ms: Callable[[], int]=<function _now_ms>) → SourceState | None

  Return SourceState, or None if rotation should be a silent no-op.

  Silent-no-op (returns None) is reserved for the operator-on-a-fresh- -laptop / expired-token cases that should NOT spam every hour:

  - source file is missing

  - `claudeAiOauth.expiresAt` (or `expires_at`) is in the past

  Raises `ValueError` for cases that DO deserve a loud error:

  - file present but doesn’t parse as JSON

  - file parses but has no `claudeAiOauth` key

## Docs (search / index helpers)

Docs build, search, and skills aggregation utilities.

## Branding

Ecosystem branding / translation registry.

Single source of truth for SciTeX-ecosystem brand identities (pypi name, import name, umbrella attr, alias, display, method-prefix, env-prefix). See `registry.yaml` for entries and `BRANDING_TRANSLATION_REGISTRY_PLAN.md` for design rationale.

Runtime API (minimal — only what figrecipe + socialia need):

    get(brand_key, field)               -> str
    translate(name, *, from_brand, to_brand) -> str
    register_method_aliases(cls, *, brand_key) -> None
    get_env(key, *, brand_key, default=None) -> str | None

Plus low-level helpers used by the auditor:

    get_brand(brand_key) -> Brand
    iter_brands() -> Iterator[tuple[str, Brand]]

class scitex_dev._branding.Brand
  alias: str
  display: str
  env_prefix: str
  import_: str
  method_prefix: str
  native_brand: str
  pypi: str
  umbrella_attr: str
  umbrella_brand: str

scitex_dev._branding.get(brand_key: str, field: str) → Any

  Look up a single field. No fallbacks — registry is authoritative.

scitex_dev._branding.get_brand(brand_key: str) → Brand

  Whole entry for one brand. Raises KeyError if unknown.

scitex_dev._branding.get_env(key: str, *, brand_key: str, default: str | None = None) → str | None

  Read an environment variable using the brand’s declared env_prefix, with a fallback to the counterpart brand’s prefix (for white-label rebrands), then the unprefixed name, then default.

  Lookup order:

    1. `<this brand env_prefix>_<key>`

    2. `<counterpart env_prefix>_<key>` (if a counterpart exists)

    3. `<key>` (unprefixed)

    4. `default`

scitex_dev._branding.iter_brands() → Iterator[tuple[str, Brand]]

  Iterate (brand_key, entry). For audit rules.

scitex_dev._branding.register_method_aliases(cls, *, brand_key: str) → None

  Walk `dir(cls)` and bind the counterpart-brand’s prefix as aliases.

  For each method starting with `<this brand>.method_prefix`, bind an attribute named with the counterpart’s method_prefix that points at the same function. The alias gets `__module__` rebound to the counterpart’s import path so `help()` on the umbrella side doesn’t leak the native package name.

  No-op if the brand has no counterpart or no method_prefix.

scitex_dev._branding.translate(name: str, *, from_brand: str, to_brand: str) → str

  Layer-5 only — swap one brand’s method_prefix for the counterpart’s.

  Raises ValueError if from_brand/to_brand are not declared as native/umbrella counterparts in the registry.

      >>> translate("fr_conf_mat", from_brand="figrecipe", to_brand="scitex-plt")
      'stx_conf_mat'

## Release

Release-related utilities (CI, deploy, version bumpers, lint gates, RTD onboarding).

## Testing helpers

Pytest helpers for downstream SciTeX packages.

Public re-exports: - audit_all_for_package — assert audit-all <pkg> exits 0.

Each ecosystem package drops a one-liner test that calls this helper so the package’s local pytest run includes the same audit gates that CI used to run as a separate workflow. See the auto-generated tests/test_audit.py template (via scitex-dev ecosystem write-audit-test <pkg>) and the skill leaf _skills/general/02_package/07_github-actions.md for the canonical shape.

scitex_dev.testing.audit_all_for_package(distribution: str, *, timeout: float = 120.0, skip_rules: tuple[str, ...] = ()) → None

  Run scitex-dev ecosystem audit-all <distribution> and assert exit 0.

  Parameters:

    - distribution – ECOSYSTEM key (e.g. `"scitex-io"`, `"scitex-stats"`, `"socialia"`).

    - timeout – Per-test wall-clock cap; covers a slow PyPI install in CI.

    - Bypass

    - ------

    - the (audit (the test calls pytest.skip instead of running)

    - the

    - pre-existing (subprocess). Use during a remediation push when)

    - runs (violations would block unrelated test)

    - developing (or when)

    - for (locally without scitex-dev's audit corpus available. CI)

    - silent. (release branches MUST NOT set this — drift goes)

  Raises:

    AssertionError – If the subprocess returns non-zero. The full stdout + stderr are included in the message so the failing rule is visible in the test report without re-running the audit by hand.

## Linter

SciTeX Linter — enforce reproducible research patterns via AST analysis.

scitex_dev.linter.list_rules(category: str = None) → list

  Return all rules (built-in + plugin), optionally filtered by category.

  Parameters:

    category (str, optional) – If provided, only return rules whose category matches this value.

  Returns:

    All matching Rule objects from built-in definitions and loaded plugins.

  Return type:

    list of Rule

## MCP server

scitex-dev’s OWN FastMCP server.

The MCP helper utilities (wrap_as_mcp, register_docs_tools, get_tools_sync, …) used to live here but are now ecosystem-glue under scitex_dev._ecosystem._mcp and re-exported as the public scitex_dev.ecosystem surface. This package retains only the _server module that hosts scitex-dev’s own MCP tools.

## Dashboard

Flask dashboard for scitex version management.

scitex_dev.dashboard.create_app() → Flask

  Create and configure the Flask application.

  Returns:

    Configured Flask application.

  Return type:

    Flask

scitex_dev.dashboard.run_dashboard(host: str = '0.0.0.0', port: int = 5000, debug: bool = False, open_browser: bool = True, force: bool = False) → None

  Run the Flask dashboard server.

  Parameters:

    - host (str) – Host to bind to. Default “127.0.0.1”.

    - port (int) – Port to listen on. Default 5000.

    - debug (bool) – Enable Flask debug mode.

    - open_browser (bool) – Open browser automatically.

    - force (bool) – Kill existing process using the port if any.