CLI tool
fabric/fabric avatar
fabric/fabric

Fabric: the Python library for driving remote hosts over SSH

Simple, Pythonic remote execution and deployment.

15,510 stars1,953 forksPythonBSD-2-Clause

At a glance

What is it?
Fabric sits on top of Invoke and Paramiko and turns remote shell execution into a Python API. It is a small, mature library with a release history the README barely advertises and one genuinely interesting migration mechanism.
Who is it for?
Fabric is a good choice when you need repeatable remote execution from Python rather than a shell script, and a poor choice when you want a full deployment tool with inventories and roles, which is what Ansible is for. The specific first step is to install it and call one function before building anything around it, because the library's value is that `run`, `local` and `put` return Python objects rather than requiring you to parse output.
Can I use it commercially?
Yes. BSD-2-Clause 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 180 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 7, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A thin layer over Invoke and Paramiko

The README describes Fabric as a high level Python library designed to execute shell commands remotely over SSH, yielding useful Python objects in return. That last clause is the whole design. The traditional alternative is a shell script, where output is text you have to scrape, failures are exit codes you have to check, and anything structured has to be assembled from `grep` and `sed`.

Fabric's position in the stack is deliberately narrow and the README says exactly what it sits on. It builds on Invoke, which handles subprocess command execution and command-line features, and on Paramiko, which implements the SSH protocol. Both are named and linked. Fabric extends their APIs so they complement each other and add functionality on top.

That architecture has two consequences worth naming. First, the SSH behaviour is Paramiko's, including its known-good key handling, and the local execution behaviour is Invoke's, which is why Fabric users also tend to use Invoke for local tasks. Second, the library is a library and not a framework: there is no configuration file format, no plugin discovery convention, and no daemon. You import what you need.

The metadata records the language as Python, the default branch as main, and the homepage as fabfile.org. The README's own description of a library supporting Python 2.7 and 3.4 and later dates from an era when that was a meaningful claim; the Python 2 support line is historical rather than current, and the authoritative statement of supported versions is the PyPI classifiers, which the README links through its badge row.

The 1.x to 2.x migration shim, explained in setup.py comments

The most interesting file in this repository is not the README. It is `setup.py`, and the reason is a block of comments at the top that explains a piece of packaging tomfoolery in unusual detail.

The goal is to let Fabric 2.x also install under the name `fabric2`, so that someone migrating from 1.x can have both versions in the same process and migrate piecemeal rather than in one step. The setup script decides the package name from two inputs: an environment variable `PACKAGE_AS_FABRIC2`, and a check of whether the `fabric2/` directory exists while `fabric/` does not.

The comments then walk through why this is harder than it sounds, and the reasoning is worth reading because it explains a class of Python packaging problem most users hit without naming it. There is a `fabric2/` symlink to `fabric/` in the repository, so that code looking for `fabric2/<whatever>` finds it whether the lookup happens inside the project or deeper inside setuptools or wheel. Wheels do not execute that step on installation, only on generation, so maintainers build wheels with the environment variable turned on and those wheels install as `fabric2` without trouble. Source distributions are the harder case: they execute this logic both when the package is created and when a user installs it, and without the environment variable set on the user's machine the script would look in `fabric/` when it meant `fabric2/` and fail.

The resolution is a second check that inspects the local filesystem directly and overrides the environment variable test. The script closes by setting `binary_name` to `fab` or `fab2` accordingly. If you have ever wondered how a Python package supports two import names simultaneously, this is the shape of the answer: a symlink, an environment variable, and a fallback.

Reading the repository to understand the project's habits

There are no GitHub releases in this repository, which is worth stating plainly rather than filling the gap with guesses. The README points at the changelog on fabfile.org for what changed in a version, which tells you the release history lives on the documentation site rather than in release tags.

The tree shows a project with conventional Python tooling and a couple of choices worth noticing. There are two coverage configuration files, `.coveragerc` and `codecov.yml`, alongside a `.codecov.yml` at the root, plus a badge pointing at the CircleCI build for the main branch. `.flake8` is present, as is `dev-requirements.txt` for test dependencies, which keeps them out of the install requirements. `tasks.py` is the Invoke task file, meaning the project's own development commands are written in Invoke rather than in a Makefile or a shell script.

Two directories show how seriously the project takes its own behaviour. `tests/` is the unit test suite, and `integration/` is a separate suite for testing against real systems, which for an SSH library is the only way to know whether it works. `SECURITY.md` at the root means the project has a disclosure process.

`sites/` is unusual. It is the directory holding the fabfile.org site source, which is why the comments in setup.py point at `sites/www/installing.txt` for installation guidance. The documentation is versioned in the same repository as the code, which is why the homepage is a real docs site rather than a link to a wiki that can drift.

