Getting Started

How to Edit Your CoPilot Command Code: Defining and Using Inputs

Written by

BIMLOGIQ

Published

Nov 24, 2025

Getting Started

How to Edit Your CoPilot Command Code: Defining and Using Inputs

Written by

BIMLOGIQ

Published

Nov 24, 2025

Getting Started

How to Edit Your CoPilot Command Code: Defining and Using Inputs

Written by

BIMLOGIQ

Published

Nov 24, 2025

Understanding Inputs in CoPilot Commands

Every CoPilot command can receive information from the user.
This information is collected through inputs—small parameters that appear in the command UI when the user runs your command.

Inputs allow you to:

  • Ask the user for names, numbers, and text

  • Let the user select Revit categories, types, and elements

  • Enable or disable behaviors

  • Pick files or configure options before execution

  • Build flexible commands that adapt to each project’s needs

In other words, inputs are the bridge between the user and your command logic.
By defining inputs correctly, you control what information the user must provide, what is optional, and what controls are shown in the UI.

Defining inputs is extremely simple:
you only need to write small annotation blocks above each variable, and CoPilot automatically turns them into UI components for the user.

This section explains:

  • What types of inputs you can define

  • How each type appears in the UI

  • How to make inputs optional or multi-select

  • How to use editors (category selector, element selector, file picker, etc.)

  • Where to place the input definitions inside your command

After reading this section, you will know exactly how to design inputs that make your commands clear, flexible, and user-friendly.


Definition of Inputs

Commands in CoPilot can have one or more inputs.
Each input has a type, which defines what kind of value the user can provide and how it is shown in the UI.

Inputs in a command can be one of the following types:

Input type

Description

C# Type

Examples

String

Text value entered by the user.

string

Name, code, note, parameter value

Integer

Whole number value.

int

Count, index, quantity

Double

Floating-point number.

double

Length, ratio, scale factor

Boolean

True/false flag shown as a checkbox.

bool

Enable/disable options, switches

List of IDs (elements, categories, types)

Multiple IDs representing Revit objects.

long

Multi-selection of sheets, views, categories, etc.


Forms of Each Input Type

Every input type can appear in one of the following forms:

Type of input

Description

Syntax

Mandatory single value

User must provide a value.

T VALUE;

Optional single value

User can leave empty.

T? VALUE_OPTIONAL;

Mandatory multi-select

User must select at least one item.

T[] VALUES;

Optional multi-select

User may select zero, one, or many.

T[]? VALUES_OPTIONAL;

 

How to Define an Input

To define an input, you must place a structured annotation block directly above the variable declaration:


// @title <Title shown in the UI>
// @description <Short explanation of the input>
// @editor <Editor type (optional; required only for special editors)>
// @editorConfig <Additional configuration (only for advanced editors)>
T PARAMETER_NAME


Meaning of the fields

  • T — The data type (e.g., string, int, bool, long, string[], etc.)

  • PARAMETER_NAME — The variable name you will use inside your command code

  • @editor — Used only when selecting elements, categories, classes, or files

  • @editorConfig — Provides filters and additional settings for special editors


Where to Place Inputs

All inputs must be declared at the beginning of your command code, inside a dedicated block:

// vars start

// All your input fields go here

// vars end

This ensures CoPilot can detect and expose your parameters properly in the UI.

Example: Complete Input Definition

Here is a simple example showing two inputs — one string and one integer — placed correctly inside the vars block:

// vars start

// @title Sheet Name
// @description The name that will be applied to the created sheet.
string SHEET_NAME;

// @title Starting Sheet Number
// @description The initial number used when creating multiple sheets.
int STARTING_NUMBER;

// vars end

CoPilot will display these inputs as two fields in the UI:

  • A text box labeled Sheet Name

  • A numeric box labeled Starting Sheet Number

And your command code can then use SHEET_NAME and STARTING_NUMBER normally.


Using Inputs Inside Your Command Code

All inputs are declared inside the // vars start and // vars end block.
After this block, your command logic begins. The variables you defined above become regular C# variables you can read, validate, and convert.

