Contents Menu Expand Light mode Dark mode Auto light/dark, in light mode Auto light/dark, in dark mode Skip to content
ubCode 0.30.3 documentation
Light Logo Dark Logo

Getting started

  • What is ubCode?
  • Key concepts
  • Installation
  • Quickstart

Configuration & authoring

  • Configuration
    • Needs
    • Schema validation
    • Deprecated needs options
    • Codelinks (source code tracing)
    • Intersphinx
    • Parsing
    • Linting
    • Formatting
    • Server
    • Project, source & scripts
    • HTML site
    • Workflow
    • Quality Analysis
  • Authoring
    • Directives
    • Roles
    • Needs
    • Variants
    • Diagrams
    • Markdown (MyST)
    • Differences from a Sphinx build

Core workflows

  • Needs tutorial
  • Coming from Sphinx-Needs
  • Tracing source code with Codelinks
  • Pharaoh Agentic Engineer
    • Quick start
    • Configuring the workflow
    • Reviews and quality analysis
    • The ubc agent command
    • In VS Code

Guides

  • Writing a filter
  • Writing reports
  • Variant builds
  • Using ubc in CI/CD

Reference

  • Features
    • Home view
    • Linting
    • RST preview
    • Realtime index
    • Model Context Protocol (MCP) server
    • Chat participant
    • Needs filtering
    • Needs graph view
    • Navigation
    • Site Map
    • Commands
    • Diff & impact analysis
    • needs.json view
  • Supported toolchain

Support

  • Troubleshooting
  • Request a license
  • Report an issue

Development

  • Roadmap
  • Changelog
Back to top
View this page
Edit this page

Codelinks (source code tracing)¶

Added in version 0.29.0.

The [codelinks] section configures source code tracing — scanning your source files for traceability markers and converting them into needs. Use this when you want to create or link needs directly from code comments, without writing reStructuredText by hand.

See also

Codelinks documentation

The full Sphinx-Codelinks documentation, covering the Sphinx extension, CLI, and marker formats in depth.

Minimal example¶

[codelinks]
set_remote_url = true

[codelinks.projects.my_app]
remote_url_pattern = "https://github.com/org/repo/blob/{commit}/{path}#L{line}"

[codelinks.projects.my_app.source_discover]
src_dir = "../src"
comment_type = "python"

[codelinks.projects.my_app.analyse]
get_oneline_needs = true

This tells ubCode to scan the ../src directory for Python files, extract one-line need markers from comments, and generate remote URLs pointing to GitHub.

In your reStructuredText files you then include the traced needs with the .. src-trace:: directive:

.. src-trace::
   :project: my_app

Global options¶

These options sit directly under [codelinks] and apply to every project defined within it.

set_local_url

Type: boolean (default: false)

When true, ubCode computes a file:// URL pointing to the local source file for every traced need. The URL is stored in the field named by local_url_field.

[codelinks]
set_local_url = true
local_url_field

Type: string (default: "local-url")

Name of the need field that receives the local file URL. The field is auto-registered in [needs.fields] when set_local_url is enabled; if it already exists with a non-string type, a diagnostic is emitted.

[codelinks]
local_url_field = "local-url"
set_remote_url

Type: boolean (default: false)

When true, ubCode computes a remote URL (e.g. GitHub, GitLab, Bitbucket) for every traced need using the remote_url_pattern defined on each project. The URL is stored in the field named by remote_url_field.

[codelinks]
set_remote_url = true
remote_url_field

Type: string (default: "remote-url")

Name of the need field that receives the remote URL. The field is auto-registered in [needs.fields] when set_remote_url is enabled; if it already exists with a non-string type, a diagnostic is emitted.

[codelinks]
remote_url_field = "remote-url"
outdir

Type: string or null (default: null)

Optional output directory for generated artifacts such as extracted markers and warnings (standalone use only). Most users do not need to set this.

[codelinks]
outdir = "output"

Project-specific options¶

Each source code project is defined under [codelinks.projects.<name>], where <name> is a unique identifier you choose (e.g. my_app, backend). You can define multiple projects when your repository contains several codebases with different languages or configurations.

[codelinks.projects.my_app]
# options for "my_app"

[codelinks.projects.backend]
# options for "backend"

