Inlay Hints
clice renders inline annotations for the information the code leaves implicit: parameter names at call sites, deduced types, and the field names behind positional aggregate initialization. Hint categories can be toggled individually through the [inlay_hints] configuration section; the sections below describe the categories that are on by default.
Parameter Hints
Parameter name hints
Call sites show parameter names for functions and constructors
Hint suppression
Named arguments and /*name=*/ comments suppress parameter hints
Setter and builtin suppression
setX(x) and std::move/std::forward arguments stay bare
Mutable reference markers
& flags arguments passed by non-const lvalue reference
Forwarding resolution
Packs forwarded through wrappers resolve to the target's parameter names
Names from definitions
Unnamed declaration parameters take the definition's names; leading underscores strip
Function pointers and call operators
Indirect calls still name their parameters
Deducing this
The explicit object parameter never hints (C++23)
Dependent calls
Parameter names appear even when the callee is only known inside a template
Candidates are matched by argument count; only a unique surviving candidate names the parameters, so a call that could still hit several overloads stays bare rather than guessing.
Unexpanded packs
A written pack expansion breaks the 1:1 argument mapping and stops hinting
Macros at call sites
Arguments spelled as macros hint; calls generated inside macro bodies do not
Implicit constructor calls
Conversions the code never wrote produce no hints of their own
Pseudo-object expressions
MS property accesses stay quiet; written subscripts keep the accessor's names
Explicit instantiation
An explicit instantiation definition adds no duplicate hints, while its written template arguments hint normally
Sloppy name matching
aParam does not yet suppress an argument spelled param
Inherited constructors
using Base::Base calls lose their parameter names
Anonymous parameters
Unnamed parameters produce no name hint, though mutable references still show &
Operators and literals
Operator syntax and user-defined literals stay bare; member and default member initializers hint
Packs in constructor arguments
Outer calls resolve; hints inside the expansion are still missing
Type Hints
Deduced auto variables
The hint shows the full variable type, qualifiers included
Type sugar length limits
Aliases keep their spelling; over-long types fall back to the sugared name
Structured bindings
Each binding hints its canonical type; the aggregate itself stays bare
Lambdas
Variables, deduced return types, and init-captures all hint
Deduced return types
Deduced return types appear as -> T after the parameter list
decltype spellings
The underlying type shows next to the written decltype
auto parameters
A template with exactly one instantiation reveals the deduced type
Explicitly spelled initializers
Casts and functional casts still hint redundantly
Dependent auto
Deduction inside an uninstantiated template body stays silent
Scope suppression
Namespace qualifiers drop from hints; class scopes stay
Tuple-protocol bindings
Hints print the canonical type, not tuple_element<I, T>::type
Instantiated templates
Instantiated bodies repeat no hints at the pattern; dependent auto could reveal the deduced type while exactly one instantiation exists
Designator Hints
Field and index designators
Positional aggregate initialization shows .field= and [index]=
Nested aggregates
Written braces recurse; omitted braces flatten into .outer.inner=
Anonymous members
Unnamed unions and structs vanish from the designator path
Designator suppression
Written designators and /*name=*/ comments keep their inits bare
Aggregates only
Constructor calls, copies and idiomatic zero-init produce no designators
Broken initializers
Designators survive next to initializers that fail to compile
Parenthesized aggregate initialization
C++20 Point(1, 2) gets no hints yet
Other Hint Kinds
Template parameter hints
Template argument hints are not emitted at call sites yet
CTAD arguments
CTAD does not display deduced class template arguments yet
Implicit conversion hints
Implicit conversions at call sites have no hints yet
Block End Hints
Off by default (inlay_hints.block_end). After the closing brace of a block spanning at least two lines, clice shows the name of what the brace closes — functions, types, namespaces, and control-flow statements:
void Widget::process(const Config& cfg) {
// ...
} // Widget::process
namespace detail {
// ...
} // namespace detail
while (running) {
// ...
} // while runningCondition summaries print for if/while/switch/for where a short spelling exists; an else if chain hints as plain // if. Labels longer than 60 characters are dropped.
A related idea, #endif hints showing the matching condition (clangd#2487), is not implemented.
Default Argument Hints
Off by default (inlay_hints.default_arguments). Call sites that rely on default arguments show what was omitted, abbreviated past the type-name limit:
void log(int level, bool flush = true, int repeat = 1);
log(2);
// ^ , flush: true, repeat: 1Configuration
The [inlay_hints] section of clice.toml (or the same keys via initializationOptions) controls every category: enabled, parameters, deduced_types, designators, block_end, default_arguments, and type_name_limit. See the configuration guide for details. Configuration changes take effect after a server restart — a recompile is never involved.
Interactive Behavior
- Requests are range-scoped: hints outside the requested range are discarded.
- Parameter hints anchor to the left of their argument; type and designator hints anchor to their declaration side with LSP padding flags instead of embedded spaces.
- Identical duplicate hints (e.g. from template instantiations) collapse into one.
Other Known Gaps
- Abbreviated type hints with expandable label parts via
InlayHintLabelPart(clangd#2269) - Clickable type names — go-to-definition on the hinted type (clangd#1535)
- Scope-aware type shortening — print
Barinstead offoo::Barinsidenamespace foo(clangd#2270) - Parameter hints lost when a coroutine returns a template type (clangd#2437)