For many selectors (category, class, element, picker, etc.), the input type is long.
This long value is the Revit element ID of the selected item.
Before you can use it, you usually need to:

  1. Validate that a value was actually provided (not a default like -1).

  2. Convert the long to ElementId.

  3. Get the actual Element (or a specific type like Room, View, FamilyInstance, etc.) from the document.

  4. Use that element in your logic.


Example of usage:

using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.DB.Structure;
using Autodesk.Revit.DB.Plumbing;
using Autodesk.Revit.DB.Electrical;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using Autodesk.Revit.Attributes;
using DocumentFormat.OpenXml;

// vars start
// @title Selection
// @description Select elements in the Revit document to count
// @editor elementSelector
// @editorConfig {"statusPrompt": "Select elements to count"}
long[] selection;
// vars end

// Get the current document from the UIDocument
Document doc = UIDoc?.Document;

// Validate that the document is available
if (doc == null)
{
    Logger.AppendLine("- **Error:** Document is not available.");
    return "Document is not available.";
}

// Convert long array to ElementId collection
List<ElementId> selectedElementIds = new List<ElementId>();
if (selection != null && selection.Length > 0)
{
    foreach (long id in selection)
    {
        CheckCancellationRequested();
        selectedElementIds.Add(new ElementId(id));
    }
}

Logger.AppendLine($"- Retrieved **{selectedElementIds.Count}** element IDs from selection.");

// Check if any elements are selected
if (selectedElementIds.Count == 0)
{
    Logger.AppendLine("- **No elements are currently selected.**");
    return "No elements are currently selected.";
}

// Convert the selected IDs into Element objects and validate them
List<Element> validSelectedElements = new List<Element>();
foreach (ElementId elementId in selectedElementIds)
{
    CheckCancellationRequested();

    Element element = doc.GetElement(elementId);
    if (element != null)
    {
        validSelectedElements.Add(element);
    }
    else
    {
        Logger.AppendLine($"- **Warning:** Element with ID {elementId.Value} could not be found in the document.");
    }
}

// Check if any valid elements were found
if (validSelectedElements.Count == 0)
{
    Logger.AppendLine("- **No valid elements found in the current selection.**");
    return "No valid elements found in the current selection.";
}

// Count the number of valid selected elements
int selectedElementCount = validSelectedElements.Count;

// Return a message indicating the count of selected elements
Logger.AppendLine($"- **Total selected elements: {selectedElementCount}**");
return $"You have {selectedElementCount} element(s) selected."


String Input

Here are the details for defining string inputs.
String inputs allow the user to enter a text value, which can then be used in the code for different purposes.


Input

C# Type

UI Element

Editor

Typical use

String

string

-

Names, keys, parameters

Editor Config

-


Examples:

// @title String input
// @description Mandatory string input without default value.
string STRING;

// @title String input (optional)
// @description Optional string input; can be left empty.
string? STRING_OPTIONAL;

// @title String input (with default)
// @description Mandatory string input with a predefined default value.
string STRING_WITH_DEFAULT = "Mark"


String Dropdown Input

String dropdown inputs allow the user to choose one or more values from a predefined list of text options.
These inputs are useful when the valid values are limited, such as colors, modes, types, labels, or configuration presets.

You can define dropdowns in three forms:

  • Single-selection dropdown — the user must select exactly one option.

  • Multi-selection dropdown — the user can select multiple options.

  • Dropdown with default value — a predefined option is selected automatically.

The available options are defined inside the @editorConfig annotation using the options list.


Input

C# Type

UI Element

Editor

Typical use

String

string

-

Predefined Names

Editor Config

{ "options": [{ "title": "Red", "value": "Red" }, { "title": "Blue", "value": "Blue" }]}


Examples:

// @title String dropdown input 
// @description Mandatory dropdown selection from a predefined list.
// @editorConfig { "options": [{ "title": "Red", "value": "Red" }, { "title": "Blue", "value": "Blue" }]}
string STRING_DROPDOWN;

// @title String dropdown input (optional)
// @description Optional dropdown selection from a predefined list.
// @editorConfig { "options": [{ "title": "Red", "value": "Red" }, { "title": "Blue", "value": "Blue" }]}
string? STRING_DROPDOWN_OPTIONAL;

