Skip to main content

clikit

Стандартная библиотека построения CLI поверх s-librarykit. Новый CLI собирается за ~10 строк: единый root-app с --json/--text/--profile/--version, 4-слойный конфиг с валидацией, JSON-first вывод для агентов и скриптов, структурированные команды. Сетевой слой — транспорт, retry, секреты, пути — это зона КОРНЯ librarykit; clikit на нём построен и тянет его как зависимость, но больше НЕ фасадит (строгие зоны). Единая иерархия ошибок (errors) — общий контракт между слоями.

librarykit   ← КОРЕНЬ: errors · retry · transport · sessions · paths · config_util
   ▲
clikit       ← ЭТОТ КИТ: command_kit · config · output · scaffold + errors.
                        transport/retry/session/paths — бери из librarykit напрямую.

Установка

uv add s-clikit

Имя дистрибутива — s-clikit, имя для импорта — clikit. librarykit подтянется автоматически как зависимость.

Быстрый старт

CLI за 10 строк — build_root_app даёт root с флагами --json/--text/--profile/--version:

from clikit import build_root_app, command, AppConfig, emit_data
from librarykit.transport import RestHttpClient  # транспорт — зона librarykit

app = build_root_app(brand="acme", help="ACME CLI")

@app.command()
@command
def items():
    cfg = AppConfig.load("acme")
    client = RestHttpClient(cfg.base_url, access_token=...)
    emit_data(..., text_renderer=...)

Запуск: acme items отдаёт машинный JSON; acme items --text — человеко-читаемый вывод. Скаффолд нового проекта: clikit new <name> (см. clikit.scaffold).

Навык — зона не этого кита

Скаффолд clikit new генерит ТОЛЬКО CLI-пакет. SKILL.md, _skill_meta.toml, install/ и остальную форму навыка Skillery держит skillkit.canon — кит, который этот формат читает и ставит, он же его и пишет. Раньше копия канона жила и здесь, и расходилась: плоская раскладка вместо src/<pkg>/ + skills/<slug>/, kind = "cli" (такого рода не существует), ни install/, ни tests/ — навык не проходил validate_canonical_skill.

Собрать навык: skillery new <slug> --kind tooling либо skillkit.canon.render_* напрямую. Подробности и путь миграции — docs/SKILL_PROJECT.md, обоснование — ADR-0001 кита skillkit.

JSON по умолчанию

Дефолтный режим вывода — json (для AI-агентов и скриптинга): без флагов команда печатает машинный JSON Lines в stdout. Человек переключается в текст:

  • флагом --text / --plain;
  • env {BRAND}_OUTPUT=text;
  • в config.tomloutput_format = "text".

--json форсит json (перебивает --text, если переданы оба).

Слои конфига: global + project + local

AppConfig.load(brand) собирает значения по слоям (низ→верх приоритета), per-key мерж (верхний слой переопределяет только заданные ключи, не заменяет объект целиком):

defaults(модель) < global(config_dir/config.toml)
    < project(.<brand>.toml | .<brand>/config.toml — найден ВВЕРХ от cwd до .git)
    < local(*.local.toml рядом с project, gitignored)
    < ENV({BRAND}_<FIELD>) < init-kwargs
  • project-discovery: подъём от cwd до маркера .git; ищется .<brand>.toml в корне ИЛИ .<brand>/config.toml — «конфиг рядом с проектом».
  • local-оверрайд: .<brand>.local.toml — приватные правки поверх командного конфига (в .gitignore).
  • Профили (--profile / {BRAND}_PROFILEprofiles/<p>/) — на уровне global. Активный профиль разрешает clikit.config.active_profile(brand): сперва контекст исполнения (ExecutionContext), затем env. Корневой callback env не пишет — профиль едет объектом (см. «Контекст исполнения»).

AppConfig построен на pydantic-settings (типизация + fail-fast валидация). Пути по ОС (librarykit.config_util.AppPaths) — на platformdirs (%APPDATA% / ~/Library / ~/.config), ENV-override {BRAND}_HOME.

env-интерполяция секретов

Строковые значения резолвятся из окружения при load (секрет не лежит в git):

api_token = "${ACME_TOKEN}"                        # из env ACME_TOKEN
base_url  = "${ACME_HOST:-http://localhost:8000}"  # с дефолтом

Поддержаны ${VAR} и ${VAR:-default}. Подстановка команд $(...) не поддержана (поверхность атаки). Заряжать env можно load_dotenv_file или keyring (librarykit.secret_store.SecretStore).

MCP-секция

AppConfig.mcp: dict[str, McpServer] — единая форма манифеста MCP-сервера (transport/command/args/env/url/headers/enabled):

[mcp.skills-hub]
transport = "stdio"
command = "skills-hub-mcp"
args = ["--stdio"]
env = { TOKEN = "${SH_TOKEN}" }

