outline
Get the structural skeleton of a Python module or class — names, kinds, signatures, and line spans in a single call. Use it to understand the static structure of any scope.
Instructions
Python: Structural skeleton of a module or class — names, kinds, signatures, line spans.
Returns a nested OutlineTree — the members hierarchy of handle as a
tree of lightweight structural nodes (Stub). Each node carries
handle, kind, scope, line_start, line_end, and
signature when Jedi yields one. No source content anywhere in the tree.
Use resolve() or inspect() first to obtain a canonical handle, then
outline() to see the complete structural skeleton in one call — the
single-call answer to "show me the structure of this scope."
Static-surface ceiling. The tree walks the members edge, so it is
complete over what is statically defined in source but not over runtime.
Runtime-injected members (metaclass / setattr / __getattr__ /
type() / __init_subclass__) are NOT captured — e.g. outline of a
Django Model omits its metaclass-injected _meta / objects /
DoesNotExist. An absent member is "not in source," not "not at runtime."
Absence contracts — an agent MUST read these before consuming the tree.
Contract 1 — children absent ⇔ not expanded.
children present (including children: []) means measured: the
complete set of direct members of this node. children: [] is a genuine
leaf — a container with no members, or a non-container (function/method/
variable). children absent means a cap fired and this node was not
walked — treat it as "unknown," never as empty.
Contract 2 — truncated absent-not-false.
truncated: true is present only on a node that a cap cut off; it
always co-occurs with truncation_reason and an absent children.
Fully-walked nodes omit truncated entirely — truncated: false never
appears.
Truncation reasons (one string per node — not a list):
"max_depth"— at the depth frontier;resolve_memberswas peeked once and found members (a genuine empty container at the frontier getschildren: []instead)."max_nodes"— total-node budget exhausted; no peek performed."external"— external-scope container at depth ≥ 1; no deeper walk into third-party code.
When both max_nodes AND a depth/external cap could apply to the same
node, truncation_reason is "max_nodes" (the harder global bound).
Args:
handle: Canonical Python dotted-name string (from resolve/inspect).
project_path: Project root path (default: current directory).
max_depth: Maximum depth from the root (root is depth 0). None
means unbounded within scope; the external cap and max_nodes
still apply. At the frontier, resolve_members is peeked once
to distinguish a genuine empty container from a cut-off one.
max_nodes: Total-node budget for the tree (root counts as 1, default
200). Containers that exceed the budget are marked
truncated: "max_nodes" without peeking.
Returns:
OutlineTree dict — {"node": Stub, "children": [OutlineTree, ...]}.
Never raises; an unresolvable handle yields a minimal single-node tree
with children: []. Children within each parent are in source order
(sorted by (line_start, handle)); BFS inclusion order bounds the budget
gracefully (all of depth 1 before any of depth 2, etc.).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| handle | Yes | ||
| project_path | No | . | |
| max_depth | No | ||
| max_nodes | No |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||