ato
ato is a declarative DSL to design electronics (PCBs) with.
Install / Use
npx skills add atopile/packagesInstalls into whichever agent you are using.
Cursor Rules
Cursor IDE rules (v2)
Quality Score
Category
Development & EngineeringSupported Platforms
Our assessment of ato
ato scores 69/100 on our quality scale, 2321st of 3,167 Development & Engineering skills we index.
Its Cursor Rules is 20 KB long, well organised into 38 sections with 6 code examples: a thorough specification that gives an agent plenty to work with.
It has no GitHub stars yet, so there is no community track record; judge it on its content.
Maintenance, license and trust
- The repository was last updated about 5 months ago. That is recent enough to be usable, but agent tooling moves fast, so check the instructions against your agent's current version.
- Our last check on 2026-09-26 found the source still online.
- No license is declared. By default that means all rights are reserved: you can read it, but reusing or redistributing it is not clearly permitted. Ask the author before building on it commercially.
- Its trust signals score 78/100, with 2 cautions from licensing, adoption, age or documentation. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.
Safety scan
No issues foundOur scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands. An AI review of the same text found nothing harmful.
AI review by kimi-k2.7-code on 2026-09-24. Automated pattern scan on 2026-09-24. It catches known dangerous patterns, not every risk — read a skill before letting an agent act on it.
ato compared with similar skills
All 4 of these similar skills score higher than ato; compare them before choosing.
| Skill | Score | Stars | Updated | Format |
|---|---|---|---|---|
| ato (this skill)by atopile | 69 | 0 | 5mo ago | Cursor Rules |
| ai-job-searchby MadsLorentzen | 100 | 44.3k | today | CLAUDE.md |
| claude-howtoby luongnv89 | 100 | 41.7k | 2d ago | CLAUDE.md |
| algorithmic-artby anthropics | 100 | 177.9k | 5d ago | SKILL.md |
| designby nextlevelbuilder | 100 | 130.2k | 7d ago | SKILL.md |
Frequently asked questions
- How do I install ato?
- Run
npx skills add atopile/packages. The install tabs above show the steps for each supported agent. - Which AI agents does ato work with?
- It is written for Cursor, as a Cursor Rules file. Other agents that read the same format can often use it too.
- Is ato safe to use?
- Our scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands. An AI review of the same text found nothing harmful. It declares no license and scores 78/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
- Is ato still maintained?
- The repository was last updated about 5 months ago. That is recent enough to be usable, but agent tooling moves fast, so check the instructions against your agent's current version.
Skill content
View source on GitHubdescription: ato is a declarative DSL to design electronics (PCBs) with. globs: *.ato, ato.yaml alwaysApply: true
ato is a declarative DSL to design electronics (PCBs) with. It is part of the atopile project. Atopile is run by the vscode/cursor/windsurf extension. The CLI (which is invoked by the extension) actually builds the project.
Not available in ato
- if statements
- while loops
- functions (calls or definitions)
- classes
- objects
- exceptions
- generators
Ato Syntax
ato sytax is heavily inspired by Python, but fully declarative. ato thus has no procedural code, and no side effects.
Examples of syntax
#pragma text
#pragma func("X")
# enable for loop syntax feature:
#pragma experiment("FOR_LOOP)
# --- Imports ---
# Standard import (newline terminated)
import ModuleName
# Import with multiple modules (newline terminated)
import Module1, Module2.Submodule
# Import from a specific file/source (newline terminated)
from "path/to/source.ato" import SpecificModule
# Multiple imports on one line (semicolon separated)
import AnotherModule; from "another/source.ato" import AnotherSpecific
# Deprecated import form (newline terminated)
# TODO: remove when unsupported
import DeprecatedModule from "other/source.ato"
# --- Top-level Definitions and Statements ---
pass
pass;
"docstring-like statement"
"docstring-like statement";
top_level_var = 123
# Compound statement
pass; another_var = 456; "another docstring"
# Block definitions
component MyComponent:
# Simple statement inside block (newline terminated)
pass
# Multiple simple statements on one line (semicolon separated)
pass; internal_flag = True
module AnotherBaseModule:
pin base_pin
base_param = 10
interface MyInterface:
pin io
module DemoModule from AnotherBaseModule:
# --- Declarations ---
pin p1 # Pin declaration with name
pin 1 # Pin declaration with number
pin "GND" # Pin declaration with string
signal my_signal # Signal definition
a_field: AnotherBaseModule # Field declaration with type hint
# --- Assignments ---
# Newline terminated:
internal_variable = 123
# Semicolon separated on one line:
var_a = 1; var_b = "string"
# Cumulative assignment (+=, -=) - Newline terminated
value = 1
value += 1; value -= 1
# Set assignment (|=, &=) - Newline terminated
flags |= 1; flags &= 2
# --- Connections ---
p1 ~ base_pin
mif ~> bridge
mif ~> bridge ~> bridge
mif ~> bridge ~> bridge ~> mif
bridge ~> mif
mif <~ bridge
mif <~ bridge <~ bridge
mif <~ bridge <~ bridge <~ mif
bridge <~ mif
# Semicolon separated on one line:
p_multi1 ~ my_signal; p_multi2 ~ sig_multi1
# --- Retyping ---
instance.x -> AnotherBaseModule
# --- Instantiation ---
instance = new MyComponent
container = new MyComponent[10]
templated_instance_a = new MyComponent
templated_instance_b = new MyComponent<int_=1>
templated_instance_c = new MyComponent<float_=2.5>
templated_instance_d = new MyComponent<string_="hello">
templated_instance_e = new MyComponent<int_=1, float_=2.5, string_="hello">
templated_instance_f = new MyComponent<int_=1, float_=2.5, string_="hello", bool_=True>
# Semicolon separated instantiations (via assignment):
inst_a = new MyComponent; inst_b = new AnotherBaseModule
# --- Traits ---
trait trait_name
trait trait_name<int_=1>
trait trait_name<float_=2.5>
trait trait_name<string_="hello">
trait trait_name<bool_=True>
trait trait_name::constructor
trait trait_name::constructor<int_=1>
# Semicolon separated on one line:
trait TraitA; trait TraitB::constructor; trait TraitC<arg_=1>
# --- Assertions ---
assert x > 5V
assert x < 10V
assert 5V < x < 10V
assert x >= 5V
assert x <= 10V
assert current within 1A +/- 10mA
assert voltage within 1V +/- 10%
assert resistance is 1kohm to 1.1kohm
# Semicolon separated on one line:
assert x is 1V; assert another_param is 2V
# --- Loops ---
for item in container:
item ~ p1
# For loop iterating over a slice
for item in container[0:4]:
pass
item.value = 1; pass
# For loop iterating over a list literal of field references
for ref in [p1, x.1, x.GND]:
pass
# --- References and Indexing ---
# Reference with array index assignment
array_element = container[3]
# --- Literals and Expressions ---
# Integer
int_val = 100
neg_int_val = -50
hex_val = 0xF1
bin_val = 0b10
oct_val = 0o10
# Float
float_val = 3.14
# Physical quantities
voltage: V = 5V
resistance: ohm = 10kohm
capacitance: F = 100nF
# Bilateral tolerance
tolerance_val = 1kohm +/- 10%
tolerance_abs = 5V +/- 500mV
tolerance_explicit_unit = 10A +/- 1A
# Bounded quantity (range)
voltage_range = 3V to 3.6V
# Boolean
is_enabled = True
is_active = False
# String
message = "Hello inside module"
# Arithmetic expressions
sum_val = 1 + 2
diff_val = 10 - 3ohm
prod_val = 5 * 2mA
div_val = 10V / 2kohm # Results in current
power_val = 2**3
complex_expr = (5 + 3) * 2 - 1
flag_check = state | MASK_VALUE
# Comparisons
assert voltage within voltage_range
assert length <= 5mm
assert height >= 2mm
# --- Multi-line variations ---
pass; nested_var=1; another=2
complex_assignment = (
voltage + resistance
* capacitance
)
G4 Grammar
parser grammar AtoParser;
options {
superClass = AtoParserBase;
tokenVocab = AtoLexer;
}
file_input: (NEWLINE | stmt)* EOF;
pragma_stmt: PRAGMA;
stmt: simple_stmts | compound_stmt | pragma_stmt;
simple_stmts:
simple_stmt (SEMI_COLON simple_stmt)* SEMI_COLON? NEWLINE;
simple_stmt:
import_stmt
| dep_import_stmt
| assign_stmt
| cum_assign_stmt
| set_assign_stmt
| connect_stmt
| directed_connect_stmt
| retype_stmt
| pin_declaration
| signaldef_stmt
| assert_stmt
| declaration_stmt
| string_stmt
| pass_stmt
| trait_stmt;
compound_stmt: blockdef | for_stmt;
blockdef: blocktype name blockdef_super? COLON block;
// TODO @v0.4 consider ()
blockdef_super: FROM type_reference;
// TODO @v0.4 consider removing component (or more explicit code-as-data)
blocktype: (COMPONENT | MODULE | INTERFACE);
block: simple_stmts | NEWLINE INDENT stmt+ DEDENT;
// TODO: @v0.4 remove the deprecated import form
dep_import_stmt: IMPORT type_reference FROM string;
import_stmt: (FROM string)? IMPORT type_reference (
COMMA type_reference
)*;
declaration_stmt: field_reference type_info;
field_reference_or_declaration:
field_reference
| declaration_stmt;
assign_stmt: field_reference_or_declaration '=' assignable;
cum_assign_stmt:
field_reference_or_declaration cum_operator cum_assignable;
// TODO: consider sets cum operator
set_assign_stmt:
field_reference_or_declaration (OR_ASSIGN | AND_ASSIGN) cum_assignable;
cum_operator: ADD_ASSIGN | SUB_ASSIGN;
cum_assignable: literal_physical | arithmetic_expression;
assignable:
string
| new_stmt
| literal_physical
| arithmetic_expression
| boolean_;
retype_stmt: field_reference ARROW type_reference;
directed_connect_stmt
: bridgeable ((SPERM | LSPERM) bridgeable)+; // only one type of SPERM per stmt allowed. both here for better error messages
connect_stmt: mif WIRE mif;
bridgeable: connectable;
mif: connectable;
connectable: field_reference | signaldef_stmt | pindef_stmt;
signaldef_stmt: SIGNAL name;
pindef_stmt: pin_stmt;
pin_declaration: pin_stmt;
pin_stmt: PIN (name | number_hint_natural | string);
new_stmt: NEW type_reference ('[' new_count ']')? template?;
new_count: number_hint_natural;
string_stmt:
string; // the unbound string is a statement used to add doc-strings
pass_stmt:
PASS; // the unbound string is a statement used to add doc-strings
list_literal_of_field_references:
'[' (field_reference (COMMA field_reference)* COMMA?)? ']';
iterable_references:
field_reference slice?
| list_literal_of_field_references;
for_stmt: FOR name IN iterable_references COLON block;
assert_stmt: ASSERT comparison;
trait_stmt
: TRAIT type_reference (DOUBLE_COLON constructor)? template?; // TODO: move namespacing to type_reference
constructor: name;
template: '<' (template_arg (COMMA template_arg)* COMMA?)? '>';
template_arg: name ASSIGN literal;
// Comparison operators --------------------
comparison: arithmetic_expression compare_op_pair+;
compare_op_pair:
lt_arithmetic_or
| gt_arithmetic_or
| lt_eq_arithmetic_or
| gt_eq_arithmetic_or
| in_arithmetic_or
| is_arithmetic_or;
lt_arithmetic_or: LESS_THAN arithmetic_expression;
gt_arithmetic_or: GREATER_THAN arithmetic_expression;
lt_eq_arithmetic_or: LT_EQ arithmetic_expression;
gt_eq_arithmetic_or: GT_EQ arithmetic_expression;
in_arithmetic_or: WITHIN arithmetic_expression;
is_arithmetic_or: IS arithmetic_expression;
// Arithmetic operators --------------------
arithmetic_expression:
arithmetic_expression (OR_OP | AND_OP) sum
| sum;
sum: sum (PLUS | MINUS) term | term;
term: term (STAR | DIV) power | power;
power: functional (POWER functional)?;
functional: bound | name '(' bound+ ')';
bound: atom;
// Primary elements ----------------
slice:
'[' (slice_start? COLON slice_stop? (COLON slice_step?)?)? ']'
// else [::step] wouldn't match
| '[' ( DOUBLE_COLON slice_step?) ']';
slice_start: number_hint_integer;
slice_stop: number_hint_integer;
slice_step: number_hint_integer;
atom: field_reference | literal_physical | arithmetic_group;
arithmetic_group: '(' arithmetic_expression ')';
literal_physical:
bound_quantity
| bilateral_quantity
| quantity;
bound_quantity: quantity TO quantity;
bilateral_quantity: quantity PLUS_OR_MINUS bilateral_tolerance;
quantity: number name?;
bilateral_tolerance: number_signless (PERCENT | name)?;
key: number_hint_integer;
array_index: '[' key ']';
// backwards compatibility for A.1
pin_reference_end: DOT number_hint_natural;
field_reference_part: name array_index?;
field_reference:
field_reference_part (DOT field_reference_part)* pin_reference_end?;
type_reference: name (DOT name)*;
// TODO better unit
unit: name;
type_info: COLON unit;
name: NAME;
// Literals
literal: string | boolean_ | number;
string: STRING;
boolean_: TRUE | FALSE;
number_hint_natural: number_signless;
number_hint_integer: number;
number: (PLUS | MINUS)? number_signless;
number_signless: NUMBER;
Most used library modules/interfaces (api of them)
interface Electrical:
pass
interface ElectricPower:
hv = new Electrical
lv = new Electrical
module Resistor:
resistance: ohm
max_power: W
max_voltage: V
unnamed = new Electrical[2]
module Capacitor:
capacitance: F
max_voltage: V
unnamed = new Electrical[2]
interface I2C:
scl = new ElectricLogic
sda = new ElectricLogic
frequency: Hz
address: dimensionless
interface ElectricLogic:
line = new Electrical
reference = new ElectricPower
For the rest use the atopile MCP server
get_library_interfacesto list interfacesget_library_modulesto list modulesinspect_library_module_or_interfaceto inspect the code
Ato language features
experimental features
Enable with #pragma experiment("BRIDGE_CONNECT")
BRIDGE_CONNECT: enables p1 ~> resistor ~> p2 syntax
FOR_LOOP: enables for item in container: pass syntax
TRAITS: enables trait trait_name syntax
MODULE_TEMPLATING: enables new MyComponent<param=literal> syntax
modules, interfaces, parameters, traits
A block is either a module, interface or component. Components are just modules for code-as-data. Interfaces describe a connectable interface (e.g Electrical, ElectricPower, I2C, etc). A module is a block that can be instantiated. Think of it as the ato equivalent of a class. Parameters are variables for numbers and they
Truncated for display — read the full file on GitHub.
Related Skills
ai-job-search
44.3kThe job search that runs on your machine. AI job application framework built on Claude Code: evaluate postings, tailor CVs, write cover letters, prep interviews. Fork it and own it.
claude-howto
41.7kA visual, example-driven guide to Claude Code — from basic concepts to advanced agents, with copy-paste templates that bring immediate value.
algorithmic-art
177.9kCreating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems.
design
130.2kComprehensive design skill: brand identity, design tokens, UI styling, logo generation (55 styles, Gemini, Atlas Cloud, or MuAPI AI), corporate identity program (50 deliverables, CIP mockups), HTML presentations (Chart.js), banner design (22 styles, social/ads/web/print), icon design (15 styles, SVG…
Trust signals
From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.