// @title String dropdown input (multi-select)
// @description Mandatory dropdown selection from a predefined list. multi-selection.
// @editorConfig { "options": [{ "title": "Red", "value": "Red" }, { "title": "Blue", "value": "Blue" }]}
string[] STRING_DROPDOWN_MULTI;

// @title String dropdown input (multi-select) (optional)
// @description Optional Mandatory dropdown selection from a predefined list. multi-selection.
// @editorConfig { "options": [{ "title": "Red", "value": "Red" }, { "title": "Blue", "value": "Blue" }]}
string[]? STRING_DROPDOWN_MULTI_OPTIONAL;

// @title String dropdown input (with default)
// @description Mandatory dropdown selection; default value is set in editorConfig.
// @editorConfig { "options": [{ "title": "Red", "value": "Red" }, { "title": "Blue", "value": "Blue" }] , optionDefaultValue: "Blue" }
string[] STRING_DROPDOWN_WITH_DEFAULT


Integer Inputs

Integer inputs allow the user to provide whole-number values that your command can use for calculations, indexing, counts, and many other numeric operations.
They are one of the simplest and most common input types.

You can define integer inputs in several forms depending on whether the value is required, optional, or part of a list.


Input

C# Type

UI Element

Editor

Typical use

Integer Number

int

-

Counts, sizes, indices

Editor Config

-


Examples:

// @title Integer input
// @description Mandatory integer input.
int INT;

// @title Integer input (optional)
// @description Optional integer input; can be left empty.
int? INT_OPTIONAL;

// @title Integer input (multi-select)
// @description Mandatory integer multi-selection.
int[] INT_MULTI;

// @title Integer input (multi-select optional)
// @description Optional integer multi-selection; can be left empty.
int[]? INT_MULTI_OPTIONAL;

// @title Integer input (with default)
// @description Mandatory integer input with a predefined default value.
int INT_WITH_DEFAULT = 1


Double Inputs

Double inputs allow the user to provide floating-point numbers (values that may contain decimals).
They are typically used for measurements, ratios, offsets, scales, tolerances, and any operation that requires numeric precision.


Input

C# Type

UI Element

Editor

Typical use

Double Number

double

-

Dimensions, scale values

Editor Config

-


Examples:

// @title Double input
// @description Mandatory double input.
double DOUBLE;

// @title Double input (optional)
// @description Optional double input; can be left empty.
double? DOUBLE_OPTIONAL;

// @title Double input (multi-select)
// @description Mandatory double multi-selection.
double[] DOUBLE_MULTI;

// @title Double input (multi-select optional)
// @description Optional double multi-selection; can be left empty.
double[]? DOUBLE_MULTI_OPTIONAL;

// @title Double input (with default)
// @description Mandatory double input with a default value.
double DOUBLE_WITH_DEFAULT = 3.0


Boolean Inputs

Boolean inputs allow the user to enable or disable a feature through a simple checkbox.
These inputs are used when a command needs a true/false decision — such as toggles, switches, options, or conditional behaviors.

You can define boolean inputs in several forms: mandatory, optional, or with a default value.


Input

C# Type

UI Element

Editor

Typical use

Checkbox

bool

-

Dimensions, scale values

Editor Config

-


Examples:

// @title Boolean input
// @description Check box.
bool BOOL;

// @title Boolean input (optional)
// @description Optional Check box.
bool? BOOL_OPTIONAL;

// @title Boolean input (with default)
// @description Check box.
bool BOOL_DEFAULT = true


Category Selector Inputs

Category selector inputs allow the user to choose one or more Revit categories directly from the UI.
These inputs are useful when your command requires the user to specify which types of elements it should work with — for example, walls, doors, sheets, title blocks, ducts, or any other BuiltInCategory.

All category selections use the categorySelector editor, which displays a list of available categories inside Revit.

Category selectors come in four forms: single selection, optional single selection, multi-selection, and optional multi-selection.


Input

C# Type

UI Element

Editor

Typical use

Category

long

categorySelector

Revit categories

Editor Config

-


Examples:

// @title Category selector input (single)
// @description Mandatory single category selection.
// @editor categorySelector
long CATEGORY_SELECTOR;

