Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
ca2417a
feat(cli): C1 — self-documenting `pachca api` (ls / --describe / --sp…
lookinway May 15, 2026
ac8cb1c
feat(cli): C6 — `pachca api --data '{json}'` (inline JSON body)
lookinway May 15, 2026
1ba3df6
docs(cli): D0/D1 — split cli.mdx into Get started / Guides / Reference
lookinway May 15, 2026
3524698
docs(cli): D6 — Overview as a soft terminal-first fork
lookinway May 15, 2026
f54b31f
docs(agents): D4 — strengthen ai-agents.mdx CLI subsection under C1
lookinway May 15, 2026
b47c77e
refactor(cli): D3 — single source of truth for global flags
lookinway May 15, 2026
8ac6c18
feat(cli/docs): D2 — auto-generated Commands page with flags & args
lookinway May 15, 2026
dec25da
docs(cli): D5 — audit confirms CLI coverage in llms.txt / llms-full.txt
lookinway May 15, 2026
51bf31b
feat(cli): C7 — `--plain` named output mode
lookinway May 15, 2026
8e6bc6e
feat(cli): C8 — PACHCA_HOME config dir override
lookinway May 15, 2026
5676769
docs(cli): C9 — fix autocomplete shells (fish → PowerShell)
lookinway May 15, 2026
22465d0
docs: mark CLI_IMPROVEMENTS_PLAN 100% implemented (commit map)
lookinway May 15, 2026
b1e29f4
chore(release): CLI 2026.5.2 — changelog, releases.json, updates
lookinway May 15, 2026
e590f72
docs: clearer wording — drop "самоописание / против спецификации / на…
lookinway May 15, 2026
7519122
docs(updates): trim 2026-05-15 entry, drop command list
lookinway May 15, 2026
2e0afda
docs(cli): restore users-list sample output in Overview quick start
lookinway May 15, 2026
d04bcb8
docs(cli): rebalance focus back to typed commands (api = auxiliary)
lookinway May 15, 2026
b63d21c
docs(cli): revise Overview, Прямые запросы; fix Commands width; nav
lookinway May 15, 2026
055ebbf
docs(cli): restructure "Два способа работы" — no numbers, intro + sub…
lookinway May 15, 2026
484d30b
docs(cli): "Способы работы" heading; "с CLI"; consistent "команда pac…
lookinway May 15, 2026
ed4ec87
docs(cli): drop AI агенты card from Overview; tidy ai-agents pointer
lookinway May 15, 2026
27b18d5
docs(cli): plain "Прямые запросы" card text (no "команда", no inline …
lookinway May 15, 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
426 changes: 426 additions & 0 deletions CLI_IMPROVEMENTS_PLAN.md

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions apps/docs/components/api/markdown-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { Tree, TreeFolder, TreeFile } from '@/components/mdx/tree';
import { ImageCard } from '@/components/mdx/image-card';
import { AgentSkillsWorkflows } from '@/components/mdx/agent-skills-workflows';
import { CliCommands } from '@/components/mdx/cli-commands';
import { GlobalFlags } from '@/components/mdx/global-flags';
import { SdkCommands } from '@/components/mdx/sdk-commands';
import { NpmBadge } from '@/components/mdx/npm-badge';
import { PackageBadge } from '@/components/mdx/package-badge';
Expand Down Expand Up @@ -231,6 +232,7 @@ const components = {
ScopeRoles,
AgentSkillsWorkflows,
CliCommands,
GlobalFlags,
SdkCommands,
NpmBadge,
PackageBadge,
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/components/mdx/cards.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ const iconMap: Record<string, LucideIcon> = {
const GUIDE_ICONS: Record<string, string> = {
'/guides/quickstart': 'Zap',
'/guides/ai-agents': 'Sparkles',
'/guides/cli': 'Terminal',
'/guides/cli/overview': 'Terminal',
'/guides/workflows': 'Route',
'/guides/webhook': 'Webhook',
'/guides/export': 'Download',
Expand Down
129 changes: 84 additions & 45 deletions apps/docs/components/mdx/cli-commands.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,59 @@
import { generateNavigation } from '@/lib/navigation';
import { parseOpenAPI } from '@/lib/openapi/parser';
import { generateUrlFromOperation } from '@/lib/openapi/mapper';
import { getCliSections, type CliCommand } from '@/lib/cli-data';
import { CopyableInlineCode } from '@/components/api/copyable-inline-code';
import { EndpointLink } from '@/components/api/endpoint-link';
import type { EndpointRequirements } from '@/lib/openapi/types';

function commandHref(command: string): string {
// "pachca messages create" → "/api/messages/create"
return '/api/' + command.replace(/^pachca\s+/, '').replace(/\s+/g, '/');
}

function FlagsArgs({ cmd }: { cmd: CliCommand }) {
const rows = [
...(cmd.args ?? []).map((a) => ({
token: `<${a.name}>`,
type: 'аргумент',
required: a.required,
description: a.description,
})),
...cmd.flags.map((f) => ({
token: `--${f.name}`,
type: f.options ? f.options.join(' | ') : f.type === 'boolean' ? 'boolean' : 'string',
required: f.required,
description: f.description,
})),
];
if (rows.length === 0) return null;
return (
<table className="w-full table-fixed border-none text-[13px] mt-2 mb-1">
<colgroup>
<col className="w-[26%]" />
<col className="w-[26%]" />
<col className="w-[48%]" />
</colgroup>
<tbody className="divide-y divide-glass-divider">
{rows.map((r) => (
<tr key={r.token}>
<td className="py-2 pl-0! pr-3 align-top break-words text-text-primary">
<CopyableInlineCode>{r.token}</CopyableInlineCode>
{r.required ? <span className="text-danger ml-1">*</span> : null}
</td>
<td className="py-2 pr-3 align-top break-words text-text-secondary">{r.type}</td>
<td className="py-2 pl-0! align-top break-words text-text-secondary">
{r.description}
</td>
</tr>
))}
</tbody>
</table>
);
}

export async function CliCommands() {
const [sections, api] = await Promise.all([generateNavigation(), parseOpenAPI()]);
const methodsSection = sections.find((s) => s.title === 'Методы API');
const allCommands = methodsSection
? methodsSection.items.flatMap((group) => group.children ?? [])
: [];
const [sections, api] = await Promise.all([Promise.resolve(getCliSections()), parseOpenAPI()]);

// Build a map from URL to requirements for tooltip data
const requirementsMap = new Map<string, EndpointRequirements>();
for (const ep of api.endpoints) {
if (ep.requirements) {
Expand All @@ -21,44 +62,42 @@ export async function CliCommands() {
}

return (
<div className="my-6 overflow-x-auto not-prose">
<table className="w-full border-none text-[14px]">
<thead className="border-b border-glass-border">
<tr>
<th className="text-left py-4 pl-0! text-text-primary! font-semibold! text-[15px]! normal-case! tracking-normal! bg-transparent!">
Команда
</th>
<th className="text-left py-4 pl-0! text-text-primary! font-semibold! text-[15px]! normal-case! tracking-normal! bg-transparent!">
Метод API
</th>
</tr>
</thead>
<tbody className="divide-y divide-glass-divider">
{allCommands.map((item) => {
const command = `pachca ${item.href.replace(/^\/api\//, '').replace(/\//g, ' ')}`;
const req = requirementsMap.get(item.href);
return (
<tr key={item.href}>
<td className="py-5 pl-0! text-text-primary">
<CopyableInlineCode>{command}</CopyableInlineCode>
</td>
<td className="py-5 pl-0! text-text-primary">
<EndpointLink
method={item.method}
href={item.href}
scope={req?.scope}
scopeRoles={req?.scopeRoles?.join(',')}
plan={req?.plan}
noAuth={req?.auth === false}
>
{item.title}
</EndpointLink>
</td>
</tr>
);
})}
</tbody>
</table>
<div className="my-6 not-prose">
{sections.map((section) => (
<section key={section.section} className="mb-10">
<h3 className="text-[15px] font-semibold text-text-primary mb-3 font-mono">
{section.section}
</h3>
<div className="space-y-5">
{section.commands.map((cmd) => {
const href = commandHref(cmd.command);
const req = requirementsMap.get(href);
return (
<div key={cmd.command}>
<div className="flex flex-wrap items-baseline gap-x-3 gap-y-1">
<CopyableInlineCode>{cmd.command}</CopyableInlineCode>
{cmd.method ? (
<EndpointLink
method={cmd.method}
href={href}
scope={req?.scope}
scopeRoles={req?.scopeRoles?.join(',')}
plan={req?.plan}
noAuth={req?.auth === false}
>
{cmd.summary}
</EndpointLink>
) : (
<span className="text-text-secondary text-[14px]">{cmd.summary}</span>
)}
</div>
<FlagsArgs cmd={cmd} />
</div>
);
})}
</div>
</section>
))}
</div>
);
}
46 changes: 46 additions & 0 deletions apps/docs/components/mdx/global-flags.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { getGlobalFlags } from '@/lib/cli-data';
import { CopyableInlineCode } from '@/components/api/copyable-inline-code';

/**
* Global CLI flags table — single source of truth: packages/cli
* src/data/global-flags.json (generated from BaseCommand.baseFlags).
* Replaces hardcoded RU flag tables in the guide and README.
*/
export function GlobalFlags() {
const flags = getGlobalFlags();

return (
<div className="my-6 overflow-x-auto not-prose">
<table className="w-full border-none text-[14px]">
<thead className="border-b border-glass-border">
<tr>
<th className="text-left py-4 pl-0! text-text-primary! font-semibold! text-[15px]! normal-case! tracking-normal! bg-transparent!">
Флаг
</th>
<th className="text-left py-4 pl-0! text-text-primary! font-semibold! text-[15px]! normal-case! tracking-normal! bg-transparent!">
Короткий
</th>
<th className="text-left py-4 pl-0! text-text-primary! font-semibold! text-[15px]! normal-case! tracking-normal! bg-transparent!">
Описание
</th>
</tr>
</thead>
<tbody className="divide-y divide-glass-divider">
{flags.map((f) => (
<tr key={f.name}>
<td className="py-4 pl-0! text-text-primary">
<CopyableInlineCode>
{f.type === 'boolean' ? `--${f.name}` : `--${f.name} <value>`}
</CopyableInlineCode>
</td>
<td className="py-4 pl-0! text-text-secondary">
{f.char ? <CopyableInlineCode>{`-${f.char}`}</CopyableInlineCode> : null}
</td>
<td className="py-4 pl-0! text-text-primary">{f.description}</td>
</tr>
))}
</tbody>
</table>
</div>
);
}
2 changes: 2 additions & 0 deletions apps/docs/components/mdx/mdx-components.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { Tree, TreeFolder, TreeFile } from '@/components/mdx/tree';
import { ImageCard } from '@/components/mdx/image-card';
import { AgentSkillsWorkflows } from '@/components/mdx/agent-skills-workflows';
import { CliCommands } from '@/components/mdx/cli-commands';
import { GlobalFlags } from '@/components/mdx/global-flags';
import { SdkCommands } from '@/components/mdx/sdk-commands';
import { NpmBadge } from '@/components/mdx/npm-badge';
import { PackageBadge } from '@/components/mdx/package-badge';
Expand Down Expand Up @@ -527,6 +528,7 @@ export const customMdxComponents = {
FormPlayground,
AgentSkillsWorkflows,
CliCommands,
GlobalFlags,
SdkCommands,
NpmBadge,
PackageBadge,
Expand Down
25 changes: 15 additions & 10 deletions apps/docs/content/guides/ai-agents.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -123,28 +123,33 @@ description: "Как Пачка работает с AI-агентами: тре

### CLI

Самый быстрый и производительный способ. Минимальное влияние на контекст агента — не нужно загружать документацию, агент узнаёт возможности через `--help`. Если есть доступ к shell, агент может генерировать скрипты для типовых задач.
Самый быстрый и производительный способ. Агент работает теми же **типизированными командами**, что и человек: каждый метод API — отдельная команда с флагами и валидацией. Готовые последовательности под типовые задачи — в [Сценариях](/guides/cli/workflows).

```bash
# Установка
npm install -g @pachca/cli

# Агент может вызывать любые команды
pachca messages create --entity-id 123 --content "Готово"
pachca users list -o json
# Без установки — агент запускает сразу, всегда последняя версия
npx @pachca/cli messages create --entity-id 123 --content "Готово" --no-input -o json
npx @pachca/cli users list --no-input -o json
```

<Info>CLI автоматически определяет неинтерактивную среду (stdin/stdout — не TTY) и адаптируется: выводит JSON вместо таблиц, отключает промпты и спиннер, а при пропущенных обязательных флагах — возвращает ошибку вместо запроса ввода. Агенту не нужна дополнительная настройка — достаточно передать все обязательные флаги.</Info>
Токен агент передаёт через переменную окружения `PACHCA_TOKEN` (или флаг `--token` для разового вызова) — ничего не пишется на диск, токен берётся из секретов агента и **не коммитится в репозиторий**.

Для ветвления логики агент использует exit codes (`0` успех, `3` нет доступа, `4` не найдено) и поле `type` в JSON-ошибке (`PACHCA_AUTH_ERROR`, `PACHCA_VALIDATION_ERROR` и т.д.).

Если нужного метода нет под рукой, не обязательно грузить документацию в контекст или открывать сайт — CLI подскажет точечно: `api ls` (список эндпоинтов), затем `api <МЕТОД> <путь> --describe` (параметры, тело, эквивалентная команда), и агент сразу её вызывает.

<Info>CLI автоматически определяет неинтерактивную среду (stdin/stdout — не TTY) и адаптируется: выводит JSON вместо таблиц, отключает промпты и спиннер, а при пропущенных обязательных флагах — возвращает ошибку вместо запроса ввода. Флаг `--no-input -o json` фиксирует этот режим явно.</Info>

<CardGroup columns={2}>
<Card title="@pachca/cli" href="https://www.npmjs.com/package/@pachca/cli">
Пакет на npm
</Card>
<Card title="Руководство CLI" href="/guides/cli">
Полная документация по CLI — команды, флаги, пайпы, сценарии
<Card title="Руководство CLI" href="/guides/cli/overview">
Установка, авторизация, скрипты и CI, полный справочник команд
</Card>
</CardGroup>

Команда `pachca api` (прямые запросы) и встроенный справочник по API (`api ls` / `--describe` / `--spec` / `--docs`) — в разделе [Прямые запросы](/guides/cli/api-requests).

### Context7 MCP

Самый надёжный вариант для постоянной работы с API. [Context7](https://context7.com) — MCP-сервер, который отдаёт актуальную документацию прямо в контекст агента. Подходит для удалённых интеграций с OAuth, многошаговых сценариев и когда вы часто просите агента выполнять разные задачи в Пачке из промптов.
Expand Down
Loading
Loading