Outline Extraction Rule Reference
Outline extraction rules tell ast-grep outline how to turn parsed source code into outline entries.
Most users do not need to write these rules. ast-grep ships bundled extractors for supported languages. Write custom outline rules when:
- a supported language misses syntax your project uses;
- you use a custom language registered in
sgconfig.yml; - you want a project-specific outline shape.
For a custom language registered in sgconfig.yml, attach its outline rule file with outlineRules:
customLanguages:
mylang:
libraryPath: parsers/mylang.so
extensions: [mylang]
outlineRules: outline/mylang.ymloutlineRules is resolved relative to sgconfig.yml. ast-grep outline loads these configured custom language rules automatically.
For one-off or extra extractor files, pass --outline-rules:
ast-grep outline src --outline-rules project-outline.ymlRules configured in customLanguages are loaded before command-line --outline-rules files.
Replace bundled rules completely with:
ast-grep outline src \
--no-default-outline-rules \
--outline-rules project-outline.ymlRule File Format
An outline rule file is a stream of YAML documents. Each document defines one extractor.
id: rust-struct
language: Rust
role: item
symbolType: struct
rule:
pattern: $VIS struct $NAME { $$$BODY }
name: $NAME
isExported:
has:
regex: '^pub\b'
---
id: rust-field
language: Rust
role: member
parentRuleIds: [rust-struct]
symbolType: field
rule:
pattern: $VIS $NAME: $TYPE
name: $NAME
signature: $VIS $NAME: $TYPE
isPublic:
has:
regex: '^pub\b'rule, constraints, utils, and transform use the same ast-grep YAML fields as normal rules. Outline rules add metadata for output placement, symbol type, names, signatures, and visibility flags.
If a top-level item extractor omits isImport, it defaults to false. If it omits isExported, it defaults to true. If a member extractor omits isPublic, it defaults to true. Set these fields explicitly when the default would make --items imports, --items exports, or --pub-members misleading.
Extractor Fields
id
- type:
String - required: true
Stable extractor id used in diagnostics and parentRuleIds.
id: ts-classlanguage
- type:
String - required: true
The language this extractor applies to. Use a built-in ast-grep language name or a custom language registered in sgconfig.yml.
language: TypeScriptrole
- type:
item | member - required: true
Controls where the extracted entry appears.
item: top-level file or module structure, including declarations, imports, and explicit exports.member: direct child structure under an item, such as fields, methods, constructors, enum variants, or module children.
role: itemparentRuleIds
- type:
String[] - required: true for
role: member
Lists item extractor ids that can contain this member.
parentRuleIds: [ts-class, ts-interface]parentRuleIds references extractor ids, not symbol names or symbol types. Actual member attachment is based on syntax containment. outline does not attach members by matching names, receiver types, imports, traits, or references.
symbolType
- type:
String - required: true
The outline category for the entry. Values use lower camel case names compatible with LSP SymbolKind.
Common values:
| Source construct | symbolType |
|---|---|
| File-level source unit | file |
| Import or module dependency | module |
| Module declaration | module |
| Namespace declaration | namespace |
| Package declaration | package |
| Class declaration | class |
| Method declaration | method |
| Object or class property | property |
| Struct or class field | field |
| Constructor | constructor |
| Enum declaration | enum |
| Interface, trait, or protocol | interface |
| Free function | function |
| Variable | variable |
| Constant | constant |
| Object or map key | key |
| Enum variant or member | enumMember |
| Struct declaration | struct |
| Operator overload | operator |
| Type or generic parameter | typeParameter |
Do not create custom symbol types for imports or exports. Use symbolType together with isImport and isExported.
rule
- type:
Rule - required: true
The ast-grep rule object that selects the syntax node to turn into an outline entry.
rule:
pattern: function $NAME($$$PARAMS) { $$$BODY }See rule object reference for supported rule syntax.
constraints
- type:
HashMap<String, Rule> - required: false
Additional filters for metavariables, using normal ast-grep constraints.
constraints:
NAME:
regex: '^[A-Z]'utils
- type:
HashMap<String, Rule> - required: false
Local utility rules that can be referenced with matches.
transform
- type:
HashMap<String, Transformation> - required: false
Transform metavariables before using them in name or signature.
transform:
NAME:
replace:
source: $RAW_NAME
replace: '^r#'
by: ''
name: $NAMEname
- type:
String - required: true
Template used to compute the displayed entry name. It can reference captured or transformed metavariables.
name: $NAMEText fields use ast-grep-style template replacement:
$NAME: captured metavariable text.$CLEAN_NAME: transformed metavariable text.- literal text mixed with metavariables.
signature
- type:
String - required: false
Template used to compute the displayed signature.
signature: function $NAME($$$PARAMS)If omitted, outline uses the first non-empty line of the matched node as the signature. This fallback is predictable, but multiline declarations may be more readable with an explicit signature.
isImport
- type:
Boolean | Rule - required: false, defaults to
false - applies to:
role: item
Marks a top-level item as an import or dependency edge.
isImport: trueisExported
- type:
Boolean | Rule - required: false, defaults to
true - applies to:
role: item
Marks a top-level item as part of the local public or exported surface.
isExported:
has:
regex: '^export\b'This is syntax-only. It does not follow re-export chains or resolve module visibility across files.
isPublic
- type:
Boolean | Rule - required: false, defaults to
true - applies to:
role: member
Marks a member as public or externally usable.
isPublic:
has:
regex: '^pub\b'If a member extractor omits isPublic, outline treats the member as public.
Boolean Fields
isImport, isExported, and isPublic can be literal booleans or rule predicates.
isImport: true
isExported: false
isPublic:
has:
regex: '^pub\b'When the value is a rule predicate, it is evaluated against the matched candidate node. Normal ast-grep relational rules such as has and inside keep their usual meaning relative to that candidate.
Prefer one extractor with boolean derivation over duplicated extractors.
# Prefer this.
id: rust-struct
language: Rust
role: item
symbolType: struct
rule:
pattern: $VIS struct $NAME { $$$BODY }
name: $NAME
isExported:
has:
regex: '^pub\b'This handles both:
struct Foo {}
pub struct Bar {}Member Attachment
Member extraction is syntactic.
For each member candidate, outline finds the nearest containing item whose extractor id is listed in parentRuleIds. The member is attached only when it is a direct structural child of that item.
This means:
- class methods can attach to classes;
- enum variants can attach to enums;
- declarations inside modules can attach to modules;
- Rust
implblocks remain top-level items unless a rule extracts members inside theimpl; - Go receiver methods remain top-level items because Go does not nest methods inside type declarations.
outline does not infer membership from names, receiver types, implemented traits, references, imports, or type resolution.
Examples
TypeScript Function
id: ts-function
language: TypeScript
role: item
symbolType: function
rule:
pattern: function $NAME($$$PARAMS) { $$$BODY }
name: $NAME
signature: function $NAME($$$PARAMS)TypeScript Class
id: ts-class
language: TypeScript
role: item
symbolType: class
rule:
any:
- pattern: class $NAME { $$$BODY }
- pattern: export class $NAME { $$$BODY }
name: $NAME
isExported:
any:
- regex: '^export\b'
- inside:
kind: export_statementTypeScript Method
id: ts-method
language: TypeScript
role: member
parentRuleIds: [ts-class]
symbolType: method
rule:
pattern: $NAME($$$PARAMS) { $$$BODY }
name: $NAME
signature: $NAME($$$PARAMS)Rust Import And Re-export
id: rust-use
language: Rust
role: item
symbolType: module
rule:
pattern: $VIS use $TARGET;
transform:
NAME:
replace:
source: $TARGET
replace: '^.*::'
by: ''
name: $NAME
isImport: true
isExported:
has:
regex: '^pub\b'This can represent both ordinary imports and public re-exports:
use crate::parser::Parser;
pub use internal_mod as api;The re-export is one item with both isImport: true and isExported: true.
Custom Languages
For custom languages:
- Register the parser in
sgconfig.ymlwith ast-grep'scustomLanguages. - Write outline extractor documents with
language: <custom-language-name>. - Add the extractor file path to the custom language's
outlineRulesfield. - Run
ast-grep outline.
Conceptual example:
# sgconfig.yml
customLanguages:
mylang:
libraryPath: parsers/mylang.so
extensions: [mylang]
outlineRules: outline/mylang.yml# outline/mylang.yml
id: mylang-function
language: mylang
role: item
symbolType: function
rule:
pattern: def $NAME($$$ARGS) $$$BODY
name: $NAME
signature: def $NAME($$$ARGS)ast-grep outline src -l mylangUnsupported languages return an empty outline and a successful exit status.
What Rules Should Not Do
Outline extraction should stay focused on local file structure. Do not use outline rules to promise semantic facts such as:
- where a symbol is referenced;
- which implementation dispatch will call;
- full transitive public APIs;
- call graphs or data-flow edges;
- normalized relationship fields such as
extends,implements, orimplementedFor; - arbitrary metadata fields such as
async,override,static, or decorators.
For those questions, use normal ast-grep rules, language-specific tools, or an LSP after outline has helped you find the relevant source.