Install
$ agentstack add skill-nice3point-revit-skills-revit-element-collector ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Revit Element Collector
Query the model through the fluent FilteredElementCollector wrappers in Nice3point.Revit.Extensions. They wrap the raw Revit collector API into a single readable chain, and keep filtering inside Revit's native database engine — which evaluates filters before elements are expanded into memory — instead of materializing every element and filtering with LINQ.
When to use
- Retrieving elements, types, or instances by class, category, or parameter value.
- Reviewing code that writes
new FilteredElementCollector(document)by hand or filters collector output with.Where(...). - Fetching just the first match or a count without loading the whole result set.
When not to use
- You already hold the element and only need to read or set its parameters — use
revit-element-and-parameter-access. - You need a specialized
ElementFilterthe extensions do not expose — fall back to a rawFilteredElementCollectorwith that filter.
Workflow
Step 1: Open a collector from the document
var collector = document.CollectElements(); // whole document
var viewScoped = document.CollectElements(view); // elements visible in a view
var restricted = document.CollectElements(elementIds); // a known id set
Step 2: Apply quick filters as generic, typed calls
Prefer the generic and multi-argument overloads over raw typeof filters.
var walls = document.CollectElements()
.OfClass()
.ToElements();
var openings = document.CollectElements()
.OfCategories(BuiltInCategory.OST_Walls, BuiltInCategory.OST_Floors)
.Instances() // only instances; use .Types() for element types
.ToElements();
Step 3: Filter by parameter with native rules, not LINQ
WhereParameter builds a native ElementParameterFilter — evaluated at the database level before element expansion — then continues the collector chain.
var tallWalls = document.CollectElements()
.OfClass()
.WhereParameter(BuiltInParameter.WALL_USER_HEIGHT_PARAM).IsGreaterThan(3.0, 1e-6)
.ToElements();
// BAD — loads every wall into memory, then filters
var tallWalls = new FilteredElementCollector(document)
.OfClass(typeof(Wall))
.Cast()
.Where(wall => wall.get_Parameter(BuiltInParameter.WALL_USER_HEIGHT_PARAM).AsDouble() > 3.0);
Comparisons include Equals, IsGreaterThan/IsGreaterThanOrEqualTo, IsLessThan/IsLessThanOrEqualTo (with an optional double epsilon), Contains/StartsWith (and their Not… inversions), and HasValue.
Step 4: Terminate with the fast native path
Use the extension terminators instead of LINQ — they call Revit's native fast implementations (Count uses GetElementCount()).
var firstRoom = document.CollectElements().OfClass().FirstOrDefault();
var wallCount = document.CollectElements().OfClass().Count();
var hasLevels = document.CollectElements().OfClass().Any();
Step 5: Verify
- The query builds the filter through collector methods, not
.Where(...)over materialized elements. - A parameter comparison uses
WhereParameter, not a post-collection predicate. - The terminator is a native call (
ToElements,First,FirstOrDefault,Count,Any).
Validation
- [ ] The collector comes from
document.CollectElements(...), not a hand-writtennew FilteredElementCollector(...). - [ ] Class and category filters use the generic/multi-argument extensions.
- [ ] Parameter conditions use
WhereParameter(...), keeping filtering at the database level. - [ ] Single-result and count queries use
First/FirstOrDefault/Count/Any, not LINQ. - [ ] A quick filter (class/category) precedes a slow filter (parameter) to shrink the candidate set.
Common Pitfalls
| Pitfall | Correct approach | |------------------------------------------------------------------------------|-----------------------------------------------------------------------------| | .Where(element => element.get_Parameter(...).AsDouble() > x) after the collector | WhereParameter(param).IsGreaterThan(x, epsilon) — a native rule. | | collector.ToElements().Count / .Any() (LINQ over the list) | collector.Count() / collector.Any() — native fast paths. | | Comparing double parameters without an epsilon | Use the IsGreaterThan(value, epsilon) overload. | | CollectElements or WhereParameter not found | The Nice3point.Revit.Extensions package is not referenced in the project. | | Reusing one collector after a terminator | Start a fresh CollectElements() per query; terminators stop the iterator. |
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: Nice3point
- Source: Nice3point/revit-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.