remote_url_pattern¶

Type: string or null (default: null)

URL pattern used to generate links to a remote source code repository. The pattern uses placeholders that ubCode replaces with the actual values at analysis time.

Placeholders:

  • {commit} — the current Git commit hash

  • {path} — relative path to the source file (from the repository root)

  • {line} — 1-based line number of the marker

Common patterns:

  • GitHub: https://github.com/user/repo/blob/{commit}/{path}#L{line}

  • GitLab: https://gitlab.com/user/repo/-/blob/{commit}/{path}#L{line}

  • Bitbucket: https://bitbucket.org/user/repo/src/{commit}/{path}#lines-{line}

[codelinks.projects.my_app]
remote_url_pattern = "https://github.com/org/repo/blob/{commit}/{path}#L{line}"

ref_url_field¶

Type: string (default: "code_url")

Name of the need field that receives the URL resolved from a @need-ids: reference marker (see analyse.need_id_refs).

When a source file carries a @need-ids: REQ_X marker, the marker’s remote URL (or its local URL, when no remote URL is configured) is written onto the already existing need REQ_X under this field. This differs from local_url_field / remote_url_field, which receive the URLs of needs defined in the source code (one-line markers and .. src-trace:: blocks); ref_url_field receives the URL back-attached onto a referenced need.

Point a tests/-scoped project at a different field (e.g. test_url) to keep links to test code separate from links to implementation code.

[codelinks.projects.my_app]
ref_url_field = "code_url"

[codelinks.projects.my_app_tests]
ref_url_field = "test_url"

source_discover¶

Configures how ubCode discovers source files within this project.

[codelinks.projects.my_app.source_discover]
src_dir = "../src"
include = ["**/*.cpp", "**/*.h"]
exclude = ["build/**"]
gitignore = true
comment_type = "cpp"
src_dir

Type: string (default: ".")

Root directory for source file discovery. Paths are resolved relative to the directory containing the ubproject.toml file.

[codelinks.projects.my_app.source_discover]
src_dir = "../src"
include

Type: array of strings (default: [])

Glob patterns for files to include. When non-empty, only files matching at least one pattern are processed. An empty list includes all files (subject to exclude and gitignore filtering).

Files must match at least one include pattern to be considered, but exclude patterns and gitignore rules still apply afterward.

[codelinks.projects.my_app.source_discover]
include = ["**/*.py"]
exclude

Type: array of strings (default: [])

Glob patterns for files and directories to exclude from discovery.

[codelinks.projects.my_app.source_discover]
exclude = ["build/**", "vendor/**"]
gitignore

Type: boolean (default: true)

When true, files matched by .gitignore (and .ignore, .git/info/exclude, and global gitignore) are automatically excluded.

[codelinks.projects.my_app.source_discover]
gitignore = false
follow_links

Type: boolean (default: false)

When true, symbolic links are followed when traversing the source directory tree. By default, symbolic links are not followed.

[codelinks.projects.my_app.source_discover]
follow_links = true
comment_type

Type: string or null (default: null)

The programming language / comment style used in this project’s source files. This determines which file extensions are discovered and how comments are parsed for markers.

This field is required for file discovery. When null, the discovery step fails with an error; set it to one of the supported values below.

Supported values:

Language

Value

Comment syntax

Discovered file extensions

C / C++

"cpp"

// (single-line), /* */ (multi-line)

.cpp, .hpp, .h, .cc, .hh, .c++, .h++

Python

"python"

# (single-line), """ """ (docstrings)

.py

Rust

"rust"

// (single-line), /* */ (multi-line), /// and //! (doc comments)

.rs

C#

"csharp"

// (single-line), /* */ (multi-line), /// (XML doc comments)

.cs

YAML

"yaml"

# (single-line)

.yaml, .yml

Bash / Shell

"bash"

# (single-line)

.sh, .bash, .zsh, .ksh

[codelinks.projects.my_app.source_discover]
comment_type = "python"

analyse¶

Configures how ubCode analyses source files to extract markers from comments.

[codelinks.projects.my_app.analyse]
get_oneline_needs = true
get_need_id_refs = true
get_rst = false
get_oneline_needs

Type: boolean (default: true)

Whether to extract one-line needs from comments. A one-line need is a compact marker like:

