Skills
Capella Headless Authoring
Skill
capella-headless-authoring. Create and modify Eclipse Capella 6.0 models from Python with no GUI, using Python4Capella over EASE inside Innexis Architect Explorer - installing it with the p2 director, the workspace bootstrap that makes projects visible, the exact element-creation idioms for PhysicalComponent/PhysicalFunction/ComponentPort/allocation, and the two silent-success traps in the API that write nothing or the wrong name while reporting success. Use for any Teamcenter-to-Capella import, bulk Capella edit, or Capella scripting.
Proven end to end 2026-08-14 against Capella 6.0.0 inside Innexis AE 2026.1
(D:\Innexis_AE\codebench\eclipse). Every claim below was verified by re-reading the saved
.capella file, never by an exit code.
This is the route for getting Teamcenter data into Capella. There is no other door: a full scan of all 1,958 jars and 75 directory bundles found no generic data-import wizard, and no ReqIF or Requirements viewpoint is installed.
Install
Use release 1.2.1. Its shipped test report is report-6.0.0.xml, matching Capella 6.0.0;
1.3.0+ target Capella 7.x. Asset org.eclipse.python4capella.update.zip from the 1.2.1 tag
(61,057,541 bytes). Prerequisites (EASE 0.8.0, Py4J, Jython engine, PyDev) are already installed
in AE.
# extract the update site first, then:
eclipsec.exe -vm D:/Innexis_AE/codebench/jre/bin/java.exe -nosplash -consoleLog \
-application org.eclipse.equinox.p2.director \
-repository file:/<extracted-site-dir> \
-installIU org.eclipse.python4capella.feature.feature.group,org.eclipse.python4capella.commandline.feature.feature.group \
-destination D:/Innexis_AE/codebench/eclipse -profile SGXXProfile
Profile id comes from configuration/config.ini → eclipse.p2.profile. Verify by artifact:
plugins 1958 → 1962, features 405 → 407.
⚠ -vm is mandatory. There is no jre beside the launcher (AE's is one level up at
codebench\jre), so the VM resolves ambiguously, nothing satisfies osgi.ee JavaSE 11, and the
director exits 13 having installed nothing.
⚠ eclipsec.exe raises a modal GUI dialog on error even in console mode. A run that appears to
hang is usually blocked on that box. Background it.
⚠ A p2 stack trace here does not mean your operation failed. Siemens' own Vista feature has an
invalid version string in its advice file and throws on every p2 operation on this install:
IllegalArgumentException: Neither raw version nor format was specified: vista2025_4beta. It threw
twice during a successful install. Check the artifact.
Running a script
eclipsec.exe -vm D:/Innexis_AE/codebench/jre/bin/java.exe -nosplash -consoleLog \
-data <workspace-dir> \
-application org.polarsys.capella.core.commandline.core \
-appid org.eclipse.python4capella.commandline \
<ABSOLUTE path>\script.py [script args]
P4C contributes to org.polarsys.capella.core.commandline.core.commandline, Capella's own
command-line extension point, so no custom plugin is needed. It selects the script by .py suffix
and runs it through org.eclipse.ease.service.ScriptService.
The engine is CPython 3.13.2 via Py4J. Write Python 3. Two messages print on every run and are
red herrings: ModuleNotFoundError: No module named 'imp' and
org.python.pydev.core.NotConfiguredInterpreterException: Python not configured. The script runs
regardless.
⚠ From Git Bash set MSYS_NO_PATHCONV=1 and MSYS2_ARG_CONV_EXCL='*', then pass every path
in Windows form. A workspace argument /AeTest/x.aird was silently rewritten to
C:/Program Files/Git/AeTest/x.aird. And with conversion off, a POSIX -data /c/Users/... made
Eclipse create an empty workspace at D:\c\Users\..., find nothing, and block on a dialog.
workspace://... survives either way because of the double slash.
The workspace bootstrap (this is the part that blocks people)
Projects must be registered, not merely present. A .project file on disk inside the workspace
folder is invisible to Eclipse, and creating empty
.metadata/.plugins/org.eclipse.core.resources/.projects/<name>/ directories does not work
either. And there is no absolute-path escape, because CapellaModel.open() demands a workspace
resource:
if CapellaPlatform.getWorkspaceFile(obj) is None:
raise AttributeError("the .aird file doesn't exist: " + obj)
The way through: a script loaded from an absolute path outside the workspace can bootstrap it.
loadModule('/System/Resources')
for n in ["Python4Capella", "AeTest"]:
p = getProject(n)
if p is None or not p.exists():
importProject("C:/.../ws/" + n)
include('workspace://Python4Capella/simplified_api/capella.py')
if False:
from simplified_api.capella import *
/System/Resources also gives createProject, linkProject, getProject, and direct Java access
through org, java, javax, gateway.
The Python4Capella workspace project itself is shipped inside the plugin at
plugins/org.eclipse.python4capella_*.jar → zips/Python4Capella.zip. Extract it; it carries
simplified_api/, java_api/, utilities/ and sample_scripts/.
Element creation idioms (all four verified in the saved file)
CE = org.polarsys.capella.core.model.helpers.CapellaElementExt
FaFactory = org.polarsys.capella.core.data.fa.FaFactory.eINSTANCE
model = CapellaModel()
model.open("/AeTest/Simple_Example.aird") # workspace path to the .aird
se = model.get_system_engineering()
pa = se.get_physical_architecture()
pc_pkg = pa.get_physical_component_pkg()
pf_pkg = pa.get_physical_function_pkg()
model.start_transaction()
try:
pc = PhysicalComponent()
pc_pkg.get_owned_physical_components().add(pc)
CE.creationService(pc.get_java_object())
pc.set_name("TC_ECU_1") # AFTER creationService
fn = PhysicalFunction()
pf_pkg.get_owned_physical_functions().add(fn)
CE.creationService(fn.get_java_object())
fn.set_name("TC_FUNC_1")
port = ComponentPort() # raw EMF: no simplified-API accessor
pc.get_java_object().getOwnedFeatures().add(port.get_java_object())
CE.creationService(port.get_java_object())
port.set_name("TC_PORT_1")
alloc = FaFactory.createComponentFunctionalAllocation()
alloc.setSourceElement(pc.get_java_object())
alloc.setTargetElement(fn.get_java_object())
pc.get_java_object().getOwnedFunctionalAllocation().add(alloc)
except:
model.rollback_transaction()
raise
else:
model.commit_transaction()
model.save()
creationService() also creates the corresponding Part (Capella component/part duality) and
the later set_name propagates to it. Do not author Parts by hand.
⚠⚠ Two silent-success traps in this API
Both write nothing or the wrong thing while every layer reports success. Both were caught only by re-reading the file.
1. set_name() before creationService() is discarded. With the ordering used by the shipped
sample_scripts/Import_physical_components_from_xlsx.py, the element is created and saved carrying
Capella's default name (PC 2). Transaction commits, save returns, the count increments. At
scale this yields N components named PC 1..PC N with no source identity at all.
⇒ Set the name AFTER. Do not copy that sample verbatim.
2. Any getter backed by capella_query_by_name is READ-ONLY, and .add() on it is a no-op.
def get_allocated_physical_functions(self):
return capella_query_by_name(self, "Allocated Physical Functions")
pc.get_allocated_physical_functions().add(fn) raises nothing and writes nothing: the
ComponentFunctionalAllocation count stayed at 8. Use the FaFactory route above.
⇒ Grep capella.py for capella_query_by_name before trusting any collection-style setter.
Testing discipline this forces
A probe that wraps each step in try/except and prints PASS when nothing throws will certify both
traps above. It printed PASS allocate function to component for an operation that wrote nothing.
⇒ Assert on the artifact, per step. Count with an exact pattern and diff against a pristine copy:
grep -c 'pa:PhysicalComponent"' model.capella # WITH the closing quote
⚠ grep -c 'core\.data\.pa:PhysicalComponent' also matches PhysicalComponentPkg and will give
you a contaminated baseline.
Which ARCADIA layer to write into
AE reads the Physical Architecture layer only. Counted across all 10 shipped AE tutorials,
unanimous: 16-34 PhysicalComponent and 3-10 PhysicalFunction in Physical, versus exactly 2
in System Analysis and 2 in Logical (Capella's empty default skeleton), and nothing in
Operational.
Two options for TC-sourced content:
- write straight into Physical: fastest, discards ARCADIA discipline;
- land it at System and run Capella's top-down transition to project System → Logical →
Physical. Plugins are installed (
org.polarsys.capella.core.transition.system.topdown). The transition creates realization links so traceability survives, and it is re-runnable with the 24 installed diffmerge plugins, which matters for a living model. Transition has not been run headless here; it is not registered as a command-line contributor.
Related
innexis-ae-model-xmlfor the AE analysis model these elements feed.innexis-ae-headlessfor the engine andvalidateas an acceptance gate.diagnose-silent-failurefor the general discipline; both traps here are textbook cases.
Generated from skills/capella-headless-authoring/SKILL.md in the tc-automation-skills library, which is the canonical copy and also serves as the agent skill set for Teamcenter work.