Library / SDK
napalm-automation/napalm avatar
napalm-automation/napalm

napalm-automation/napalm: one API for many routers, and four installed commands

Network Automation and Programmability Abstraction Layer with Multivendor support

2,509 stars593 forksPythonApache-2.0

At a glance

What is it?
NAPALM gives network devices a single Python API across vendors, parsing text CLI output where no API exists. Its README documents one of the four console commands it installs, and disagrees with its own packaging about which Python versions it needs.
Who is it for?
NAPALM is a good fit when you own the devices and want one code path across vendors, and a poor fit if you need a per-vendor feature the abstraction does not model. Three things to check before you build on it.
Can I use it commercially?
Yes. Apache-2.0 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 54 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 5, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The README says Python 3.9, the packaging metadata requires 3.10

The README carries three separate notes about Python versions, one per major line, and the newest of them does not match the project metadata.

code
requires-python = ">=3.10"
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",

The README says that from release 5.1.0 onward the library supports Python 3.9 and later only, that 5.0.0 raised the floor to 3.8, and that 4.0.0 raised it to 3.7. The packaging file requires 3.10 or newer and the classifiers stop at 3.14, with no 3.9 entry. So a reader on Python 3.9 who trusts the newest note, which is also the note nearest the install command, will attempt an install the metadata refuses. Three notes for three releases is also more bookkeeping than the situation seems to need, since one sentence naming the current floor would cover every line at once. The classifier list is the part worth keeping in mind: the package declares support for five interpreter versions from 3.10 to 3.14, so the matrix you would test against is wider than the three release lines the README walks through.

Four console commands are installed and the README shows one

The packaging file declares four entry points under scripts, all pointing into the same clitools module: napalm, plus cl_napalm_configure, cl_napalm_test and cl_napalm_validate. The README walks through the first and never mentions the other three. So an installation puts three commands on your path that have no coverage in the project's own README, which is where a new user looks first. Their names imply distinct jobs. One configures a device, one runs the test suite against it, and one validates something, either a configuration or a candidate set of methods, since the library's whole purpose is to expose a uniform method set across vendors. That is exactly the kind of tool that would be worth having documented, because it is the answer to the question the README keeps raising and never answering: how do you find out whether your device and your credentials actually work. The FAQ section gestures at the same problem with a command line and a checklist, which is the documented path to an answer, but the three commands built for the job sit outside the file.

The password is a command line argument, so it lands in shell history

The documented way to talk to a device is one long command, and the credential is one of its arguments.

bash
$ napalm --vendor VENDOR --user USERNAME --password PASSWORD --optional_args OPTIONAL_ARGS HOSTNAME call get_facts

Four arguments are mandatory, vendor, username, password and hostname, and optional arguments are passed as comma separated values in a single string. The README's worked example targets one vendor, sends a user and a password, and sets two optional values, a non-default port and a switch that turns off configuration locking. Passing a secret as an argument is the weak point in that design: the value ends up in your shell history, and while the command runs it is visible to anything on the host that can list processes. The library depends on paramiko and netmiko for SSH, so the transport underneath is a normal SSH session, which means a key-based or agent-based login is the natural alternative to a password argument. Nothing in the README says the argument is optional, and nothing in the visible documentation describes an environment variable or a config file that would keep the secret out of the command line. For a tool whose job is touching production network gear, that is the first thing to change.

Every failure is answered with a checklist that assumes the reader is wrong

The FAQ section exists to reduce support load, and it does that by walking through five checks before you file a question: install the latest release, confirm you can reach the device with the credentials you were given, check the device against the minimum requirements, look for operating system specific constraints, and then try the library from the command line. The fourth item is where the real work is delegated, and it names two of them outright, the XML agent on IOS-XR and the NXAPI feature on NXOS. Both are features you have to switch on inside the device before a library can talk to it, which is the shape of the problem this abstraction cannot solve for you. After the checklist, the file states that if you still have errors, this looks like a problem with your environment setup. That is the only diagnosis on offer. There is no error catalogue, no mapping from a vendor error string to a cause, and no troubleshooting section anywhere in the file, so a device that rejects a method for a vendor-specific reason is indistinguishable from a device you were simply not allowed to log into.

Where no API exists, the library parses the command line output

The direct dependencies are what explain how one API covers so many vendors, and they split into three transport stacks plus two text parsing libraries.

code
"paramiko>=3.5.0",
"textfsm>=1.1.3",
"pyeapi>=1.0.2",
"netmiko>=4.4.0",
"junos-eznc>=2.7.4",
"lxml>=4.3.0",
"ncclient>=0.6.16",
"ttp>=0.9.5",
"ttp_templates>=0.3.7",