// @title Category selector input (single optional)
// @description Optional single category selection.
// @editor categorySelector
long? CATEGORY_SELECTOR_OPTIONAL;

// @title Category selector input (multi-select)
// @description Mandatory category multi-selection.
// @editor categorySelector
long[] CATEGORY_SELECTOR_MULTI;

// @title Category selector input (multi-select optional)
// @description Optional category multi-selection.
// @editor categorySelector
long[]? CATEGORY_SELECTOR_MULTI_OPTIONAL


Type Selector Inputs (By Category)

Element Type of Category selectors allow the user to choose one or more Revit element types filtered by a specific BuiltInCategory. These inputs are designed for situations where your command must work with types rather than instances, such as selecting Title Block Types, Wall Types, Door Types, or any other element type defined under a category.

Behind the scenes, this selector works the same way as using a FilteredElementCollector with two filters:

  1. Filter by Category – Only elements from the specified BuiltInCategory are included.

  2. Filter by Element Type – Only types (not instances) are shown in the selection UI.

In Revit API terms, this is equivalent to:

new FilteredElementCollector(doc)
    .OfCategory(BuiltInCategory.OST_TitleBlocks)
    .WhereElementIsElementType

The selector UI performs these filters internally and displays the resulting element types for the user to choose from. You can define this input as single-selection, optional, multi-selection, or optional multi-selection depending on your command’s needs.


Input

C# Type

UI Element

Editor

Typical use

Element Types in document

long

categorySelector

Choose Revit Types from a Category

Editor Config

{"providerName": "Element", "filterByBuiltInCategory": ["OST_TitleBlocks"], "filterByIsType": true}


Examples:

// @title Element Type of Category selector input
// @description Mandatory selection using the provided category filters.
// @editor categorySelector
// @editorConfig {"providerName": "Element", "filterByBuiltInCategory": ["OST_TitleBlocks"], "filterByIsType": true}
long ELEMENT_TYPE_OF_CATEGORY_SELECTOR;

// @title Element Type of Category selector input (optional)
// @description Optional selection using the provided category filters.
// @editor categorySelector
// @editorConfig {"providerName": "Element", "filterByBuiltInCategory": ["OST_TitleBlocks"], "filterByIsType": true}
long? ELEMENT_TYPE_OF_CATEGORY_OPTIONAL;

// @title Element Type of Category selector input (multi-select)
// @description Multiple selection using the provided category filters.
// @editor categorySelector
// @editorConfig {"providerName": "Element", "filterByBuiltInCategory": ["OST_TitleBlocks"], "filterByIsType": true}
long[] ELEMENT_TYPE_OF_CATEGORY_MULTI;

// @title Element Type of Category selector input (multi-select) (optional)
// @description Multiple selection using the provided category filters.
// @editor categorySelector
// @editorConfig {"providerName": "Element", "filterByBuiltInCategory": ["OST_TitleBlocks"], "filterByIsType": true}
long[]? ELEMENT_TYPE_OF_CATEGORY_MULTI_OPTIONAL


Element Selector Inputs (By Category)

Element of Category selectors allow the user to choose one or more Revit element instances filtered by a specific BuiltInCategory.
These inputs are used when your command needs to work directly with placed elements in the model, such as Sheets, Views, Rooms, Grids, Title Blocks on sheets, or any other instance-type elements inside a category.

This selector behaves the same way as a FilteredElementCollector in Revit with two filters applied:

  1. Filter by Category – Only elements that belong to the specified BuiltInCategory are considered.

  2. Filter by Element Instance – Only instances (not types) are included in the results.

In terms of Revit API logic, this is equivalent to:

new FilteredElementCollector(doc)
    .OfCategory(BuiltInCategory.OST_Views)
    .WhereElementIsNotElementType

The selector UI applies these filters behind the scenes and displays the resulting list of elements for the user to choose from.
You can define this input as single-selection, optional, multi-selection, or optional multi-selection depending on the requirements of your command.


Input

C# Type

UI Element

Editor

Typical use

Elements in document

long

categorySelector

Choose Revit Elements from a Category

Editor Config