The repository also carries a `fabric2` entry at the top level, which is the symlink described above, and an `integration/` suite separate from `tests/`. The last push was on 2026-04-10.

Where Fabric stops and Ansible starts

The honest limitation is about ambition rather than correctness. Fabric is a library: it gives you `run`-style remote execution as Python objects, and it does not stop there, but it does not attempt the surrounding apparatus either.

Ansible adds inventories that describe your hosts, roles that describe what should be on them, playbooks that describe the ordering of tasks, idempotence so re-running a playbook is safe, and a large module library for configuring specific software. Fabric has none of that. If your problem is executing a command on six servers from a script, Fabric is smaller and clearer. If your problem is converging a fleet of servers to a known state, Ansible's model is the one built for it.

The second limitation is Python version support in practice. The README's own claim of 2.7 and 3.4 or later spans an era that has closed. Paramiko and Invoke both continue to move, and a library that extends their APIs inherits their compatibility boundaries as much as its own. If you are starting new work, check the current PyPI metadata for the classifiers that actually declare supported versions rather than relying on a README line written years ago.

The third is the nature of SSH libraries in general. Paramiko gives Fabric a solid, pure-Python implementation of SSH, which is a genuine advantage over shelling out to the `ssh` binary, and it is also a dependency with its own release history and its own behaviour around key formats and algorithm negotiation. Nothing here is Fabric's fault, but it is the surface where problems tend to surface.

For a comparison of the design philosophies, Invoke alone is the closer peer: both are Python libraries where the unit of work is a function call, and both treat the shell as something you program rather than a file you write. Fabric is what you reach for when the shell is on another machine.

Where the project is going, according to the maintainer

Two links in a short README carry the forward-looking information. The first is the changelog on fabfile.org, which is where version changes are described. The second is more interesting: the README says the project maintainer keeps a roadmap on his website, at a personal projects page.

That tells you something real about this project. It is maintained by one person, the roadmap lives on a personal site rather than in a governance document, and the documentation site is versioned alongside the code. For a library at this level of adoption that is a perfectly good arrangement, and for a team that needs a documented support commitment it is a weaker one.

The practical implication for anyone adopting Fabric is that you should read the changelog before pinning a version, because the semantic version number is the only signal the package gives you and the release history is not visible as tags. That is a real gap in the packaging rather than a criticism of the library, and it is one of the reasons a version pin in your own requirements is worth having.

The description field for the repository puts it plainly as simple, Pythonic remote execution and deployment. The word deployment is doing some work there. Fabric can deploy, in the sense that you can write Python that copies files and runs commands on a remote host, and plenty of people use it that way. It does not provide the state tracking or idempotence that makes a deployment safe to re-run, and that distinction is the line between Fabric and the tools built to replace shell scripts.

Editorial conclusion

Fabric is a good choice when you need repeatable remote execution from Python rather than a shell script, and a poor choice when you want a full deployment tool with inventories and roles, which is what Ansible is for. The specific first step is to install it and call one function before building anything around it, because the library's value is that `run`, `local` and `put` return Python objects rather than requiring you to parse output. The `fabric2` compatibility shim matters only if you are migrating from 1.x, and the maintainer's roadmap on his own site is where the future of the project is actually described.

Frequently asked questions

What is the Python Fabric library used for?

It executes shell commands remotely over SSH and returns useful Python objects instead of text to scrape. It builds on Invoke for subprocess execution and Paramiko for the SSH protocol, extending both APIs. You call it from Python, which makes it a library for building deployment scripts rather than a tool you configure.

How do Fabric and Ansible differ?

Fabric is a library for remote command execution as Python objects, with no inventories, roles, playbooks or idempotence model. Ansible is a configuration management tool built around all of those, so it is the one that converges a fleet of hosts to a declared state. Fabric is smaller and clearer when you need to run a command on a handful of hosts.

Can I install Fabric 2 alongside Fabric 1 during a migration?

That is exactly what the packaging supports. setup.py can build the package under the name fabric2, with the fab2 binary, so both versions can exist in one process while you migrate piececemeal. It relies on a fabric2 symlink to fabric/ in the repository plus a PACKAGE_AS_FABRIC2 environment variable, and the source distribution case is handled by a separate filesystem check.

Does Fabric have GitHub releases I can check for changes?

There are no GitHub releases in this repository. The README points to the changelog on fabfile.org for what changed in each version, which is where the release history is published. It also links a roadmap on the maintainer's own website, so version pinning in your own requirements is worth doing rather than tracking tags.

Official sources

  1. fabric/fabric on GitHub
  2. Issues
  3. License: BSD-2-Clause
  4. Project website
  5. README
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/fabric-fabric.svg)](https://hysenlabs.com/projects/fabric-fabric)