dacli [OPTIONS] <COMMAND> [ARGS]
Options:
--docs-root PATH Documentation root directory (default: $PROJECT_PATH or cwd)
--format FORMAT Output format: text (default), json, yaml
--pretty Formatted output for humans
--verbose, -v Show warning messages (default: only errors shown)
--no-gitignore Include files that would normally be excluded by .gitignore patterns
--include-hidden Include files in hidden directories (starting with '.')
--version Show version
--help Show help
dacli - Docs-As-Code CLI Specification
Overview
dacli (Docs-As-Code CLI) enables the use of all documentation tools via the command line.
This is especially useful for LLMs that don’t have MCP support but can use Bash/Shell tools.
Global Options
Help System
Command Groups
Commands are organized into story-based groups in the help output:
| Group | Commands |
|---|---|
Discover |
|
Find |
|
Read |
|
Validate |
|
Edit |
|
Typo Correction
If you mistype a command, dacli suggests the correct command:
$ dacli serch "API"
Error: No such command 'serch'.
Did you mean: search
Usage Examples
The main help (dacli --help) and each command help show usage examples:
$ dacli --help
...
Examples:
dacli --format json structure # Get document structure as JSON
dacli search "authentication" # Find sections about authentication
dacli section api.endpoints # Read a specific section
Command Aliases
For faster typing, all commands have short aliases:
| Alias | Command | Description |
|---|---|---|
|
|
Show document structure |
|
|
Show project/section metadata |
|
|
Search documentation |
|
|
Sections at level N |
|
|
Read section content |
|
|
Get code/tables/images |
|
|
Validate structure |
Example:
# These are equivalent:
dacli --format json search "API"
dacli --format json s "API"
Navigation Commands
structure
Shows the hierarchical document structure.
dacli structure [--max-depth N]
Example:
$ dacli structure --max-depth 1
{
"sections": [
{"path": "introduction", "title": "Introduction", "level": 1},
{"path": "architecture", "title": "Architecture", "level": 1}
],
"total_sections": 15
}
section
Reads the content of a section.
dacli section <PATH>
Path Format:
Section paths use hybrid notation:
- Colon (:) separates document from section: doc:section
- Dot (.) separates nested sections: doc:section.subsection
Examples:
# Read a chapter (Level 1)
$ dacli section my-doc:introduction
{
"path": "my-doc:introduction",
"title": "Introduction",
"content": "== Introduction\n\nThis section...",
"format": "asciidoc"
}
# Read a nested section (Level 2)
$ dacli section my-doc:introduction.goals
{
"path": "my-doc:introduction.goals",
"title": "Goals",
"content": "=== Goals\n\nThese are...",
"format": "asciidoc"
}
# Error: Path not found with helpful hint (Issue #198)
$ dacli section my-doc:intro:goals
{
"error": {
"code": "PATH_NOT_FOUND",
"message": "Section 'my-doc:intro:goals' not found",
"details": {
"requested_path": "my-doc:intro:goals",
"corrected_path": "my-doc:intro.goals",
"hint": "Use colon (:) only once to separate document from section. Use dots (.) for nested sections. Example: my-doc:intro.goals",
"suggestions": ["my-doc:introduction", "my-doc:introduction.goals"]
}
}
}
sections-at-level
Shows all sections at a specific level.
dacli sections-at-level <LEVEL>
Arguments:
-
LEVEL: Non-negative integer (0, 1, 2, …) representing the nesting level-
Level 0: Document root
-
Level 1: Top-level chapters/sections
-
Level 2: Subsections
-
Level 3 and higher: Deeper nested sections
-
Examples:
# Get all top-level chapters (Level 1)
$ dacli sections-at-level 1
# Get all second-level sections (Level 2)
$ dacli sections-at-level 2
# Error: Negative levels are not valid (Issue #199)
$ dacli sections-at-level -1
Error: Invalid value for 'level': Level must be non-negative, got -1.
Document hierarchies start at level 0 (document root).
Search & Elements Commands
search
Searches the documentation.
dacli search <QUERY> [--scope PATH] [--max-results N] [--limit N]
Options:
-
--max-results N,--limit N: Maximum results to return (default: 20, aliases) -
--scope PATH: Restrict search to path prefix. Warns if scope path doesn’t exist in the documentation structure.
Example:
$ dacli search "authentication" --limit 5
{
"query": "authentication",
"results": [
{"path": "security.auth", "context": "...implements authentication...", "score": 0.95}
],
"total_results": 1
}
elements
Lists elements (code blocks, tables, etc.).
dacli elements [SECTION_PATH] [--type TYPE] [--recursive] [--include-content] [--content-limit N]
Arguments:
-
SECTION_PATH: Optional section path to filter elements (positional argument)
Options:
-
--type TYPE: Element type filter -code,table,image,plantuml,list,admonition. Warns if type is invalid but still returns empty result. -
--recursive: Include elements from child sections (default: exact match only) -
--include-content: Include element content and attributes (Issue #159) -
--content-limit N: Limit content to first N lines (requires--include-content)
Examples:
# Get code blocks without content (metadata only)
$ dacli elements --type code
# Get code blocks with full content
$ dacli elements --type code --include-content
# Get code blocks with first 5 lines only
$ dacli elements --type code --include-content --content-limit 5
# Get all elements in a section with content
$ dacli elements api --recursive --include-content
Meta-Information Commands
metadata
Shows metadata for project or section.
dacli metadata [PATH]
Project metadata (without PATH):
$ dacli metadata
{
"total_files": 15,
"total_sections": 87,
"total_words": 12450,
"formats": ["asciidoc", "markdown"]
}
Section metadata (with PATH):
$ dacli metadata architecture.decisions
{
"path": "architecture.decisions",
"title": "Architecture Decisions",
"word_count": 2340,
"subsection_count": 5
}
validate
Validates the documentation structure.
dacli validate
Example:
$ dacli validate
{
"valid": true,
"errors": [],
"warnings": [
{"type": "orphaned_file", "path": "unused.adoc"}
],
"validation_time_ms": 45
}
Manipulation Commands
update
Updates the content of a section.
dacli update <PATH> --content "..." [--no-preserve-title] [--expected-hash HASH]
Content Input:
-
Direct string:
--content "New content here" -
Escape sequences:
--content "Line 1\nLine 2"(converts\nto actual newlines) -
From stdin:
--content -(reads from stdin)
Options:
-
--no-preserve-title- Use title from provided content instead of preserving original title. When this flag is set, the content must include a section title (starting with=for AsciiDoc or#for Markdown), otherwise the update will fail. This allows changing the section title while maintaining document structure. -
--expected-hash HASH- Hash for optimistic locking (see examples below)
Examples:
# Direct content with escape sequences
$ dacli update introduction --content "First paragraph.\n\nSecond paragraph."
{
"success": true,
"path": "introduction",
"previous_hash": "a1b2c3d4",
"new_hash": "e5f6g7h8"
}
# Read content from stdin (useful for multi-line content)
$ cat new_content.txt | dacli update introduction --content -
# Pipe from another command
$ echo "Updated via stdin" | dacli update introduction --content -
# Change section title (requires --no-preserve-title)
$ dacli update introduction --content "== New Title\n\nUpdated content." --no-preserve-title
{
"success": true,
"path": "introduction"
}
# Error: --no-preserve-title requires content with title
$ dacli update introduction --content "Content without title" --no-preserve-title
{
"success": false,
"error": "Content must include a section title when preserve_title is false. Expected content to start with '=' (AsciiDoc) or '#' (Markdown)."
}
insert
Inserts content relative to a section.
dacli insert <PATH> --position before|after|append --content "..."
Position Options:
-
before- Insert before the section heading. Adds blank line after content if next line is a heading. -
after- Insert after the section end, including all child sections (before next sibling at same or higher level) -
append- Insert at end of section’s own content (before any child sections)
Content Input:
-
Direct string:
--content "New content" -
Escape sequences:
--content "## Section\n\nContent"(converts\nto newlines) -
From stdin:
--content -(reads from stdin)
|
Note
|
When inserting content that starts with a heading (# or =) after existing content, a blank line is automatically added for proper formatting.
|
Examples:
# Insert new section with escape sequences
$ dacli insert architecture --position after --content "== New Section\n\nContent..."
{
"success": true,
"inserted_at": {"file": "arc42.adoc", "line": 150}
}
# Insert from stdin (for complex multi-line content)
$ cat new_section.adoc | dacli insert architecture --position after --content -
# Append to end of parent section (after all subsections)
$ dacli insert components --position append --content "=== New Component\n\nDetails..."
Exit Codes
| Code | Meaning |
|---|---|
0 |
Success |
1 |
General error |
2 |
Invalid arguments |
3 |
Path not found |
4 |
Validation error |
5 |
Write error |
LLM Integration Example
An LLM can use the CLI via Bash tools:
# Query structure
structure=$(dacli structure --max-depth 2 --docs-root /project/docs)
# Search for topic
results=$(dacli search "database" | jq '.results[].path')
# Read section
content=$(dacli section architecture.decisions)
# Update documentation
dacli update api.endpoints --content "Updated API documentation..."
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.