{ providerName: "Element" , filterByBuiltInCategory: ["OST_Views"], filterByIsType: false}


Examples:

// @title Element of Category selector input
// @description Mandatory selection using the provided category filters.
// @editor categorySelector
// @editorConfig { providerName: "Element" , filterByBuiltInCategory: ["OST_Sheets"], filterByIsType: false}
long ELEMENT_OF_CATEGORY_SELECTOR;

// @title Element of Category selector input (optional)
// @description Optional selection using the provided category filters.
// @editor categorySelector
// @editorConfig { providerName: "Element" , filterByBuiltInCategory: ["OST_Sheets"], filterByIsType: false}
long? ELEMENT_OF_CATEGORY_SELECTOR_OPTIONAL;

// @title Element of Category selector input (multi-select)
// @description Multiple selection using the provided category filters.
// @editor categorySelector
// @editorConfig { providerName: "Element" , filterByBuiltInCategory: ["OST_Sheets"], filterByIsType: false}
long[] ELEMENT_OF_CATEGORY_SELECTOR_MULTI;

// @title Element of Category selector input (multi-select) (optional)
// @description Multiple selection using the provided category filters.
// @editor categorySelector
// @editorConfig { providerName: "Element" , filterByBuiltInCategory: ["OST_Sheets"], filterByIsType: false}
long[]? ELEMENT_OF_CATEGORY_SELECTOR_MULTI_OPTIONAL;


Type Selector Inputs (By Class)

Element Type of Class selectors allow the user to choose one or more Revit element types filtered by a specific .NET class.
This input is used when your command must work with types that belong to a particular Revit API class, such as ViewType, FamilySymbol, PlanView, RebarBarType, etc.

These selectors do not rely on categories—they filter based on the .NET type of the Revit element.
This gives you more control when you want only the element types that derive from or match a specific API class.

Internally, the selector works the same way as using a FilteredElementCollector with:

  1. Filter by .NET Class – Only elements whose .NET type matches the desired Revit class are included.

  2. Filter by Element Type – Only types (not instances) are allowed.

In Revit API terms, this is equivalent to:

new FilteredElementCollector(doc)
    .OfClass(typeof(Autodesk.Revit.DB.PlanView))
    .WhereElementIsElementType();

The selector UI performs these filters behind the scenes and displays a list of element types that match the specified class.
You may define this input as single-selection, optional, multi-selection, or optional multi-selection based on your command’s requirements.


Input

C# Type

UI Element

Editor

Typical use

Element types in document

long

categorySelector

Choose Revit Types from a Class

Editor Config

{"providerName": "Element", "filterByNetType": ["Autodesk.Revit.DB.ViewFamilyType"], "filterByIsType": true}


Examples:

// @title Element Type of Class selector input
// @description Mandatory Element Type selector filtered by Class.
// @editor categorySelector
// @editorConfig {"providerName": "Element", "filterByNetType": ["Autodesk.Revit.DB.ViewFamilyType"], "filterByIsType": true}
long ELEMENT_TYPE_OF_CLASS_SELECTOR;

// @title Element Type of Class selector input (optional)
// @description Optional Element Type selector filtered by Class.
// @editor categorySelector
// @editorConfig {"providerName": "Element", "filterByNetType": ["Autodesk.Revit.DB.ViewFamilyType"], "filterByIsType": true}
long? ELEMENT_TYPE_OF_CLASS_SELECTOR_OPTIONAL;

// @title Element Type of Class selector input (multi-select)
// @description Multiple Element Type selection filtered by Class.
// @editor categorySelector
// @editorConfig {"providerName": "Element", "filterByNetType": ["Autodesk.Revit.DB.ViewFamilyType"], "filterByIsType": true}
long[] ELEMENT_TYPE_OF_CLASS_SELECTOR_MULTI;

// @title Element Type of Class selector input (multi-select) (optional)
// @description Optional multiple Element Type selection filtered by Class.
// @editor categorySelector
// @editorConfig {"providerName": "Element", "filterByNetType": ["Autodesk.Revit.DB.ViewFamilyType"], "filterByIsType": true}
long[]? ELEMENT_TYPE_OF_CLASS_SELECTOR_MULTI_OPTIONAL;