// @Function Bar, IMPL_4, impl, [SPEC_1]

which ubCode converts to a need with title “Function Bar”, ID IMPL_4, type impl, and a link to SPEC_1. The marker format is controlled by oneline_comment_style below.

get_need_id_refs

Type: boolean (default: true)

Whether to extract need-ID reference markers from comments. A need-ID reference links a code location to existing needs without creating new ones:

// @need-ids: REQ_001, REQ_002

The marker strings are configured via need_id_refs.markers.

get_rst

Type: boolean (default: false)

Whether to extract marked RST blocks from comments. A marked RST block lets you embed full reStructuredText inside a source code comment:

// @rst
// .. req:: My Requirement
//    :id: REQ_INLINE
//
//    This requirement lives in source code.
// @endrst

The start and end sequences are configured via marked_rst.

git_root

Type: string or null (default: null)

Explicit path to the Git repository root. Useful in non-standard layouts (e.g. Bazel builds, monorepo sub-projects) where auto-detection of .git would fail. When null, ubCode traverses parent directories automatically. Paths are resolved relative to the ubproject.toml file.

[codelinks.projects.my_app.analyse]
git_root = "/path/to/repo"

analyse.oneline_comment_style¶

Defines the format of one-line markers. Fields are positional: the order in needs_fields determines which comma-separated value maps to which need field.

[codelinks.projects.my_app.analyse.oneline_comment_style]
start_sequence = "@"
end_sequence = "\n"
field_split_char = ","
needs_fields = [
    { name = "title", type = "str" },
    { name = "id", type = "str" },
    { name = "type", type = "str", default = "impl" },
    { name = "links", type = "list[str]", default = [] },
]

With this configuration, the comment:

// @Function Bar, IMPL_4, impl, [SPEC_1, SPEC_2]

produces a need equivalent to:

.. impl:: Function Bar
   :id: IMPL_4
   :links: SPEC_1, SPEC_2
start_sequence

Type: string (default: "@")

Character sequence that begins a one-line marker inside a comment.

end_sequence

Type: string (default: "\n")

Character sequence that ends a one-line marker. The default (newline) means each marker occupies a single comment line.

field_split_char

Type: string (default: ",")

Character used to split the marker into individual field values.

needs_fields

Type: array of objects (at least 1 entry required)

Ordered list of field definitions. Each entry describes one positional field in the marker:

name

Type: string (required)

The need field to populate (e.g. "title", "id", "type").

"str"-typed fields must exist in [needs.fields], and "list[str]"-typed fields must exist in [needs.links]; missing entries produce a warning diagnostic at startup.

type

Type: "str" or "list[str]" (default: "str")

  • "str" — a plain string value.

  • "list[str]" — a bracketed, comma-separated list (e.g. [SPEC_1, SPEC_2]).

default

Type: string, array of strings, or null (default: null)

Default value when the field is omitted from the marker. null means the field is required.

Important

The title and type fields (or their equivalents) must always be present in needs_fields, as they are mandatory for every need.

analyse.need_id_refs¶

Configures how need-ID reference markers are recognised.

[codelinks.projects.my_app.analyse.need_id_refs]
markers = ["@need-ids:"]
markers

Type: array of strings (at least 1 entry required, default: ["@need-ids:"])

Marker strings that identify need-ID references in comments. When ubCode encounters a comment containing one of these markers, everything after the marker is parsed as a comma-separated list of need IDs.

// @need-ids: REQ_001, REQ_002

analyse.marked_rst¶

Configures the delimiters for marked RST blocks embedded in comments.

[codelinks.projects.my_app.analyse.marked_rst]
start_sequence = "@rst"
end_sequence = "@endrst"
start_sequence

Type: string (default: "@rst")

Sequence that begins a marked RST block inside a comment.

end_sequence

Type: string (default: "@endrst")

Sequence that ends a marked RST block.

analyse.preprocessor¶

Added in version 0.31.0.

By default, C/C++ files are scanned with a tree-sitter parser that finds markers in every comment — including comments inside #if / #ifdef branches that the compiler would never build.

Adding the [codelinks.projects.<name>.analyse.preprocessor] table, even when it is empty, switches C/C++ files to a preprocessor-aware libclang engine that sees the source as a compiler does: markers in inactive #if / #ifdef branches are excluded, and only markers in the branches that are actually compiled become needs.

