This file contains instructions for AI agents working with the @diplodoc/cli project.
If a module contains a MODULE.md file, it is considered part of the module's context and should be consulted when working with that module. These files provide module-specific documentation, architecture decisions, and implementation details that complement the general project documentation.
@diplodoc/cli is a CLI tool for building documentation from Markdown files with Yandex Flavored Markdown (YFM) support. The project allows you to build full-fledged documentation with navigation, internal transitions, and full YFM support.
src/— source code of the projectcommands/— CLI commands (build, publish, translate)core/— core logic (config, logger, markdown, toc, etc.)extensions/— extensions (openapi, generic-includer, local-search)steps/— DEPRECATED processing steps (do not add new code here)
build/— compiled code (generated during build)lib/— libraries (generated during build)tests/— project testse2e/— end-to-end testscases/— test casesfixtures/— test fixturesmocks/— test mocks
schemas/— JSON/YAML schemas for fundamental project data structures
-
build — main command for building documentation
- Location:
src/commands/build/ - Subcommands and features are located in
src/commands/build/features/
- Location:
-
publish — publishing documentation
- Location:
src/commands/publish/
- Location:
-
translate — translating documentation
- Location:
src/commands/translate/
- Location:
- Language: TypeScript
- Runtime: Node.js >= 22
- Testing: Vitest
- Build: esbuild
- Linting: ESLint (via
@diplodoc/lint)
# Build project
npm run build
# Run tests
npm test
# Run tests in watch mode
npm run test:watch
# Run E2E tests
npm run e2e
# Type checking
npm run typecheck
# Linting
npm run lint
npm run lint:fixThe project uses path aliases:
~/— points tosrc/- Example:
import {Program} from '~/core/program'
-
Program — main class that manages command execution
- Located in
src/commands/index.ts - Uses decorator pattern (
@withConfigDefaults)
- Located in
-
Commands — CLI commands inherit from
BaseProgram- Each command can have its own options, hooks, and handlers
-
Features — functionality is grouped into features
- Examples:
output-html,search,watch, etc. - Each feature can have its own configuration and hooks
- Examples:
-
Hooks — hook system for extending functionality
- Uses
tapablelibrary
- Uses
Every command should follow a well-defined structure to ensure maintainability and separation of concerns.
- Main logic is concisely gathered in
index.ts - Implementation is divided into separate functionalities through
features/ - Features do not depend on each other
- A command can extract part of functionality into services, located in
services/directory - Services do not depend on each other
- If multiple features need to use the same computed data, such data (and logic for working with them) should be extracted into a service
- If multiple features use the same logic for processing their own data, such logic should likely be extracted into a common utility in the
utils/directory at the same level asfeatures/andservices/ - Utils may depend on each other
- Utils cannot depend on anything outside of
utils/
index.ts— main entry point with concise core logichooks.ts— command hooks for external interaction are always described hereconfig.ts— command and feature configurations for CLI are described heretypes.ts— public types are always described here and exported from the module viaindex.ts- Only public types are exported from
types.ts - Common types used only at the module level should be described next to the entity that produces these types
- Only public types are exported from
Features represent separate functionalities of a command:
- Located in
features/[feature-name]/directory - Features are independent and do not depend on each other
- Each feature can have its own:
index.ts— feature implementationconfig.ts— feature configurationhooks.ts— feature hooks (optional)
Services contain shared business logic:
- Located in
services/[service-name]/directory - Services are independent and do not depend on each other
- Services are used when multiple features need shared computed data or logic
- Services can have:
index.ts— service implementationtypes.ts— service-specific typeshooks.ts— service hooks (optional)
Utility functions for shared logic:
- Located in
utils/directory at the same level asfeatures/andservices/ - Utils may depend on each other
- Utils cannot depend on anything outside of
utils/(no dependencies on features, services, or external modules) - Use utils when multiple features need the same data processing logic
The core/ directory contains logic common to all commands:
- Most often this logic is organized into services
- But base (abstract) classes are also possible, for example
BaseProgram - Used in external extensions in a fully bundled form, i.e., dependencies from
coreare fully bundled
The same rules apply to core/ as to commands:
types.ts— only public types are exportedhooks.ts— hooks are always described here- Service concept applies — logic is organized into services
- Common types used only at the module level should be described next to the entity that produces these types
-
File naming:
- Type files:
types.ts - Configuration:
config.ts - Main module file:
index.ts - Tests:
*.spec.tsor*.test.ts
- Type files:
-
Comments and documentation:
- All code comments must be in English
- All documentation files (ADR, AGENTS.md, README, etc.) must be in English
- JSDoc comments are used for exported functions/classes
-
Variables:
- Avoid single-letter variable names
- Don't use overly long variable names
-
Unit tests:
- Uses Vitest
- Tests are next to code or in
__tests__/ - Prefer using
vitest-whenfor mocking instead of standardmockImplementation
-
E2E tests:
- Located in
tests/e2e/ - Snapshots are used for output verification
- Located in
-
Test fixtures:
- Data preparation (Arrange) should be grouped into helper functions when the same setup is repeated across tests
- Prefer using
page.goto()instead ofpage.evaluate()for navigation - Avoid
page.locator(selector).first()— use more explicit and reliable selectors
core/config/— configuration managementcore/logger/— loggingcore/markdown/— Markdown processingcore/toc/— table of contents managementcore/vcs/— version control systems integrationcore/program/— base program and extension system
Main build logic is located in:
src/commands/build/handler.ts— command handlersrc/commands/build/run.ts— command executionsrc/commands/build/features/— various build features
Extensions integrate with CLI through hooks. There are two integration patterns based on initialization approach:
- Independent extensions — extensions that are not automatically initialized by CLI (can use
peerDependencyregardless of monorepo membership) - Auto-initialized extensions — extensions that CLI automatically imports and initializes on startup (require wrapper logic in
src/extensions/to avoid circular dependencies)
For details, see ADR-001: Dependent Extensions.
Auto-initialized extensions:
extensions/openapi/— OpenAPI support (wrapper for@diplodoc/openapi-extension)extensions/generic-includer/— generic includerextensions/local-search/— local search (wrapper for@diplodoc/search-extension)extensions/github-vcs/— GitHub integrationextensions/arcadia-vcs/— Arcadia integration
The project supports configuration via:
.yfmfile (YAML)- Command-line arguments
- Environment variables
Main configuration files:
YFM_CONFIG_FILENAME— configuration file name (usually.yfm)- Schemas in
schemas/— JSON/YAML schemas for validation
The schemas/ directory stores schemas for fundamental project data structures:
-
toc-schema.yaml— schema for documentation table of contents (toc.yaml)- Defines the structure of navigation and document hierarchy
-
presets-schema.yaml— schema for template variables file (presets.yaml)- Defines variables used for document templating
-
leading-schema.yaml— schema for "leading" (overview) pages structure- Defines the structure of summary/overview pages in documentation
-
page-constructor-schema.yaml— schema for Page Constructor format- Defines the format for generating HTML pages from YAML descriptions
- Based on @gravity-ui/page-constructor
- Used to create pages from JSON/YAML block-based configurations
Important: Schemas and TypeScript types must always be kept in sync. When modifying types in src/ that correspond to a schema (e.g., RawToc ↔ toc-schema.yaml, Preset ↔ presets-schema.yaml), you must update the matching schema in schemas/ and vice versa. A mismatch between schemas and code leads to bugs where valid input (per schema) is silently rejected by the implementation.
README.md— main documentationCONTRIBUTING.md— contributor guideCHANGELOG.md— change historyadr/arch-quality.md— architectural quality principlesadr/ADR-001-dependent-extensions.md— architecture decision record for extension integration patterns
MODULE.md— if present in a module directory, this file contains module-specific documentation and is part of the module's context for AI agents- Provides module architecture, implementation details, and usage patterns
- Should be consulted when working with that specific module
- Example locations:
src/core/MODULE.md,src/commands/build/MODULE.md, etc.
- Create directory in
src/commands/[command-name]/ - Create command class inheriting from
BaseProgram - Register command in
src/commands/index.ts
- Create directory in
src/commands/build/features/[feature-name]/ - Implement feature with hooks
- Register feature in
src/commands/build/index.ts
- Create directory in
src/extensions/[extension-name]/ - Implement extension
- Register in project configuration
- The project uses a monorepo (nx)
- All changes must pass linter and tests
- Types must be correct (checked via
npm run typecheck) - When working with VCS (GitHub/Arcadia), token configuration is required in
.envor.yfm - All comments and documentation files (ADR, AGENTS.md, README, etc.) must be written in English
- The
src/steps/directory is deprecated. Do not add new code there. If you need to fix existing code, carefully move it tocommands/build/features/ - When changing TypeScript types that have a corresponding schema in
schemas/, always update the schema to match, and vice versa