Element Selector Inputs (By Class)

Element of Class selectors allow the user to choose one or more Revit element instances filtered by a specific .NET class.
These inputs are ideal when your command needs to work with actual placed elements—such as Plan Views, 3D Views, Family Instances, Schedules, or any other instance that belongs to a particular API class.

Unlike category-based selectors, this filter works on the element’s .NET type, meaning you can precisely target elements that belong to a class like PlanView, View, FamilyInstance, or any custom or specific Revit API element class.

This selector behaves similarly to a FilteredElementCollector using:

  1. .NET Class Filter – Only elements whose .NET type matches the specified class are included.

  2. Instance Filter – Only element instances are shown (not element types).

In Revit API terms, this corresponds to:

new FilteredElementCollector(doc)
    .OfClass(typeof(Autodesk.Revit.DB.ViewPlan))
    .WhereElementIsNotElementType

The selector UI applies these filters automatically and presents the user with a list of matching instance elements.
You can define this input as single-selection, optional, multi-selection, or optional multi-selection depending on your command’s requirements.


Input

C# Type

UI Element

Editor

Typical use

Elements in document

long

categorySelector

Choose Revit Elements from a Class

Editor Config

{"providerName": "Element", "filterByNetType": ["Autodesk.Revit.DB.ViewPlan"], "filterByIsType": false}


Examples:

// @title Element of Class selector input
// @description Mandatory Element selector filtered by Class.
// @editor categorySelector
// @editorConfig {"providerName": "Element", "filterByNetType": ["Autodesk.Revit.DB.ViewPlan"], "filterByIsType": false}
long ELEMENT_OF_CLASS_SELECTOR;

// @title Element of Class selector input (optional)
// @description Optional Element selector filtered by Class.
// @editor categorySelector
// @editorConfig {"providerName": "Element", "filterByNetType": ["Autodesk.Revit.DB.ViewPlan"], "filterByIsType": false}
long? ELEMENT_OF_CLASS_SELECTOR_OPTIONAL;

// @title Element of Class selector input (multi-select)
// @description Multiple Element selections filtered by Class.
// @editor categorySelector
// @editorConfig {"providerName": "Element", "filterByNetType": ["Autodesk.Revit.DB.ViewPlan"], "filterByIsType": false}
long[] ELEMENT_OF_CLASS_SELECTOR_MULTI;

// @title Element of Class selector input (multi-select) (optional)
// @description Optional multiple Element selections filtered by Class.
// @editor categorySelector
// @editorConfig {"providerName": "Element", "filterByNetType": ["Autodesk.Revit.DB.ViewPlan"], "filterByIsType": false}
long[]? ELEMENT_OF_CLASS_SELECTOR_MULTI_OPTIONAL


Element of Class Selector (Including Derived Classes)

In some scenarios, you may want the selector to include not only elements of a specific class but also all elements derived from that class.
For example, when filtering by Autodesk.Revit.DB.View, you may want to include Plan Views, 3D Views, Section Views, Elevation Views, Drafting Views, and other subclasses.

This behavior can be enabled by setting:

"filterNetTypeMatchMode": "InheritorTypes"

This mode extends the class matching logic so it works the same as checking:

element.GetType().IsSubclassOf(typeof(View))

And in API terms, the equivalent FilteredElementCollector logic is:

new FilteredElementCollector(doc)
    .OfClass(typeof(Autodesk.Revit.DB.View))
    .WhereElementIsNotElementType();

This selector gathers all element instances that belong to the chosen class or any subclass, making it extremely flexible when the command targets a broad group of related element types.


Input

C# Type

UI Element

Editor

Typical use

Elements in document

long

categorySelector

Choose Revit Elements from a Class

Editor Config

{"providerName": "Element", "filterByNetType": ["Autodesk.Revit.DB.View, RevitAPI"], "filterNetTypeMatchMode": "InheritorTypes", "filterByIsType": false}


Examples:

// @title Element of Class selector input (Include all Derived Classes)
// @description Mandatory Element selector filtered by this class and all derived classes.
// @editor categorySelector
// @editorConfig {"providerName": "Element", "filterByNetType": ["Autodesk.Revit.DB.View, RevitAPI"], "filterNetTypeMatchMode": "InheritorTypes", "filterByIsType": false}
long ELEMENT_OF_CLASS_SELECTOR_INHERIT;