[codelinks.projects.my_app.analyse.preprocessor]
# An empty table is enough — its presence selects the libclang engine.

Only files discovered as C/C++ (comment_type = "cpp") use this engine; files of every other language continue to use tree-sitter.

compile_commands

Type: string or null (default: null)

Path to a compile_commands.json compilation database, from which each file’s real compiler flags are taken. When null, the database is discovered by walking up from each source file’s directory, stopping at the project root. Paths are resolved relative to the ubproject.toml file.

[codelinks.projects.my_app.analyse.preprocessor]
compile_commands = "../build/compile_commands.json"
defines

Type: array of strings (default: [])

Preprocessor defines, each written as NAME or NAME=VALUE, applied as -D flags. These are the fallback used for files that no compile_commands.json entry applies to.

[codelinks.projects.my_app.analyse.preprocessor]
defines = ["FEATURE_X", "MAX_ITEMS=32"]
includes

Type: array of strings (default: [])

Include directories, applied as -I flags on the same fallback path as defines. Paths are resolved relative to the ubproject.toml file.

[codelinks.projects.my_app.analyse.preprocessor]
includes = ["../include", "../vendor/include"]
std

Type: string (default: "c++17")

The C/C++ standard used on the fallback parse path (e.g. "c++17", "c++20", "c11"); it also decides whether a file is parsed as C or as C++. Files matched by a compile_commands.json entry use that entry’s own flags instead, including its own standard.

[codelinks.projects.my_app.analyse.preprocessor]
std = "c++20"

A worked example — an out-of-source build directory for the flags, plus fallback flags for the headers the build does not compile directly:

[codelinks.projects.my_app.source_discover]
src_dir = "../src"
include = ["**/*.cpp", "**/*.h"]
comment_type = "cpp"

[codelinks.projects.my_app.analyse.preprocessor]
compile_commands = "../build/compile_commands.json"
defines = ["FEATURE_X=1", "NDEBUG"]
includes = ["../include"]
std = "c++17"

How the compilation database is applied:

For every C/C++ file, ubCode looks for a matching entry in the applicable compile_commands.json (the explicit compile_commands path, or the one found by walking up):

  • The file has an entry — it is parsed with that entry’s own flags, and defines, includes and std are not used for it.

  • A translation-unit source (.c, .cpp, .cc, .cxx) with no entry — it is skipped, and no markers are extracted from it. A compilation database lists every source the build compiles, so a source that is missing from it is one the build does not compile, and there is no correct set of flags to parse it with.

  • A header (e.g. .h, .hpp, .hh, .hxx) with no entry — it is parsed standalone with defines, includes and std. Compilation databases never list headers, so this is the normal case for them.

When no database is found at all, every file is parsed standalone with defines, includes and std.

Warning

Only GCC/Clang-style flags in compile_commands.json are interpreted. MSVC cl.exe syntax (/D NAME, /I dir, /std:c++17) is not: such flags are dropped rather than translated, and because the file does have a database entry the defines / includes / std fallback does not apply to it either, so it is parsed with no defines or include paths at all. For MSVC projects, either generate a Clang-style database (for example with clang-cl, or a CMake Ninja/Makefile generator), or drop compile_commands and set defines, includes and std explicitly.

Providing libclang:

The libclang engine needs a libclang library, version 16 or newer, the first time it parses a C/C++ file. It is located in this order:

  1. LIBCLANG_PATH, if you have set it. This is treated as a deliberate choice: if the library it names cannot be loaded, or is older than version 16, the parse fails with an error rather than falling back.

  2. A libclang already installed on the system, provided it is version 16 or newer. An older system library is not used — ubCode falls through to the next step instead.

  3. Otherwise, ubCode downloads the pinned libclang wheel from PyPI, verifies it against pinned SHA-256 checksums, and caches the extracted library per user so later runs need no network access.

Once step 3 has run on a machine, the cached pinned library is used in preference to a system libclang on every later run, because it is the version extraction is verified against. Set LIBCLANG_PATH if you want a specific library instead.

Note

