Welcome to FeatureScript
FeatureScript guide
Language reference


In a Feature Studio, you can import another Onshape tab with the import dialog, found by pressing the import button:

Import button

This will insert import text into your Feature Studio with a unique id that points to the selected Onshape tab:

// Internal import
import(path : "9d3b53629e57cc424f4037fc", version : "e8931278b1daf37bfa3838c3");

// Linked document import
import(path : "c4220a7b1e28da28a09cebec/4d848d5d64fa938c3843ddac/9d3b53629e57cc424f4037fc", version : "e8931278b1daf37bfa3838c3");

Like elsewhere in Onshape, imports within the same document automatically update their import versions when the imported tab is changed, while imports from external documents are fixed at a specific version.

Importing a module will make a number of symbols visible, which may be used directly in the feature studio:

x = importedFunction();

Any import may be prefixed by a namespace, and its symbols may be accessed through the same namespace:

x = MyFunctions::importedFunction();

Importing another Feature Studio

When importing another Feature Studio, all the symbols which have been exported become available to the importing Feature Studio. An exported symbol is any top level node which has been declared with the export prefix:

export function myFunction(x) {...}
export enum myEnum {...}
export type myType typecheck p;
export predicate myPredicate(value) {...}

By default, symbols imported by the current module are not exported by it. However, you can also export an import like any other top level node. This makes sense if, for instance, a module also exports functions that use an imported type or a feature that uses imported enums.

export import(path : "onshape/std/tool.fs", version : "");

Importing external data

To guarantee that Part Studios always regenerate the same way, external data must be uploaded into an Onshape tab before FeatureScript can reference it.

Importing an uploaded tab imports the constant BLOB_DATA, which is a map with at least the following keys:

Onshape currently understands uploaded CSV files (parsed using Apache Commons CSV Excel format) and allows you to reference the data in them via the csvData key: the corresponding value is an array. If the CSV file consists of one record (one line), each entry in the array is a field, represented either as a number of a string (if the field could not be parsed as a number). If the CSV file consists of multiple records, each entry in the csvData array is an array corresponding to one record.

An image will have the keys imageWidth and imageHeight mapped to numbers of pixels. Image data is not currently available to FeatureScript.

For example, to access the first element in an uploaded CSV file with multiple records:

MyData::import(path : "...", version : "...");
const firstEntry = MyData::BLOB_DATA.csvData[0][0];

Importing a Part Studio

A Part Studio exports a function named build, which returns a context containing everything created in that Part Studio. It is often useful to utilize a Part Studio to create the static pieces of your feature (which may be transformed or booleaned in FeatureScript), Rather than manually writing the code to build complex geometry in FeatureScript.

A simple feature which builds a Part Studio, merges in its context, and transforms its bodies to a mate connector is below. Naturally, the import should be changed to an import of a Part Studio.

MyThing::import(path : "", version : "");

annotation { "Feature Type Name" : "Add thing" }
export const addThing = defineFeature(function(context is Context, id is Id, definition is map)
        annotation { "Name" : "Mounting mate connector", "Filter" : BodyType.MATE_CONNECTOR, "MaxNumberOfPicks" : 1 }
        definition.mountingConnector is Query;
        // Build a thing in a separate context
        var contextWithThing is Context = MyThing::build();

        // Delete its construction planes and origin
        opDeleteBodies(contextWithThing, id + "deleteDefaultGeometry", {
            "entities" : qUnion([
                qConstructionFilter(qBodyType(qEverything(EntityType.BODY), BodyType.SHEET), ConstructionObject.YES),

        // Add thing's context to the current Part Studio
        opMergeContexts(context, id + "addThing", {
            "contextFrom" : contextWithThing

        // Move the thing to the mate connector
        var transform is Transform = toWorld(evMateConnector(context, {
               "mateConnector" : definition.mountingConnector
        opTransform(context, id + "transformThing", {
               "bodies" : qCreatedBy(id + "addThing", EntityType.BODY),
               "transform" : transform

This feature can be used to add bodies from the imported part studio and place them correctly all in one feature. Just like with other tab imports, changing the Part Studio will instantly update the feature and any Part Studios referencing the feature, so long as all are in the same workspace.

Using the Add Thing feature