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')[source]

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[source]

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[source]

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')[source]

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) - _utilshandle_result, run_as_cli, wrap_as_cli, json/dry-run option helpers - _completion — shell tab-completion installer - _doctorscitex-dev doctor - _statsscitex-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[source]

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

scitex_dev._cli.add_json_argument(parser: Any) None[source]

Add --json flag to an argparse parser.

scitex_dev._cli.dry_run_option(fn: Callable) Callable[source]

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[source]

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[source]

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[source]

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[source]

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: - _coreECOSYSTEM 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][source]

Get list of all ecosystem package names.

scitex_dev._ecosystem.get_local_path(package: str) Path | None[source]

Get expanded local path for a package.

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

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 = '')[source]

Per-repo rotation outcome.

is_error() bool[source]
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/docs/.claude/.credentials.json'), dry_run: bool = False, force: bool = False, ecosystem: dict | None = None, local_path_lookup=None) list[RotateResult][source]

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/docs/.claude/.credentials.json'), *, now_ms: Callable[[], int]=<function _now_ms>) SourceState | None[source]

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[source]
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[source]

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

scitex_dev._branding.get_brand(brand_key: str) Brand[source]

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[source]

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]][source]

Iterate (brand_key, entry). For audit rules.

scitex_dev._branding.register_method_aliases(cls, *, brand_key: str) None[source]

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[source]

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[source]

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[source]

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[source]

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[source]

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.