For an internal mirror or an air-gapped environment, point the download at a PyPI-compatible index with UBC_LIBCLANG_INDEX_URL. If it is unset, ubCode also honours the index variables you may already have configured for your Python tooling, in this order: UV_DEFAULT_INDEX, UV_INDEX_URL, then PIP_INDEX_URL. The index only decides where the library is fetched from — what is accepted is fixed by the pinned checksums, so a mirror serving a different artifact is rejected.

Alternatively, install libclang 16 or newer yourself and set LIBCLANG_PATH to the directory containing the library.

The .. src-trace:: directive¶

Once you have configured a codelinks project, include the traced needs in your documentation using the .. src-trace:: directive:

.. src-trace::
   :project: my_app

The directive accepts the following options:

:project:

Required. The project name as defined under [codelinks.projects.<name>].

:file:

Limit tracing to a single source file (relative to src_dir).

.. src-trace::
   :project: my_app
   :file: main.cpp
:directory:

Limit tracing to files within a subdirectory (relative to src_dir).

.. src-trace::
   :project: my_app
   :directory: core/

When neither :file: nor :directory: is given, all files under src_dir are included. Multiple .. src-trace:: directives can appear in the same document to combine needs from different projects or scopes.

Note

The :file: and :directory: options cannot be used together on the same directive.

Automatic field registration¶

When set_local_url or set_remote_url is enabled, ubCode automatically adds the corresponding URL field (local_url_field / remote_url_field) to [needs.fields] as a string field. You do not need to declare it manually.

If the field already exists with a compatible string type, the existing definition is kept unchanged. If it exists with a non-string type, a warning diagnostic is emitted.

Similarly, "str"-typed entries in needs_fields are cross-validated against [needs.fields], and "list[str]"-typed entries are cross-validated against [needs.links]. Missing entries produce warning diagnostics at startup so you can add the field or link type definition before tracing fails.

Complete example¶

"$schema" = "https://ubcode.useblocks.com/ubproject.schema.json"

[needs]
id_required = true

[[needs.types]]
directive = "impl"
title = "Implementation"
prefix = "IMPL_"

[[needs.types]]
directive = "req"
title = "Requirement"
prefix = "REQ_"

[needs.fields.source_file]
description = "Source file for codelinks needs"

[needs.links.implements]
incoming = "implemented by"
outgoing = "implements"

# --- Codelinks configuration ---

[codelinks]
set_remote_url = true
remote_url_field = "remote-url"

[codelinks.projects.my_app]
remote_url_pattern = "https://github.com/org/repo/blob/{commit}/{path}#L{line}"

[codelinks.projects.my_app.source_discover]
src_dir = "../src"
include = ["**/*.cpp", "**/*.h"]
gitignore = true
comment_type = "cpp"

[codelinks.projects.my_app.analyse]
get_oneline_needs = true
get_need_id_refs = true
get_rst = false

[codelinks.projects.my_app.analyse.oneline_comment_style]
start_sequence = "@"
field_split_char = ","
needs_fields = [
    { name = "title", type = "str" },
    { name = "id", type = "str" },
    { name = "type", type = "str", default = "impl" },
    { name = "implements", type = "list[str]", default = [] },
]

[codelinks.projects.my_app.analyse.need_id_refs]
markers = ["@need-ids:"]

[codelinks.projects.my_app.analyse.marked_rst]
start_sequence = "@rst"
end_sequence = "@endrst"

# Optional: use the preprocessor-aware libclang engine for the C/C++ files,
# so that markers in inactive #if / #ifdef branches are excluded.
[codelinks.projects.my_app.analyse.preprocessor]
compile_commands = "../build/compile_commands.json"
defines = ["FEATURE_X=1"]
includes = ["../include"]
std = "c++17"
Next
Intersphinx
Previous
Deprecated needs options
Copyright © 2026, team useblocks
Made with Sphinx and @pradyunsg's Furo
On this page
  • Codelinks (source code tracing)
    • Minimal example
    • Global options
    • Project-specific options
      • remote_url_pattern
      • ref_url_field
      • source_discover
      • analyse
      • analyse.oneline_comment_style
      • analyse.need_id_refs
      • analyse.marked_rst
      • analyse.preprocessor
    • The .. src-trace:: directive
    • Automatic field registration
    • Complete example