FERS from the terminal and from coding agents
The Python package puts the solver on your machine, and since 0.1.100 a fers command with it. A shell, a script, a CI job or a coding agent validates a model, solves it to a file and reads only the numbers it needs — in engine time, with no server round-trip and nothing to connect.
1. Install, and check what you have
One package carries the modelling objects, the compiled engine and the command. fers doctor prints the versions and where the examples live; with a key it also asks the licence server whether the key is accepted.
pip install FERS
fers doctor --offline # versions and where the examples live
fers versionWithout an API key the engine runs on the free tier, for non-commercial use up to 100 members, and makes no network call at all. Put a key in FERS_API_KEY (or pass --api-key) for Pro, which covers commercial use; the engine then verifies it with ferscloud.com once per solve.
2. The loop: author, validate, solve, read
Authoring stays in Python, where the objects and the numbered examples are. The command takes over at the file: it validates the JSON against the engine's input schema, hands it to the engine unchanged, and reports in one line.
- Author the model in Python — Build it with
fers_corein SI units and save it withmodel.save_to_json("model.json").fers examples listandfers examples show 001are the quickest reference for the object API. - Validate the file —
fers validate model.jsonchecks it against the input schema and names the field that fails.fers schema --listandfers schema Memberprint the schema when a field name is in doubt. - Solve to a file —
fers solve model.json --out results.jsonstreams the results to the file. Stdout is one summary line, or a JSON object with--json. - Read a selection — Load the solved file with
FERS.from_jsonand read the load case or combination you need, or ask the engine for less up front with aResultRequest.
python build_model.py # authors with fers_core and saves model.json
fers validate model.json # the input schema, naming the field that fails
fers solve model.json --out results.json # the engine streams the results to the file
# solved: 3 load cases, 8 combinations in 0.4 s -> results.json (2.1 MB)3. Results stay in files
fers solve never parses the results: the engine writes them and the command reads back only enough for the summary. A model that writes hundreds of megabytes costs the process, and an agent's context, nothing. The exit code says what happened, so a script or an agent can branch on it without reading prose.
- 0 solved. 4 solved, but the engine recorded failures (
solve_failures,load_case_failures): read them before using any number. - 1 the engine refused or failed the solve, with its message on stderr. 2 bad input: a missing file, invalid JSON, a model that fails the schema.
- 3 licence: no key where one is needed, a rejected key, or the licence handshake timed out.
- The summary line counts load cases, combinations, recorded failures, result sets that did not converge, and the engine's errors and warnings.
from fers_core import FERS, ResultBlock, ResultRequest
# Before solving: ask the engine for only the blocks you will read.
model.settings.analysis_options.result_requests = [
ResultRequest(ResultBlock.REACTIONS, limit_state="ULS"),
ResultRequest(ResultBlock.NODE_DISPLACEMENTS, components=["dy"]),
]
model.save_to_json("model.json")
# After "fers solve model.json --out results.json":
solved = FERS.from_json("results.json")
case = solved.resultsbundle.loadcombinations["ULS 1"]
print(case.reaction_nodes["1"].nodal_forces.fy)4. Code checks and reports
A model that carries unity-check definitions — check_beam in fers_core.builders builds one in a line — gets its EN 1993-1-1 verdict from fers check: status, utilization and the governing member per check. fers report renders the hand-calc HTML report from an already solved document, without solving again.
fers check beam.json --out beam_solved.json
# ec3: Green, utilization 0.778, governing 1 in combination 1
fers report beam_solved.json --out report.html5. Catalogues and the schema
The section tables (EN, British Steel, AISC) and the material presets are the same ones the Python objects resolve, printed in SI so a value can be checked against a handbook before it goes into a model.
fers sections list --series HEB
fers sections get IPE200 # h, b, i_y, i_z, j, area, wel, wpl ... in m, m2, m4
fers materials list
fers materials get S355 --json
fers schema --list # the schema's definitions, one line each
fers schema Member # one definition in full6. Coding agents and the skill file
An agent with a shell — Claude Code, Codex, Cursor's agent, a CI runner — needs no server and no connector: the package is the solver. What it needs is the working loop above in a form it reads before starting, and that is what the skill file is: one page in the skill format with the install step, the loop, how to read results, and when to use the MCP server instead.
The file ships inside the package, and fers skill --install . writes it to .claude/skills/fers/SKILL.md, where Claude Code looks; fers skill --path names it for any other agent. It also lives in the FERS_core repository. Agents that read rather than call still have llms.txt and the markdown twin of this page at /docs/command-line.md.
fers skill --install . # writes .claude/skills/fers/SKILL.md, where Claude Code looks
fers skill --path # the file's path, for any other agent
fers skill # or read it7. CLI or MCP?
Where the agent runs decides, not which protocol is better in the abstract. Both routes run the same engine and return the same numbers.
- A terminal agent (Claude Code, Codex, a CI job) installs the package: the solve runs on its own machine in engine time, there are no request limits or timeouts, results stay in files, and it authors in Python against the examples.
- A desktop or editor client (Claude Desktop, Cursor, VS Code, ChatGPT desktop) uses the local MCP server: it solves on the same machine, and one tool call returns the checked numbers. A terminal agent can use it too; for a turnkey check it needs fewer turns than the command.
- A chat app in a browser or on a phone uses the hosted MCP server: it builds and validates the model and returns a link that solves it in your browser.
- Both can share one account: the API key that raises the command's limits is the key the MCP server accepts.
Related pages
See also
Frequently asked questions
Does `fers solve` run on my machine or in the cloud?
Do I need an API key?
FERS_API_KEY or pass --api-key; fers doctor tells you whether it is accepted.Why does `fers solve` not print the results?
FERS.from_json or a ResultRequest reads the part you need.Can I use the command in CI?
--json output, and the engine needs no display or GPU. Pin the package version, set FERS_API_KEY as a secret if the models exceed the free limit, and cache the wheel.