Configuring a project with ubproject.toml¶
The ubproject.toml file is a TOML configuration file that allows you to specify the settings for your project.
You can find the schema at https://ubcode.useblocks.com/ubproject.schema.json, and it is recommended that you add this to the top of your file for use with the taplo toolkit:
"$schema" = "https://ubcode.useblocks.com/ubproject.schema.json"
Please also see the detailed ubproject.toml schema reference.
For a complete example, see the Sphinx-Needs Demo project.
Configuration file discovery¶
Hierarchical configuration is supported, such that the “closest” config file in the directory hierarchy is used for every individual file, with all paths in the config file being resolved relative to the directory containing that config file.
For example, given the following directory structure:
project/
├── docs1/
│ ├── doc1.rst
│ └── ubproject.toml
├── docs2/
│ └── doc2.rst
└── ubproject.toml
The configuration for doc1.rst will be read from project/docs1/ubproject.toml, whereas for doc2.rst it will be read from project/ubproject.toml.
See also the source configuration below for how file-discovery works for reStructuredText source files.
Configuration options¶
The ubproject.toml file supports a rich set of configuration options organized into logical sections. Each section controls different aspects of ubCode’s behavior:
Top-level options: Basic project settings and inheritance
needs: Configuration for need identification, types, links, and workflow
needs_json: Settings for the Needs Index tree view
parse: Extend reStructuredText parsing with custom directives and roles
project: Basic project metadata
lint: Control error reporting and validation
source: File discovery and inclusion patterns
scripts: Custom commands for your development workflow
server: Language server behavior and performance settings
format_rst: Comprehensive reStructuredText formatting options
Each section includes sensible defaults, so you only need to specify the options you want to customize.
Top-level options¶
The configuration file supports several top-level options that control the overall behavior:
# Extend another configuration file
extend = "path/to/ubproject.toml"
# Virtual configurations do not correspond to an actual project.
# They are used for providing shared configuration defaults.
virtual = true
- extend
Type:
string(optional)The path to another
ubproject.tomlfile to extend. This allows you to create a hierarchy of configuration files where child configurations can inherit settings from parent configurations. Paths are resolved relative to the current configuration file.# Extend the configuration from the parent directory extend = "../ubproject.toml" # Or extend from a specific shared configuration extend = "~/.config/ubcode/base.toml"
- virtual
Type:
boolean(default:false)When set to
true, this configuration is marked as virtual and does not correspond to an actual project. Virtual configurations are used for providing shared configuration defaults or for workspaces that are not themselves projects. This is particularly useful when creating base configurations that will be extended by other projects.# In a shared base configuration file virtual = true [needs] id_required = true id_regex = "^[A-Z0-9_]{5,}"
needs¶
This provides configuration for ubCode to identify and extract needs in the source files.
[needs]
# whether an non-autogenerated ID is required for each need
id_required = true
# regex pattern to validate the ID against
id_regex = "^[A-Z0-9_]{5,}"
# options for auto-generating IDs
id_length = 5
# Base auto-generated IDs on the title.
id_from_title = false
# If True, a title is optional.
title_optional = false
# Base auto-generated titles on the content.
title_from_content = false
# If given, only the defined statuses are allowed.
statuses = [{name="open"}, {name="closed"}]
# If given, only the defined tags are allowed.
tags = [{name="tag1"}, {name="tag2"}]
# Mapping of keys that can be used as needimport arguments and replaced by the values
import_keys = {key1="/path/to/needs.json"}
# Path to a JSON file containing schema definitions
schema_definitions_from_json = "path/to/schema.json"
# Set of need fields that may contain variant functions
variant_options = ["status", "priority"]
# Additional context for filter expressions
filter_data = {environment = "production", team = "backend"}
# list of need types
[[needs.types]]
directive = "my-req"
title = "My Requirement"
prefix = "M_"
color = "#000000"
style = "node"
# list of link types
[[needs.extra_links]]
option = "tests"
incoming = "is tested by"
outgoing = "tests"
copy = true
color = "#00AA00"
style = "solid"
style_part = "dotted"
style_start = "-"
style_end = ">"
allow_dead_links = false
# list of extra options
extra_options = ["tests"]
# Alternative detailed definition
# extra_options = [{name = "priority", description = "Priority level"}]
# default options for all needs
[needs.global_options.status]
default = "open"
# Using predicates for conditional defaults
[needs.global_options.priority]
default = "medium"
predicates = [
["type == 'req'", "high"],
["status == 'closed'", "low"]
]
# External needs sources
[[needs.external_needs]]
json_path = "path/to/external_needs.json"
id_prefix = "EXT"
base_url = "https://example.com"
target_url = "needs/{{ id }}.html"
css_class = "external-need"
version = "1.0.0"
skip_in_ubcode = false
Core Options¶
- id_required
Type:
boolean(default:false)If
true, every need must have an explicit ID. Iffalse, IDs will be auto-generated when not provided.- id_regex
Type:
string(default:"^[A-Z0-9_]{5,}")Regular expression pattern to validate need IDs against. Only applies when
id_requiredistrue.- id_length
Type:
integer(default:5)Length of auto-generated IDs when not explicitly provided.
- id_from_title
Type:
boolean(default:false)When
true, auto-generated IDs will be based on the need title instead of being random.- title_optional
Type:
boolean(default:false)When
true, allows needs to be created without a title.- title_from_content
Type:
boolean(default:false)When
true, auto-generates titles from the first line of need content when no title is provided.
Need Types¶
The types array defines the available need directives in your project:
[[needs.types]]
directive = "requirement" # The RST directive name
title = "Requirement" # Human-readable title
prefix = "REQ_" # Prefix for auto-generated IDs
color = "#BFD8D2" # Color for diagrams
style = "node" # Style for diagrams
Each type supports:
directive(required): The reStructuredText directive nametitle(required): Human-readable title for the need typeprefix(required): Prefix used for auto-generated need IDscolor(optional, default:"#000000"): Color used in need diagramsstyle(optional, default:"node"): Style used in need diagrams
Link Types¶
The extra_links array defines custom relationships between needs:
[[needs.extra_links]]
option = "implements" # The option name used in need directives
incoming = "implemented by" # Description for incoming links
outgoing = "implements" # Description for outgoing links
copy = false # Whether to copy to common links
color = "#0000FF" # Color for diagrams
style = "solid" # Line style for diagrams
style_part = "dotted" # Style for partial links
style_start = "-" # Start marker for diagrams
style_end = ">" # End marker for diagrams
allow_dead_links = false # Allow links to non-existent needs
External Needs¶
Load needs from external sources (JSON files or URLs):
# From local file
[[needs.external_needs]]
json_path = "external/project_needs.json"
id_prefix = "EXT"
base_url = "https://external-project.com"
target_url = "docs/{{ id }}.html"
# From remote URL
[[needs.external_needs]]
json_url = "https://api.example.com/needs.json"
id_prefix = "REMOTE"
Extra Options¶
The extra_options configuration allows you to define custom fields for your needs beyond the standard fields (like id, title, status, etc.). You can specify these options in two ways:
Simple format (string list):
extra_options = ["priority", "effort", "assignee", "component"]
Detailed format (with descriptions and schemas):
extra_options = [
{name = "priority", description = "Priority level"},
{name = "effort", description = "Story points", schema = {type = "integer", minimum = 1, maximum = 13}},
{name = "assignee", description = "Assigned team member", schema = {type = "string", pattern = "^[a-zA-Z.]+@company\\.com$"}},
{name = "status", description = "Current status", schema = {type = "string", enum = ["draft", "review", "approved", "done"]}},
{name = "due_date", description = "Due date", schema = {type = "string", format = "date"}},
{name = "tags", description = "Associated tags", schema = {type = "array", items = {type = "string"}}},
{name = "active", description = "Is currently active", schema = {type = "boolean"}},
]
Schema Validation¶
When using the detailed format, you can specify a schema property to validate the values entered for that field. The schema follows JSON Schema specification and supports various data types:
String Schemas:
needs.extra_options = [
# Basic string
{name = "title", schema = {type = "string"}},
# String with length constraints
{name = "summary", schema = {type = "string", minLength = 10, maxLength = 100}},
# String with pattern validation (email)
{name = "contact", schema = {type = "string", format = "email"}},
# String with pattern validation (custom regex)
{name = "id_pattern", schema = {type = "string", pattern = "^[A-Z]{3}-[0-9]{4}$"}},
# Enumerated string values
{name = "severity", schema = {type = "string", enum = ["low", "medium", "high", "critical"]}},
# Constant string value
{name = "type", schema = {type = "string", const = "requirement"}},
]
String Format Options:
The format property supports various predefined formats:
"date": RFC 3339 date format (e.g.,2023-10-22)"date-time": RFC 3339 date-time format (e.g.,2023-10-22T14:30:00Z)"time": RFC 3339 time format (e.g.,14:30:00Z)"email": RFC 5322 email address (e.g.,user@example.com)"hostname": RFC 1123 hostname (e.g.,example.com)"uri": RFC 3986 URI (e.g.,https://example.com/path)"uuid": RFC 4122 UUID (e.g.,550e8400-e29b-41d4-a716-446655440000)"regex": ECMAScript regular expression
Integer and Number Schemas:
needs.extra_options = [
# Basic integer
{name = "count", schema = {type = "integer"}},
# Integer with range constraints
{name = "priority", schema = {type = "integer", minimum = 1, maximum = 10}},
# Integer with exclusive bounds
{name = "score", schema = {type = "integer", exclusiveMinimum = 0, exclusiveMaximum = 100}},
# Integer that must be a multiple of another number
{name = "percentage", schema = {type = "integer", multipleOf = 5}},
# Number (floating point)
{name = "rating", schema = {type = "number", minimum = 0.0, maximum = 5.0}},
# Enumerated integer values
{name = "fibonacci", schema = {type = "integer", enum = [1, 2, 3, 5, 8, 13, 21]}},
]
Boolean Schemas:
needs.extra_options = [
# Basic boolean
{name = "approved", schema = {type = "boolean"}},
# Boolean with specific allowed values
{name = "enabled", schema = {type = "boolean", enum = [true]}}, # Only true allowed
# Boolean with constant value
{name = "published", schema = {type = "boolean", const = false}},
]
Array Schemas:
[[needs.extra_options]]
name = "tags"
schema = { type = "array", items = { type = "string" } }
[[needs.extra_options]]
name = "reviewers"
schema = { type = "array", items = { type = "string", format = "email" }, minItems = 1, maxItems = 3 }
[[needs.extra_options]]
name = "priorities"
schema = { type = "array", items = { type = "integer", enum = [1, 2, 3, 4, 5] } }
[[needs.extra_options]]
name = "categories"
schema = { type = "array", items = { type = "string" }, uniqueItems = true }
Complex Schema Examples:
[[needs.extra_options]]
name = "assignee"
description = "Assigned team member"
[needs.extra_options.schema]
type = "string"
format = "email"
pattern = "^[a-zA-Z0-9._%+-]+@(company|contractor)\\.com$"
[[needs.extra_options]]
name = "effort"
description = "Story points (Fibonacci sequence)"
[needs.extra_options.schema]
type = "integer"
enum = [1, 2, 3, 5, 8, 13, 21, 34]
description = "Must be a Fibonacci number"
[[needs.extra_options]]
name = "due_date"
description = "Target completion date"
[needs.extra_options.schema]
type = "string"
format = "date"
[[needs.extra_options]]
name = "component"
description = "System component affected"
[needs.extra_options.schema]
type = "array"
minItems = 1
uniqueItems = true
[needs.extra_options.schema.items]
type = "string"
enum = ["frontend", "backend", "database", "api", "auth", "ui"]
Usage in Need Directives:
Once defined, these extra options can be used in your need directives:
.. requirement:: User Authentication
:priority: 5
:effort: 8
:assignee: developer@company.com
:due_date: 2024-12-31
:tags: security, authentication
:component: auth, backend
:active: true
Users must be able to authenticate using their corporate credentials.
Advanced Options¶
- schema_definitions_from_json
Type:
string(default:"")Path to a JSON file containing schema definitions for validating need content.
- variant_options
Type:
array(default:[])List of need field names that may contain variant functions for conditional content.
variant_options = ["status", "priority", "assignee"]
- import_keys
Type:
object(default:{})Mapping of keys for
needimportdirectives, allowing short keys to reference longer file paths.[needs.import_keys] backend = "/path/to/backend_needs.json" frontend = "/path/to/frontend_needs.json"
- filter_data
Type:
object(default:{})Additional context variables that can be referenced in filter expressions throughout your needs configuration. This allows you to define custom variables that can be used in conditional logic in multiple contexts.
Where filter_data can be used:
Predicate default filters - In
global_optionspredicates to conditionally set default valuesneedimport item filters - To filter which needs are imported from external sources
needextend filters - To conditionally extend or modify needs based on context
[needs] filter_data = { environment = "production", team = "backend", version = "2.0" } # (1) Use in predicate defaults [needs.global_options.priority] default = "medium" predicates = [ ["environment == 'production'", "high"], ["team == 'backend'", "high"] ]
Example with needimport:
.. needimport:: external_needs.json :filter: environment == 'production' and version == '2.0'
Example with needextend:
.. needextend:: team == 'backend' :status: critical
Common use cases:
Setting environment-specific defaults (development, staging, production)
Filtering imported needs based on release version or team ownership
Applying team or project-specific configurations
Conditional formatting or validation based on build context
Dynamic behavior in CI/CD pipelines
needs_json¶
This provides configuration for the Needs Index tree view
[needs_json]
# Path to the needs.json file
path = "relative/path/to/needs.json"
# Optional path to resolve source locations against
src = "."
parse¶
This provides configuration for parsing of source files, allowing you to extend the built-in reStructuredText directives and roles.
[parse]
# A list of directive names that will not emit a warning if they are unknown.
ignore_directives = ["my-custom-directive", "experimental"]
# A map of directive names to extend the built-in directives with.
[parse.extend_directives.my-admonition]
argument = true # Whether the directive can have an argument
options = true # Whether the directive can have options
content = true # Whether the directive can have content
content_required = false # Whether a warning should be emitted if the directive has no content
parse_content = true # Whether the directive content should be parsed as reStructuredText
description = "A custom admonition directive" # A description of the directive
extension = "my-extension" # The extension that provides the directive
# Named options for the directive
[parse.extend_directives.my-admonition.named_options]
class = { description = "CSS classes to apply" }
name = { description = "A name for the admonition" }
# A map of role names to extend the built-in roles with.
[parse.extend_roles.my-role]
description = "A custom role for special text" # A description of the role
extension = "my-extension" # The extension that provides the role
Core Options¶
- ignore_directives
Type:
array(default:[])List of directive names that won’t trigger warnings when encountered but not recognized by the parser. Useful for custom directives from external extensions.
ignore_directives = [ "my-custom-directive", "experimental-feature", "legacy-directive" ]
Extending Directives¶
The extend_directives section allows you to define custom directives or override built-in directive behavior. Each directive is configured as a subsection:
[parse.extend_directives.my-directive]
argument = true
options = true
content = true
content_required = false
parse_content = true
description = "My custom directive"
extension = "my-package"
# Define named options
[parse.extend_directives.my-directive.named_options]
title = { description = "The title of the element" }
class = { description = "CSS classes to apply" }
Directive Configuration Options:
- argument
Type:
boolean(default:false)Whether the directive accepts an argument (text on the same line as the directive name).
.. my-directive:: This is the argument Content here.
- options
Type:
boolean(default:false)Whether the directive accepts options (field list immediately after the directive line).
.. my-directive:: :option1: value1 :option2: value2 Content here.
- content
Type:
boolean(default:false)Whether the directive can have content (indented text block after options).
- content_required
Type:
boolean(default:false)When
true, emit a warning if the directive has no content when content is expected.- parse_content
Type:
boolean(default:false)When
true, parse the directive content as reStructuredText instead of treating it as literal text.- description
Type:
string(default:"")Human-readable description of what the directive does.
- extension
Type:
string(default:"")Name of the extension or package that provides this directive.
- named_options
Type:
object(default:{})Map defining the specific options this directive accepts. Each option can have a description.
[parse.extend_directives.figure.named_options] width = { description = "Width of the figure" } height = { description = "Height of the figure" } alt = { description = "Alternative text for accessibility" }
Extending Roles¶
The extend_roles section allows you to define custom inline roles:
[parse.extend_roles.api]
description = "Reference to an API endpoint"
extension = "my-api-docs"
[parse.extend_roles.issue]
description = "Reference to a GitHub issue"
extension = "github-integration"
Role Configuration Options:
- description
Type:
string(default:"")Human-readable description of what the role does.
- extension
Type:
string(default:"")Name of the extension or package that provides this role.
Example Usage¶
Once defined in configuration, you can use custom directives and roles in your RST files:
This is a paragraph with a :api:`/users/create` endpoint reference
and an :issue:`123` issue reference.
.. my-admonition:: Important Notice
:class: warning highlight
:name: security-note
This is custom admonition content that will be parsed as RST.
Common Patterns¶
Sphinx Extension Integration: Define directives from Sphinx extensions you use:
[parse.extend_directives.automodule]
argument = true
options = true
description = "Automatically document a Python module"
extension = "sphinx.ext.autodoc"
[parse.extend_directives.automodule.named_options]
members = { description = "Include module members" }
undoc-members = { description = "Include undocumented members" }
Custom Documentation Patterns: Define project-specific directives:
[parse.extend_directives.api-endpoint]
argument = true
options = true
content = true
description = "Document an API endpoint"
extension = "project-docs"
[parse.extend_directives.api-endpoint.named_options]
method = { description = "HTTP method (GET, POST, etc.)" }
path = { description = "URL path pattern" }
deprecated = { description = "Mark as deprecated" }
project¶
This provides configuration for the project.
[project]
# Project name
name = "My Project"
# Project version
version = "1.0.0"
# Project description
description = "My project description"
# A directory, used for resolving paths in certain directives (defaults to config directory).
srcdir = "src"
lint¶
This provides configuration for linting of projects.
[lint]
# List of linting codes to ignore
ignore = ["block.title_line"]
# A list of linting codes to select in LSP file diagnostics
# This overrides the ignore list.
lsp_select = ["block.title_line"]
- ignore
Type:
array(default:[])List of linting error codes to ignore globally across the project.
- lsp_select
Type:
array(default:[])List of linting codes to specifically enable in Language Server Protocol (LSP) file diagnostics. This setting overrides the ignore list, allowing you to see specific errors in your editor even if they’re globally ignored.
Deprecated since version 0.18.0: The rst_lint configuration section has been deprecated. Use lint instead for all linting configuration.
source¶
This provides configuration for discovery of source files in your project. The source configuration determines which files are processed by ubCode.
[source]
# Whether to automatically exclude files ignored by git
respect_gitignore = true
# Files and patterns to include (default: *.rst)
include = ["*.rst"]
# Files and patterns to exclude (has sensible defaults)
exclude = [".git", "_build", "node_modules"]
# Additional patterns to extend the exclude list
extend_exclude = ["temp/**", "*.tmp"]
# Additional patterns to extend the include list
extend_include = ["*.md", "docs/**/*.txt"]
Core Options¶
- respect_gitignore
Type:
boolean(default:true)When enabled, automatically excludes files that are ignored by:
.gitignorefiles.git/info/excludeGlobal gitignore configuration
.ignorefiles (used by tools like ripgrep)
- include
Type:
array(default:["*.rst"])Base list of glob patterns for files to include. By default, only reStructuredText files are processed.
- exclude
Type:
array(default: comprehensive list)Base list of glob patterns for files and directories to exclude. The default list includes common directories that typically don’t contain source documentation:
exclude = [ ".bzr", ".direnv", ".eggs", ".git", ".git-rewrite", ".hg", ".svn", ".venv", ".vscode", "_build", "build", "dist", "node_modules", "site-packages" ]
- extend_exclude
Type:
array(default:[])Additional patterns to add to the exclude list without replacing the defaults.
- extend_include
Type:
array(default:[])Additional patterns to add to the include list without replacing the defaults.
Glob Pattern Types¶
- Single-path patterns
Match anywhere in the directory tree:
directory- matches any directory named “directory”foo.rst- matches any file named “foo.rst”foo_*.rst- matches files like “foo_test.rst”, “foo_doc.rst”
- Relative patterns
Match specific paths relative to the project root:
./foo.rst- matches “foo.rst” in project root onlydirectory/foo.rst- matches “foo.rst” in “directory” onlydirectory/*.rst- matches all RST files in “directory”docs/**/*.rst- matches RST files anywhere under “docs”
Pattern Precedence¶
Exclude patterns take precedence over include patterns. If a file matches both an include and exclude pattern, it will be excluded.
Tip
To see which patterns are active: ubc config
To see all discovered files: ubc build list-documents
Common Configurations¶
Multi-format documentation:
[source]
extend_include = ["*.md", "*.txt"]
extend_exclude = ["README.md", "CHANGELOG.md"]
Excluding build artifacts:
[source]
extend_exclude = [
"build/**",
"_build/**",
"*.tmp",
"temp/**"
]
Including only specific directories:
[source]
include = ["docs/**/*.rst", "specifications/**/*.rst"]
exclude = ["**"] # Exclude everything else
See also
For detailed glob syntax documentation, see the globset documentation.
scripts¶
This key can be used to register custom scripts to run. In VS Code they can be accessed via the command palette (Ctrl+Shift+P) by selecting “ubCode: Run Script in Terminal”.
Each key is a script, and each value is the configuration for that script. Normally the value is an object with different keys with the most important key being cmd which holds the command to execute. However if only cmd is set, then the object is optional.
[scripts]
sphinx1 = "sphinx-build -b html . _build/html {{filepath}}"
sphinx2 = { cmd = "sphinx-build -b html . _build/html {{filepath}}", env = { SPHINXOPTS = "-W" }, terminal = "name", jinja = true }
Additionally, the chain key can be used in place of cmd to run multiple commands in sequence:
[scripts]
rm_build = "rm -rf _build"
sphinx = "sphinx-build -b html . _build/html {{filepath}}"
"sphinx:clean" = { chain = ["rm_build", "sphinx"] }
The following keys are possible for a script:
cmd: The command to execute.chain: A list of scripts to execute in sequence.env: A map of environment variables to set.terminal: What to name the terminal in VS Code. If not set, the terminal will be named after the script key. Terminal names are unique, so if a terminal with the same name already exists, it will be reused.jinja: If True (the default), the command is treated as a jinja template, which can take the following variables:{{ confdir }}: The directory containing the configuration file.{{ filepath }}: The currently active file in VS Code
The current working directory for the script is set as the directory containing the configuration file.
server¶
This provides configuration for the language server that powers the VS Code extension and other editor integrations.
[server]
# Whether to enable hover images on image/figure directive arguments.
hover_images = true
# Whether to enable hover tips for need references.
hover_need_refs = true
# Whether to run background indexing of the project every time a source document is saved.
index_on_save = false
# File patterns considered as image files for autocompletion
image_file_patterns = [
"*.jpg", "*.jpeg", "*.png", "*.gif", "*.svg",
"*.webp", "*.bmp", "*.tiff", "*.tif", "*.ico"
]
- hover_images
Type:
boolean(default:true)When enabled, hovering over image/figure directive arguments in the editor will show a preview of the image.
- hover_need_refs
Type:
boolean(default:true)When enabled, hovering over need references (like
:need:`REQ_001`) will show a tooltip with need information.- index_on_save
Type:
boolean(default:false)When enabled, the language server will automatically reindex the entire project whenever a source document is saved. This keeps need references and cross-links up to date but may impact performance on large projects.
Note
Enabling this feature ensures that need references are always current but may slow down save operations on large projects.
- image_file_patterns
Type:
array(default: extensive list of image formats)List of glob patterns that define which files are considered images. Used for:
Autocompletion in
imageandfiguredirectivesImage preview in hover tooltips
File discovery for image-related features
Default patterns include common formats like:
image_file_patterns = [ "*.jpg", "*.jpeg", "*.png", "*.gif", "*.svg", "*.webp", "*.bmp", "*.tiff", "*.tif", "*.ico", "*.heif", "*.heic", "*.avif", "*.eps", "*.psd", "*.ai", "*.pdf" ]
Performance Considerations¶
For large projects, consider these settings:
[server]
# Disable automatic indexing for better performance
index_on_save = false
# Keep hover features for productivity
hover_images = true
hover_need_refs = true
# Limit image patterns to only used formats
image_file_patterns = ["*.png", "*.jpg", "*.svg"]
format_rst¶
This provides configuration for the reStructuredText formatter, which can automatically format and clean up your RST files.
[format_rst]
# Validation and error handling
fail_on_warning = ["rst.invalid_code_block"]
validate = true
# Indentation settings
blockquote_indent = 2
definition_list_indent = 2
directive_indent = 3
field_list_indent = 2
literal_indent = 2
substitution_indent = 3
# List formatting
enum_list_auto = "preserve"
enum_list_style = "preserve"
# Field list formatting
field_list_align_body = false
field_list_body_on_new_line = 20
# Paragraph formatting
paragraph_line_length = 88
paragraph_semantic_wrap = false
# Table formatting
simple_table_space = 2
# Transition formatting
transition_char = "-"
transition_length = 80
Core Options¶
- fail_on_warning
Type:
array(default:[])List of linting codes that should cause formatting to fail. This is useful in CI/CD pipelines to enforce code quality.
fail_on_warning = ["rst.invalid_code_block", "rst.malformed_table"]
- validate
Type:
boolean(default:true)When
true, the formatter validates that the document structure hasn’t changed after formatting. This prevents accidental content corruption.
Indentation Settings¶
- blockquote_indent
Type:
integer(default:2)Number of spaces to indent blockquotes.
This is a paragraph. This is a blockquote, indented 2 spaces.
- definition_list_indent
Type:
integer(default:2)Number of spaces to indent definition bodies in definition lists.
Term Definition body indented 2 spaces.
- directive_indent
Type:
integer(default:3)Number of spaces to indent directive content.
.. note:: This content is indented 3 spaces.
- field_list_indent
Type:
integer(default:2)Number of spaces to indent field list bodies.
:Author: John Doe Second line indented 2 spaces.- literal_indent
Type:
integer(default:2)Number of spaces to indent literal blocks after paragraphs.
This is a paragraph:: This literal block is indented 2 spaces.
- substitution_indent
Type:
integer(default:3)Number of spaces to indent substitution definition content.
.. |name| replace:: Substitution content indented 3 spaces.
List Formatting¶
- enum_list_auto
Type:
string(default:"preserve")Controls behavior of enumerated lists with auto
#markers:"preserve": Keep original auto markers from source"always": Always use auto markers for subsequent items"never": Never use auto markers for subsequent items
- enum_list_style
Type:
string(default:"preserve")Controls the style of enumerated list markers:
"preserve": Keep original style from source"period": Use periods (1.,2.,3.)"rparen": Use right parenthesis (1),2),3))"parens": Use parentheses ((1),(2),(3))
Field List Formatting¶
- field_list_align_body
Type:
boolean(default:false)When
true, align field list body continuation lines with the first line.# When false (default): :Field: This is the body and this continues on next line. # When true: :Field: This is the body and this aligns with first line.
- field_list_body_on_new_line
Type:
integer(default:20)Field name length threshold. When a field name exceeds this length, the body starts on a new line.
:Short: Body on same line. :This is a very long field name: Body starts on new line due to length.
Paragraph Formatting¶
- paragraph_line_length
Type:
integerornull(default:null)Target line length for paragraph wrapping. When set, paragraphs are wrapped at word boundaries near this length. Not a hard limit and won’t wrap paragraphs in tables.
paragraph_line_length = 88 # Wrap paragraphs around 88 characters
- paragraph_semantic_wrap
Type:
boolean(default:false)When
true, wrap paragraphs at semantic boundaries rather than arbitrary line lengths:Always wrap at sentence boundaries (
[.!?] [A-Z])May also wrap at clause boundaries (
[,;]) ifparagraph_line_lengthis set
# With semantic wrapping: This is a sentence. This is another sentence with a clause, and here's the rest.
Table Formatting¶
- simple_table_space
Type:
integer(default:2)Number of spaces between columns in simple tables.
==== ==== ==== A B C ==== ==== ==== 1 2 3 ==== ==== ====
Transition Formatting¶
- transition_char
Type:
stringornull(default:null)Character to use for transition lines. When
null, preserves original characters.Available options:
"-","=","~","^",".","+","_","#"- transition_length
Type:
integer(default:10)Length of transition lines in characters.
-------- # 8 character transition with "-"
Complete Configuration Examples¶
This section provides complete, real-world configuration examples for different types of projects.
Basic Documentation Project¶
A minimal configuration for a simple documentation project:
"$schema" = "https://ubcode.useblocks.com/ubproject.schema.json"
[project]
name = "My Documentation"
version = "1.0.0"
description = "User documentation for our product"
[needs]
id_required = true
id_regex = "^[A-Z]{3}_[0-9]{3}$" # Format: ABC_123
[[needs.types]]
directive = "requirement"
title = "Requirement"
prefix = "REQ_"
color = "#BFD8D2"
Software Development Project¶
Configuration for a software project with comprehensive need tracking:
"$schema" = "https://ubcode.useblocks.com/ubproject.schema.json"
[project]
name = "MyApp"
version = "2.1.0"
description = "Mobile application requirements"
srcdir = "docs"
[needs]
id_required = true
id_regex = "^[A-Z0-9_]{5,}$"
id_length = 8
# Define comprehensive need types
[[needs.types]]
directive = "epic"
title = "Epic"
prefix = "EPIC_"
color = "#FF6B6B"
[[needs.types]]
directive = "story"
title = "User Story"
prefix = "STORY_"
color = "#4ECDC4"
[[needs.types]]
directive = "task"
title = "Task"
prefix = "TASK_"
color = "#45B7D1"
[[needs.types]]
directive = "bug"
title = "Bug"
prefix = "BUG_"
color = "#F39C12"
# Define relationships
[[needs.extra_links]]
option = "implements"
incoming = "implemented by"
outgoing = "implements"
copy = false
color = "#2ECC71"
[[needs.extra_links]]
option = "blocks"
incoming = "blocked by"
outgoing = "blocks"
color = "#E74C3C"
# Define status workflow
[[needs.statuses]]
name = "draft"
description = "Initial draft"
[[needs.statuses]]
name = "review"
description = "Under review"
[[needs.statuses]]
name = "approved"
description = "Approved for implementation"
[[needs.statuses]]
name = "done"
description = "Completed"
# Custom fields
extra_options = [
{name = "priority", description = "Priority level"},
{name = "effort", description = "Story points"},
{name = "assignee", description = "Assigned team member"}
]
# Default values with conditions
[needs.global_options.priority]
default = "medium"
[needs.global_options.status]
default = "draft"
predicates = [
[["type", "bug"], "review"],
[["priority", "critical"], "review"]
]
Multi-Team Enterprise Configuration¶
Configuration for large organizations with multiple teams and external dependencies:
"$schema" = "https://ubcode.useblocks.com/ubproject.schema.json"
extend = "../shared/base-config.toml"
[project]
name = "Platform API"
version = "3.2.0"
description = "Core platform API requirements"
[needs]
# Import from other team's exports
[needs.import_keys]
frontend = "../frontend-team/needs.json"
mobile = "../mobile-team/needs.json"
# Load external needs from other projects
[[needs.external_needs]]
json_path = "../security-team/security-requirements.json"
id_prefix = "SEC"
base_url = "https://security-docs.company.com"
target_url = "requirements/{{ id }}.html"
[[needs.external_needs]]
json_url = "https://compliance.company.com/api/needs.json"
id_prefix = "COMP"
base_url = "https://compliance.company.com"
css_class = "compliance-need"
# Advanced link types for traceability
[[needs.extra_links]]
option = "validates"
incoming = "validated by"
outgoing = "validates"
color = "#9B59B6"
[[needs.extra_links]]
option = "derives_from"
incoming = "parent of"
outgoing = "derives from"
color = "#34495E"
# Rich metadata with schema validation
extra_options = [
{name = "component", description = "System component"},
{name = "risk_level", description = "Security risk assessment"},
{name = "test_coverage", description = "Test coverage percentage"}
]
# Variant options for conditional content
variant_options = ["component", "environment"]
# Additional context for conditional defaults
filter_data = {environment = "production", compliance_level = "strict"}
# Conditional defaults based on filter data
[needs.global_options.risk_level]
default = "low"
predicates = [
["compliance_level == 'strict'", "medium"],
["environment == 'production'", "high"]
]
[format_rst]
# Enforce consistent formatting
paragraph_line_length = 88
paragraph_semantic_wrap = true
validate = true
fail_on_warning = ["rst.malformed_table"]
[lint]
# Project-specific linting rules
ignore = ["needs.id_not_found"] # Allow forward references
lsp_select = ["needs.title_missing", "rst.malformed_table"]
[server]
# Optimize for large project
index_on_save = false
hover_need_refs = true
[source]
# Multi-format support
extend_include = ["*.md"]
extend_exclude = ["archive/**", "drafts/**"]
[scripts]
# Team workflows
validate = "ubc lint --fail-on-error"
export = "ubc build needs-json --output needs.json"
"docs:build" = { chain = ["validate", "export"], terminal = "docs-build" }
Sphinx Integration Example¶
Configuration optimized for Sphinx documentation projects:
"$schema" = "https://ubcode.useblocks.com/ubproject.schema.json"
[project]
name = "API Documentation"
srcdir = "source"
[needs]
# Integrate with Sphinx-Needs
external_needs = []
[[needs.types]]
directive = "requirement"
title = "Requirement"
prefix = "R_"
color = "#BFD8D2"
[[needs.types]]
directive = "specification"
title = "Specification"
prefix = "S_"
color = "#FEDCD2"
# Link to API documentation
[[needs.extra_links]]
option = "api"
incoming = "documented by"
outgoing = "documents API"
[parse]
# Sphinx directive support
[parse.extend_directives.automodule]
argument = true
options = true
description = "Auto-document Python module"
extension = "sphinx.ext.autodoc"
[parse.extend_directives.automodule.named_options]
members = {description = "Include module members"}
undoc-members = {description = "Include undocumented members"}
[parse.extend_roles.py-func]
description = "Reference to Python function"
extension = "sphinx.domains.python"
[format_rst]
# Sphinx-friendly formatting
paragraph_line_length = 79 # PEP 8 line length
directive_indent = 3
field_list_indent = 2
[scripts]
# Sphinx build commands
html = "sphinx-build -b html {{confdir}} {{confdir}}/_build/html"
linkcheck = "sphinx-build -b linkcheck {{confdir}} {{confdir}}/_build/linkcheck"
"docs:live" = { cmd = "sphinx-autobuild {{confdir}} {{confdir}}/_build/html --host 0.0.0.0", terminal = "docs-server" }