$schema для редактора

AppConfig.json_schema() отдаёт JSON Schema модели. Команда для CLI — make_schema_command(MyConfig):

from clikit import make_schema_command, AppConfig
app.command(name="schema")(make_schema_command(MyConfig))   # `acme schema` печатает схему

Контекст исполнения (ExecutionContext)

Контекст запуска — ЯВНЫЙ объект в ContextVar, а не процессное окружение. Корневой callback собирает его один раз (единственное место чтения env) и ставит на всё исполнение команды:

from clikit import build_root_app, current_context

app = build_root_app("acme", redact_output=True)   # + флаг --unsafe-show-secrets

@app.command()
def whoami():
    ctx = current_context()          # profile / tenant / home_dir / proxy /
    ...                              # output_mode / reveal_secrets / trace_id

Зачем: os.environ — процессный носитель, поэтому два тенанта в одном процессе делили профиль, {BRAND}_HOME и прокси, а запись env из-под await уводила сессию чужого аккаунта. ContextVar скоупится по asyncio-task и треду.

  • Env читается ТОЛЬКО в build_context(brand, ...) ({BRAND}_PROFILE, {BRAND}_TENANT, {BRAND}_HOME, {BRAND}_PROXY/ALL_PROXY, {BRAND}_UNSAFE_SHOW_SECRETS, {BRAND}_TRACE_ID); явный аргумент старше env.
  • Свой контекст (сервер, тесты, пул воркеров) — use_context(ctx) / set_context / reset_context.
  • Маскировка секретов — свойство контекста: redact_output=True включает редакцию для ВСЕХ команд (emit_data/emit_table зовут redact сами), а --unsafe-show-secrets её снимает. Monkey-patch emit_data и процессный global _REVEAL у потребителей больше не нужны.
  • Профиль потребители читают через clikit.config.active_profile(brand) (контекст → env). Тем, кто ещё берёт его из os.environ напрямую, доступен временный опт-ин build_root_app(..., legacy_profile_env=True).

Публичный API

Зона clikit (clikit.__all__): CliError, AuthRequired, SessionExpired, RateLimited, NotImplementedYet, ValidationError, init_output_mode, is_json, console, emit_data, emit_message, emit_error, redact, AppConfig, McpServer, AdapterConfig, validate_adapters_installed, AdapterProbe, set_adapter_probe, get_adapter_probe, load_dotenv_file, interpolate_env, discover_project_config, active_profile, ExecutionContext, build_context, current_context, has_context, set_context, reset_context, use_context, context_for, build_root_app, command, async_command, gated, make_schema_command, scaffold_cli.

Депрекейт (строгие зоны): HttpClient / ApiError / RefreshCallback, RetryPolicy / DEFAULT_RETRY, SecretStore, AppPaths / atomic_write_text / chmod_600 / slugify ещё доступны из clikit (back-compat), но кидают DeprecationWarning. Бери их канон напрямую из librarykit.transport / librarykit.retry / librarykit.secret_store / librarykit.config_util.

Разработка

uv sync
uv run pytest -q
uv run ruff check clikit

Лицензия

MIT © 2026 Dmitry.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

s_clikit-0.1.9.tar.gz (141.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

s_clikit-0.1.9-py3-none-any.whl (49.2 kB view details)

Uploaded Python 3

File details

Details for the file s_clikit-0.1.9.tar.gz.

File metadata

  • Download URL: s_clikit-0.1.9.tar.gz
  • Upload date:
  • Size: 141.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.30 {"installer":{"name":"uv","version":"0.9.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for s_clikit-0.1.9.tar.gz
Algorithm Hash digest
SHA256 e08c93f3b680515c6ff1bec82244eafcd262346166daef7f95e014f7cd865f69
MD5 8f7506bb6b6a7ef1fd6095d41710a077
BLAKE2b-256 42d8ffe5add31ab86ba607044cb84dc95aaaf5ea8698562f95483ac042182057

See more details on using hashes here.

File details

Details for the file s_clikit-0.1.9-py3-none-any.whl.

File metadata

  • Download URL: s_clikit-0.1.9-py3-none-any.whl
  • Upload date:
  • Size: 49.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.30 {"installer":{"name":"uv","version":"0.9.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for s_clikit-0.1.9-py3-none-any.whl
Algorithm Hash digest
SHA256 3302f238789445abce4945d4d2989039bdb70ed7f8d00e4d8506fa6588e4c962
MD5 fcc592830c5d47edac8ec899c929755a
BLAKE2b-256 20a55a8f6aa67ac4a2cfc9bca800b755eec5ff860507046bc552030a02426762

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.9 This release

2 files

0.1.8

2 files

0.1.7

2 files

0.1.6

2 files

0.1.5

2 files

0.1.4

2 files

0.1.3

2 files

0.1.2

2 files

0.1.1

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page