There is a vendor-native client for Arista through the eAPI library, one for Junos, a NETCONF client, an XML parser for the agents that speak XML over SSH, and two SSH libraries for everything that does not. Then there are the last two lines, a template engine and a template collection, which is the answer to the awkward case: a device family with no usable API still prints a table, and the library reads that table. That design is why the documentation keeps sending you to a caveats page per operating system, because the reliability of get_facts on any given platform depends on whether a template matched its output. jinja2 is in there too, for the configuration side of the library, and netaddr for the address arithmetic that interface and route methods need.

The Makefile has exactly one target and it builds the documentation

The whole Makefile is three lines of real content, and the target is called doctest.

code
.PHONY: doctest
doctest:
	cd docs && make clean
	cd docs && sphinx-build -W -b html -d _build/doctrees . _build/html

It builds the documentation with warnings treated as errors, which is a strict and sensible setting for docs. What is missing is the rest: no test target, no lint target, no type check target, no build target. Those live elsewhere, and the root listing shows where. There is a mypy.ini for static typing, a committed uv.lock with a build backend pinned to a narrow uv release range, a test/ directory, a vagrant/ directory for provisioning, and a CONTRIBUTING.md. So the repository carries real development machinery while the Makefile, the one file most contributors try first, exposes only the docs build. The vagrant directory is the more interesting of the two: device automation is only testable against something that behaves like a router, and this project keeps its provisioning outside the package so the docs can stay a single command.

Every item in the News section predates the current release line

The README ends with a News section that has not been touched in years. Its blog posts are from 2015 through 2017, its presentations are from NANOG 64, a 2015 Netnod meeting, a 2015 Euro-IX forum and NANOG 68, and its single podcast is from 2015. The release line those pieces describe is long gone: 5.0.0 shipped 2024-04-10, 5.1.0 on 2025-08-05 and 5.2.0 on 2026-07-27. The last recorded push to the default branch, which is develop rather than main, is 2026-08-12. Two other things in the same file are worth a look. The project records no homepage at all, and the packaging metadata fills that gap by pointing its own Homepage field at its own repository. And the Contact section offers one route, a Slack channel named napalm on the network.toCode() team, reached through a Heroku-hosted team URL, while the FAQ a few lines earlier tells you that you may submit questions by email or on Slack. The email channel the FAQ relies on is not the one the contact section documents.

Editorial conclusion

NAPALM is a good fit when you own the devices and want one code path across vendors, and a poor fit if you need a per-vendor feature the abstraction does not model. Three things to check before you build on it. Read the caveats page for your operating systems, because the README itself points there twice and the checklist it offers ends at the platform features you have to switch on yourself. Match your Python to the packaging metadata rather than the README, because the two disagree about the floor. And decide how you will pass credentials, since the documented command line takes the password as an argument, which puts it in your shell history and in the process table while the session is open. For anything beyond a read-only call, test against a lab first: the project's own test and provisioning material lives in vagrant/ rather than in the docs you are reading.

Frequently asked questions

What does napalm-automation/napalm do?

It is an Apache-2.0 Python library that implements one set of functions for interacting with different router vendor devices through a unified API, covering connections, configuration changes and data retrieval. Each supported network operating system is reached through its own driver.

Which Python versions does napalm support?

The packaging metadata requires Python 3.10 or newer, and its classifiers list 3.10 through 3.14. The README's notes are older: releases from 5.1.0 need 3.9 or later, from 5.0.0 need 3.8 or later, and from 4.0.0 need 3.7 or later.

How do I install or upgrade napalm?

The install command is pip install napalm, and upgrading is the same command with a -U flag. The Dockerfile builds an image on python:3.12-slim-bookworm whose entrypoint is the napalm command itself.

How do I check whether napalm can reach my device?

The README's checklist ends with the CLI form napalm --vendor VENDOR --user USERNAME --password PASSWORD --optional_args OPTIONAL_ARGS HOSTNAME call get_facts. Vendor, username, password and hostname are mandatory, and optional arguments are given as comma separated values.

Which automation frameworks can use napalm?

The README names three. Ansible through a separate napalm-ansible repository, SaltStack, which it says has been fully integrated since the release codenamed Carbon in 2016.11, and StackStorm through an integration pack.

Where can I get help with napalm?

The Contact section points at a Slack channel named napalm on the network.toCode() team, reached through a Heroku-hosted URL for that team. The FAQ also refers to submitting questions by email before trying Slack, though that address is not in the contact section.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. napalm-automation/napalm on GitHub
  4. README
  5. Releases
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/napalm-automation-napalm.svg)](https://hysenlabs.com/projects/napalm-automation-napalm)