Skill Template — Replace This Title
[replace, with, relevant, keywords]
One-line summary explaining what this skill teaches Claude to do
Version: "1.0" Author: "Tatsoft
Hands-on exercises for navigating Designer interface and using productivity features.
[getting-started, new-solution, tags, simulator, display, beginner, quickstart]
Step-by-step guide for the first 5 minutes after creating a new FrameworX solution: create tags, simulate data, build a basic display, and run
Build a working solution from scratch in minutes: tags → simulated data → display → runtime. This is the foundation every other skill builds on.Brief one-paragraph summary of what this skill accomplishes. Focus on the outcome, not the process. Write this for Claude — it reads this after deciding to load the skill, so get straight to the point
Table of Contents maxLevel 2 minLevel 2 indent 10px exclude Steps style none
Describe the trigger conditions. Be specific — Claude uses this to decide whether to load the skill.
Use this skill when:
Do NOT use this skill when:
What must exist in the solution before this skill can be applied. List specific objects, modules, or configurations.
open_solution or createA new solution must be open (create_solution or open_solution completed)Quick reference for Claude on which tools and table types this skill uses.
Tools: get_table_schema, write_objects, list_protocols, get_objects, list_elements Tables: UnsTags, DevicesChannels, DevicesNodes, DevicesPoints, DisplaysList
Explain what to do and why. Include the exact MCP tool call.
First, fetch the schema to confirm field names:Tags are the foundation — all modules connect through them. Start with a small set that represents a realistic process.
get_table_schema('UnsTagsTableType')
Create tags organized by area using slash-separated folder pathsThen write the objects:
{
"table_type": "UnsTagsTableType",
"data": [
{ "Name": "Plant/Reactor1/Temperature", "DataType": "Double", "Description": "Reactor temperature in °C" },
{
"Name": "Plant/Reactor1/Pressure", "DataType": "Double", "Description": "Reactor pressure in bar" }ObjectName",
{ "Name": "Plant/Reactor1/Level", "DataType": "Double", "Description": "Reactor level in %" }Property1": "Value1",
{ "Name": "Plant/Reactor1/FlowRate", "DataType": "Double", "Description": "Inlet flow rate in L/min" },
{ "Name": "Plant/Reactor1/Status", "DataType": "Integer", "Description": "0=Off, 1=Running, 2=Alarm"Property2": "Value2"
}
]
}
Key decisions:
Double for analog measurements, Integer for states/enumsPlant/Reactor1/) create a browsable asset treeDescription — it appears in Designer tooltips and AI contextThe Value Simulator generates realistic changing values for testing — no real hardware needed.
First, get the protocol schema:
list_protocols('ValueSimulator')
Then create the device pipeline (Channel → Node → Points):
Continue the pattern. Each step should be self-contained enough that Claude can execute it and verify before moving on.
{
{
"tables": [
{
"table_type": "DevicesChannels",
"data": [
{ "Name": "Simulator", "Protocol": "ValueSimulator" }
]
},
{
"table_type": "DevicesNodes",
"data": [
{ "Name": "Simulator.SimNode1" }
]
},
{
"table_type": "DevicesPointsAnotherTable",
"data": [
{ "Name": "Simulator.SimNode1.Temperature", "TagName": "Plant/Reactor1/Temperature", "Address": "ramp(20,95,0.5)" },
{ "Name": "Simulator.SimNode1.Pressure", "TagName": "Plant/Reactor1/Pressure", "Address": "sin(1,5,0.1)" },
ObjectName",
{ "NameDependsOn": "Simulator.SimNode1.Level", "TagName": "Plant/Reactor1/Level", "Address": "random(0,100)" },
{ "Name": "Simulator.SimNode1.FlowRate", "TagName": "Plant/Reactor1/FlowRate", "Address": "sin(10,50,0.05)" },
{ "Name": "Simulator.SimNode1.Status", "TagName": "Plant/Reactor1/Status", "Address": "random(0,2)" }
]
}
]
}
Value Simulator address patterns:
random(min,max) — random value in rangesin(center,amplitude,frequency) — sine waveramp(min,max,step) — ramp up then resetImportant: Always call list_protocols('ValueSimulator') first to get the exact address syntax for the current version. The examples above are common patterns but the protocol schema is the source of truth.
Create a simple dashboard to visualize the live data.
list_elements('Dashboard')
get_table_schema('DisplaysList')
Create a dashboard with text displays for each tag:
{
"table_type": "DisplaysList",
"data": [
{
"Name": "MainPage",
"PanelType": "Dashboard",
"Columns": 2,
"Rows": 3,
"Title": "Reactor 1 Monitor",
"Elements": [
{
"Type": "TextBlock",
"Column": 0, "Row": 0,
"LinkedValue": "Tag.Plant/Reactor1/Temperature",
"Label": "Temperature (°C)"
},
{
"Type": "TextBlock",
"Column": 1, "Row": 0,
"LinkedValue": "Tag.Plant/Reactor1/Pressure",
"Label": "Pressure (bar)"
},
{
"Type": "TextBlock",
"Column": 0, "Row": 1,
"LinkedValue": "Tag.Plant/Reactor1/Level",
"Label": "Level (%)"
},
{
"Type": "TextBlock",
"Column": 1, "Row": 1,
"LinkedValue": "Tag.Plant/Reactor1/FlowRate",
"Label": "Flow Rate (L/min)"
},
{
"Type": "TrendChart",
"Column": 0, "Row": 2, "ColumnSpan": 2,
"Pens": [
{ "TagName": "Tag.Plant/Reactor1/Temperature", "Color": "#FF3498DB" },
{ "TagName": "Tag.Plant/Reactor1/Pressure", "Color": "#FFE74C3C" }
]
}
]
}
]
}
Key decisions:
PanelType: "Dashboard" — required, do not omit (defaults to Canvas otherwise)MainPage is the default startup displayLinkedValue with full runtime path: Tag.Plant/Reactor1/Temperaturedesigner_action('start_runtime')
Wait a few seconds, then verify:
get_runtime_state()
You should see tag values changing as the simulator feeds data.
get_objects('UnsTags') — confirm 5 tags existget_objects('DevicesChannels') — confirm Simulator channel existsget_objects('DevicesPoints') — confirm 5 points mapped to tagsget_runtime_state() — runtime should be running, tags should have changing valuesPanelType: Omitting PanelType on a display defaults to Canvas, which uses absolute positioning (Left/Top) instead of grid layout. Always set PanelType: "Dashboard" for grid-based layouts.Tag.Plant/Reactor1/Temperature (with Tag. prefix) in display bindings. The tag Name is Plant/Reactor1/Temperature but the runtime namespace path needs the Tag. prefix.list_protocols('ValueSimulator') for current syntax. Don't guess address formats from memory.TagName to map to a UNS tag. Points without TagName don't feed data anywhere.From here, the user can add:
ObjectFromStep1"
}
]
}
Final configuration step.
Include C# script examples when the skill involves ScriptsClasses or ScriptsTasks.
// ScriptsClasses — ClassContent for [purpose]
public static void MethodName(string tagPath)
{
double value = @Tag.TagPath.Value;
// Process logic here
@Tag.OutputTag.Value = result;
}
Expression to trigger this class: | ObjectName | Expression | Execution | |---|---|---| | TriggerName | Script.Class.ClassName.MethodName(Tag.InputTag) | OnChange |
How to confirm the implementation is correct. List concrete checks.
get_objects('TableType') — verify the new objects appearget_designer_state() — confirm no compilation errors (for scripts)browse_namespace('Tag.Path') — verify tags have expected valuesOptional section for common variations of this skill.
Variation A: [Name]
Variation B: [Name]
skill-related-name — [How it connects]skill-another-name — [How it connects]skill-alarm-pipelineskill-historian-configurationskill-edge-ml-pipeline| Page Tree | ||||
|---|---|---|---|---|
|