Element Picker Inputs (Interactive Selection in View)

Element picker inputs allow the user to select elements directly in the Revit view, instead of choosing from a list. When a command uses an element picker, CoPilot activates Revit’s selection mode, shows a status prompt (for example: “Select a duct in the chosen view”), and waits for the user to click one or more elements.

These inputs behave very similarly to calling UIDocument.Selection.PickObject or PickObjects in the Revit API, combined with an element selection filter:

  • When filtered by category (builtInCategories), only elements whose category matches one of the specified BuiltInCategories can be picked. This is like using PickObject(s) with an ISelectionFilter that checks element.Category.Id.

  • When filtered by class (netTypes), only elements whose .NET type matches the given Revit API class (for example Autodesk.Revit.DB.FamilyInstance) can be picked. This is like using PickObject(s) with an ISelectionFilter that checks element is FamilyInstance.

Conceptually, the behavior is equivalent to something like:

// By category
uidoc.Selection.PickObjects(
    ObjectType.Element,
    new CategorySelectionFilter(BuiltInCategory.OST_DuctCurves),
    "Select ducts in the chosen view");

// By class
uidoc.Selection.PickObjects(
    ObjectType.Element,
    new ClassSelectionFilter(typeof(FamilyInstance)),
    "Select your family instances."

The selected elements are stored as element IDs in your inputs:

  • Single element → long or long?

  • Multiple elements → long[] or long[]?

You can define element picker inputs as:

  • Single vs multi-select

  • Mandatory vs optional

  • Filtered by category (builtInCategories) or by class (netTypes)

All of this is controlled via the elementSelector editor and its @editorConfig settings.


Input

C# Type

UI Element

Editor

Typical use

Elements in UI

long

elementSelector

Pick Revit Elements from Revit View

Editor Config

{"statusPrompt": "Select a duct in the chosen view", "builtInCategories": ["OST_DuctCurves"]}


{"statusPrompt": "Select your family instance.", "netTypes": ["Autodesk.Revit.DB.FamilyInstance, RevitAPI"]}


Examples:

// @title Element picker input (single by category)
// @description Mandatory single element selection filtered by category.
// @editor elementSelector
// @editorConfig {"statusPrompt": "Select a duct in the chosen view", "builtInCategories": ["OST_DuctCurves"]}
// Mandatory
long ELEMENT_PICKER_BYCATEGORY;

// @title Element picker input (single by category, optional)
// @description Optional single element selection filtered by category.
// @editor elementSelector
// @editorConfig {"statusPrompt": "Select a duct in the chosen view", "builtInCategories": ["OST_DuctCurves"]}
// Optional
long? ELEMENT_PICKER_BYCATEGORY_OPTIONAL;

// @title Element picker input (multi-select by category)
// @description Mandatory multi-selection of elements filtered by category.
// @editor elementSelector
// @editorConfig {"statusPrompt": "Select ducts in the chosen view", "builtInCategories": ["OST_DuctCurves"]}
// Mandatory
long[] ELEMENT_PICKER_MULTI_BYCATEGORY;

// @title Element picker input (multi-select by category, optional)
// @description Optional multi-selection of elements filtered by category.
// @editor elementSelector
// @editorConfig {"statusPrompt": "Select ducts in the chosen view", "builtInCategories": ["OST_DuctCurves"]}
// Optional
long[]? ELEMENT_PICKER_MULTI_BYCATEGORY_OPTIONAL;


// @title Element picker input (single by class)
// @description Mandatory single element selection filtered by class type.
// @editor elementSelector
// @editorConfig {"statusPrompt": "Select your family instance.", "netTypes": ["Autodesk.Revit.DB.FamilyInstance, RevitAPI"]}
// Mandatory
long ELEMENT_PICKER_BYCLASS;

// @title Element picker input (single by class, optional)
// @description Optional single element selection filtered by class type.
// @editor elementSelector
// @editorConfig {"statusPrompt": "Select your family instance.", "netTypes": ["Autodesk.Revit.DB.FamilyInstance, RevitAPI"]}
// Optional
long? ELEMENT_PICKER_BYCLASS_OPTIONAL;


// @title Element picker input (multi-select by class)
// @description Mandatory multi-selection of elements filtered by class type.
// @editor elementSelector
// @editorConfig {"statusPrompt": "Select your family instances.", "netTypes": ["Autodesk.Revit.DB.FamilyInstance, RevitAPI"]}
// Mandatory
long[] ELEMENT_PICKER_MULTI_BYCLASS;

// @title Element picker input (multi-select by class, optional)
// @description Optional multi-selection of elements filtered by class type.
// @editor elementSelector
// @editorConfig {"statusPrompt": "Select your family instances.", "netTypes": ["Autodesk.Revit.DB.FamilyInstance, RevitAPI"]}
// Optional
long[]? ELEMENT_PICKER_MULTI_BYCLASS_OPTIONAL


File Picker Input

A File Picker input allows the user to select a file from their computer.
This input is typically used when your command requires external data—such as Excel spreadsheets, configuration files, text files, or other supported formats.

When the command runs, the File Picker opens a dialog window and lets the user browse to a file that matches the filter rules defined in the @editorConfig.
The selected file path is then stored as a string and can be used within your code to read or process the file.

The file picker can be configured to accept specific file types using the filters option, where you can define one or more extension groups (for example: Excel files, CSV files, images, etc.).


Input

C# Type

UI Element

Editor

Typical use

File picker

long

filePicker

Choose a file from drive

Editor Config

{"filters": [{"name": "Excel Files", "extensions": ["xlsx", "xls"]}]}


Examples:

// @title File picker input
// @description Mandatory file selection; choose an Excel file.
// @editor filePicker
// @editorConfig {"filters": [{"name": "Excel Files", "extensions": ["xlsx", "xls"]}]}
string FILE_PICKER


Global Context Variables

When you write or edit a CoPilot command, certain objects and helper utilities are automatically provided for you.
You do not need to define or initialize these.
They are already available anywhere in your command code after the // vars end block.

These global variables give you access to the Revit API, the active document, logging utilities, and progress updates.

Below is a list of all provided global context objects:


Revit API Context

UIApp

public static UIApplication UIApp { get; set


The global UIApplication instance.
Use it to access application-level features such as:

  • Application settings

  • Active add-ins

  • UI-level information

UIDoc

public static UIDocument UIDoc { get; set


The active UIDocument for the current project.
You’ll use this constantly to:

  • Access the active document

  • Pick elements

  • Retrieve selections

  • Modify the model (inside a transaction)

For convenience, many examples use:

Document doc = UIDoc.Document


Logging Utility

Logger

public static StringBuilder Logger { get; set


Use this to record messages during execution In Markdown format.
Everything you append here will appear in the CoPilot output panel.

Example:

Logger.AppendLine(" - Starting **furniture** count..."


Progress and Cancellation Helpers

These methods help you report progress or handle cancellation in long operations.


Check Cancellation

public static void CheckCancellationRequested


Call this inside loops to allow CoPilot to cancel gracefully.


Progress Updates

public static void ProgressUpdateWithState(string state)
public static void ProgressUpdateWithSteps(double steps, double total)
public static void ProgressUpdate(string state, double steps, double total


Examples:

ProgressUpdateWithState("Collecting elements...");
ProgressUpdate("Processing rooms", 3, 10


Important Note:

These variables are automatically injected by CoPilot:

  • You do not define them

  • You do not initialize them

  • You do not need any using statements beyond the standard Revit namespaces

  • You can use them immediately after the // vars end block

This ensures a consistent environment for every CoPilot command and allows you to focus entirely on your command logic.


Copyright © 2024 BIMLOGIQ

Contact Us: support@bimlogiq.com

Level 4/1 Castlereagh St, Sydney, NSW 2000
ACN 639 389 727
ABN 33 639 389 727

Copyright © 2024 BIMLOGIQ

Contact Us: support@bimlogiq.com

Level 4/1 Castlereagh St, Sydney, NSW 2000
ACN 639 389 727
ABN 33 639 389 727