onnx-modifier: editing ONNX graphs in the browser instead of in Python
A tool to modify ONNX models in a visualization fashion, based on Netron and Flask.
At a glance
- What is it?
- onnx-modifier is a Flask and Netron based tool that lets you change an ONNX model graph by clicking on it, with the edits collected in a panel and applied through the Python ONNX API on save. It supports node deletion and addition, renaming, model input and output changes, attribute edits and initializer edits, and it ships as a script, a Windows executable and a Docker image.
- Who is it for?
- Adopt onnx-modifier when you need to adjust an existing ONNX graph and the iteration cost of writing Python, running it, reopening the model in a viewer and looking again is what slows you down, since the edits are visible as you make them. Do not adopt it for building a model from scratch, since the editing operations it lists are all modifications to a graph that already exists.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 118 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The iteration cost of edit, run, look, repeat
The problem onnx-modifier sets out to solve is described in the README as a workflow problem rather than a capability problem. The common way to edit an ONNX model is to visualise the graph and then edit it with the ONNX Python API. That works fine, the README says, but you have to code the edit and then visualise it to check, and the two processes may iterate many times, which is time-consuming.
So the tool is built around making the edit visible at the moment you make it. You work in the visualisation panel, the editing information is summarised there, and the Python ONNX API is invoked automatically at the end when the model is written. The claim is that the time saved comes from collapsing the loop between making a change and seeing what it did.
That framing explains the design choice that follows from it. The tool is built on Netron, the network viewer, and on Flask, described in the README as a lightweight web application framework. The graph rendering, the node inspector and the model file handling come from Netron, and the browser UI around them is served by Flask. It runs locally, in a browser, and the model is uploaded from disk rather than fetched from somewhere.
The project is MIT licensed, the primary language is JavaScript, the default branch is `master`, and the last push was on 2026-06-27. There are no GitHub releases attached to the repository, and the repository also carries a Chinese README, a `docs/` directory with an update log and a TODO list, and a wiki with the design overview for contributors.
The nine editing operations, and which of them are experimental
The README lists the supported operations, and the list is worth reading as a scope statement rather than a feature list.
Deleting nodes and adding new nodes come first. Then renaming the node inputs and outputs, renaming the model inputs and outputs, adding new model outputs, and adding new model inputs. The last three are editing model input shape, editing attributes of nodes, and editing model initializers.
That is nine operations, and every one of them is a modification of an existing graph. There is no operation for creating a model from nothing, and there is no operation for wiring a layer to a layer in an arbitrary way. The tool is for surgery on a graph that already exists, which is the honest scope for something built on top of a viewer.
The README is clear about which parts are still rough. Node addition is described as supported experimentally. So are the two checkboxes on the download panel, where `shape inference` runs shape inference when saving the model, built on onnx-tool, and `clean up` removes unused nodes and tensors in the manner of ONNX GraphSurgeon. Both are labelled experimental, and a third note says the default value of an attribute may not be supported well in the current version.
For the attribute and input types that matter when adding a node, the README gives three specifics. The `?` next to the node type and the `+` next to each attribute give reference material while you fill the form. Attributes of type `list` are split with a comma and the brackets are not needed. And inputs and outputs of type `list` have their own handling.
Launching it from the command line, and the three ways in
There are three ways to start the tool, and the first is the normal development path.
Clone the repository and install the Python requirements.
git clone https://github.com/ZhangGe6/onnx-modifier.git
cd onnx-modifier
pip install -r requirements.txtThen start the application.
python app.pyFlask prints the URL it is serving on, and the README says to click that URL, defaulting to `http://127.0.0.1:5000/`, which opens the tool in a browser.
The requirement set is three pinned releases, and the pins are the first thing to look at when you install.
onnx==1.13.0
flask==2.2.5
onnx-tool==0.8.1onnx-tool is the third-party tool the shape inference feature is built on, and it is installed by default rather than being optional.
The second way is a prebuilt executable, and it is Windows only. The README links `onnx-modifier.exe` at 28.3MB through Google Drive and Baidu NetDisk, and says to double-click it, with Edge as the default runtime environment. The author notes that the process of making the executable is recorded in `app_desktop.py`, and that executables for other platforms are left for future work. So the executable route is a convenience for one operating system rather than a supported distribution channel.
The third way is a container, and it is the route that suits a server. The README builds the image from the Dockerfile in the repository root.
git clone [email protected]:ZhangGe6/onnx-modifier.git
cd onnx-modifier
docker build --file Dockerfile . -t onnx-modifierThen run it with the port mapped and a local folder for the output models.
mkdir -p modified_onnx
docker run -d -t \
--name onnx-modifier \
-u $(id -u ${USER}):$(id -g ${USER}) \
-v $(pwd)/modified_onnx:/modified_onnx \
-p 5000:5000 \
onnx-modifierThe container runs as your own user id and group id, so the files it writes into the mounted folder are owned by you rather than by root. The modified models end up in that folder, and the interface is on port 5000. Note that the Dockerfile copies `static`, `templates` and `utils` into the image and runs `python3 app.py --host='0.0.0.0' --debug=True`, so the service binds all interfaces and starts in debug mode. That is fine on a laptop and worth changing on a shared host.
Deleting nodes has a preview step and a backtracking pass
Deletion is the operation with the most detail in the README, and it is the one to understand first because it shows how the preview model works.
There are two modes. `Delete Single Node` removes only the node you clicked. `Delete With Children` also removes every node rooted on the clicked node, which the README calls convenient and natural when you want to delete a long path. The implementation of that mode is based on a backtracking algorithm, so the traversal follows the graph downward from the node you picked rather than relying on a precomputed list of dependents.
The preview behaviour is what makes this usable. Deleted nodes are shown in grey mode first, they are not yet gone. If a deletion was a mistake, the `Recover Node` button puts the node back into the graph. Only when you press `Enter` does the deletion take effect, and the updated graph then renders on the page automatically.
That two-step pattern is the core interaction of the whole tool, and it is worth generalising: the visual panel holds the pending state, the graph shows the pending state in a distinguishable way, and the underlying model is only changed when you commit. The same shape applies to adding a node, where a new empty node of the chosen type appears on the graph and you fill in its attributes and its inputs and outputs in the sidebar before it is real.
The sidebar is where node-level operations live. Clicking a specific node invokes it, and that is where you rename its inputs and outputs and edit its attributes. The graph-level buttons sit on the top left of the page instead, and there are three of them: `Reset`, `Download` and `Add node`.
Adding a node, and the operator catalogue behind the selector
Adding a node is a three step flow, and the README describes it as easy. You choose a node type in the selector and click `Add node`, an empty node of that type appears on the graph. You click it and edit it in the sidebar, filling in the node attributes, which are `undefined` by default, and the inputs and outputs, which decide where the node will be inserted into the graph. Then you are done.
The selector is where the coverage of the tool is visible, and the README counts the operator types per domain: 171 in `ai.onnx`, 4 in `ai.onnx.preview.training`, 18 in `ai.onnx.ml` and 1 in `com.microsoft`. That is a broad catalogue of the standard operator set, not a curated subset.
The Inputs and Outputs fields are the part with real subtlety, because they are not names but positions. The README says the inputs and outputs decide where the node will be inserted in the graph, which means you are describing the edge connections by naming the tensors they attach to. The attributes of type `list` are split with a comma and the square brackets are not needed, and the README recommends filling in all attributes rather than leaving them as `undefined`, because the default value may not be supported well in the current version.
So the workflow for adding a node is closer to writing a small function definition by hand than to dragging a box on a canvas, and that is a fair characterisation of what the tool does. The canvas makes the graph structure legible, but the data you type into the sidebar is what actually determines the result, and the type of the result is decided by the operator you picked.
Where the tool sits against the alternatives
The README names the comparison points itself, and they clarify the trade-off.
The alternative is the Python ONNX API, which the README calls the common way and says works fine. onnx-modifier does not replace it, it wraps it. Every operation the tool performs is finally applied by the Python ONNX API, so the result is a normal ONNX model that any runtime can load, and a script using the API can still do things the tool does not cover.
For the clean up step the README points at ONNX GraphSurgeon, and for shape inference at the onnx-tool project and the ONNX shape inference documentation. So the tool borrows capabilities from both rather than reimplementing them, which is sensible but also means the experimental features inherit the behaviour and the sharp edges of tools with their own design assumptions.
The other comparison is with Netron itself, since Netron is the base. Netron is a viewer, and the README's framing is that coding the edit and then viewing it is the loop that costs time. onnx-modifier makes the viewing part editable, so the difference from using Netron plus a script is entirely in the editing half.
There is a limit to that. The tool covers the nine operations listed and nothing more. If your task is pruning a model to a specific subgraph, renaming an input to match a downstream contract, or adjusting an attribute after a quantisation pass, it covers that. If your task is restructuring a computation, writing the ONNX code is the more direct route, and the tool's own design implies it, since every edit ends up as a call to the Python API anyway.
Editorial conclusion
Adopt onnx-modifier when you need to adjust an existing ONNX graph and the iteration cost of writing Python, running it, reopening the model in a viewer and looking again is what slows you down, since the edits are visible as you make them. Do not adopt it for building a model from scratch, since the editing operations it lists are all modifications to a graph that already exists. Before you rely on it, check the pinned versions in `requirements.txt`, because `onnx==1.13.0` and `flask==2.2.5` are fixed releases, and note that shape inference, graph clean up and node addition are all marked experimental in the README.
Frequently asked questions
How do I install and run onnx-modifier?
Clone the repository, run `pip install -r requirements.txt`, then `python app.py` and open the URL Flask prints, which defaults to `http://127.0.0.1:5000/`. There is also a Windows executable and a Docker route, where the image is built with `docker build --file Dockerfile . -t onnx-modifier` and run with port 5000 mapped and a local folder mounted for the output models.
What editing operations does onnx-modifier support?
The README lists deleting nodes, adding new nodes, renaming node inputs and outputs, renaming model inputs and outputs, adding new model outputs, adding new model inputs, editing model input shape, editing node attributes and editing model initializers. Node addition, shape inference and clean up are all marked experimental.
What is the difference between deleting a single node and deleting with children?
`Delete Single Node` removes only the node you clicked, while `Delete With Children` also removes every node rooted on it, which the README says is convenient for deleting a long path of nodes. The implementation of that mode is based on a backtracking algorithm, and deleted nodes are shown in grey until you press `Enter` to commit.
Which ONNX operators can onnx-modifier add?
The selector covers the supported operator types in the domains `ai.onnx` with 171 types, `ai.onnx.preview.training` with 4, `ai.onnx.ml` with 18 and `com.microsoft` with 1. The README advises filling in all attributes rather than leaving them as `undefined`, since defaults may not be supported well in the current version.
Which Python packages does onnx-modifier depend on?
The `requirements.txt` pins `onnx==1.13.0`, `flask==2.2.5` and `onnx-tool==0.8.1`. The tool is built on Netron for the graph viewer and Flask for the web application, and the shape inference feature is built on onnx-tool.
How do I save a modified ONNX model from onnx-modifier?
The `Download` button on the graph-level panel saves the model to disk, and it has two checkboxes next to it. Selecting `shape inference` runs shape inference when saving, and selecting `clean up` removes unused nodes and tensors in the manner of ONNX GraphSurgeon. Both are described as experimental.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/zhangge6-onnx-modifier)Was this useful?