A typed, Pythonic client and CLI for the TrueNAS middleware API
Project description
pytruenas
A typed, Pythonic client and CLI for the TrueNAS middleware API.
pytruenas speaks the middleware's JSON-RPC 2.0 websocket protocol directly —
over wss:///ws:// to a remote host, or over the local unix socket
(ws+unix://) when running on the NAS itself. It exposes the whole API surface
through an attribute-style namespace, adds convenience helpers for the common
create/update/upsert patterns, a remote-filesystem abstraction, an optional
typings generator, and a small CLI for scripting host configuration.
Running commands and reading files is delegated to
hostctl: a client is a hostctl host, so
run() and path() pick whichever transport a target actually offers rather
than assuming one.
Install
pip install pytruenas
Optional extras:
| Extra | Enables |
|---|---|
pytruenas[ssh] |
SSH commands + the SFTP filesystem leg (asyncssh) |
pytruenas[config] |
YAML config/targets file for the CLI (pyyaml) |
pytruenas[codegen] |
generate-typings command (jinja2) |
Quickstart
from pytruenas import TrueNASClient
# Remote host (api key, or "user:password", or a token)
client = TrueNASClient("nas.example.com", "1-<64-char-api-key>", sslverify=False)
# Attribute-style access to any API namespace/method:
for user in client.api.user.query():
print(user["username"])
# Convenience helpers for common DB patterns:
client.api.user._upsert("username", username="svc", full_name="Service", group_create=True)
# Running on the NAS itself talks to the local unix socket, no auth:
local = TrueNASClient() # ws+unix:///var/run/middleware/middlewared.sock
print(local.api.system.info())
Commands and files
run() and path() are inherited from hostctl, which selects a transport
rather than assuming one:
client = TrueNASClient("nas.example.com", api_key, shell="ssh://root@nas.example.com")
client.run("zpool status", capture_output="stdout", encoding="utf-8").stdout
client.path("/mnt/tank/notes.txt").read_text()
client.capabilities # {"run", "path"} -- what this target can actually do
client.last_selection # which transport served the last run(), and why
| target | commands | files |
|---|---|---|
| on the NAS | local (plain subprocess) |
local |
| remote, SSH configured | ssh, then webshell |
sftp, then tnasws |
| remote, no SSH | webshell |
tnasws |
webshell runs commands over /websocket/shell — the same PTY the web UI's
Shell page uses — so a host reachable on the API port but not on 22 (NAT, a
firewall allowing only 443) can still run commands. Name providers explicitly
with executor= / path= to force or exclude one.
Credentials
TrueNASClient(target, credentials) accepts, for the second argument:
- an API key string
"<id>-<64 chars>", "user:password"(optionally"user:password\n<otp>"),- a token string,
- a
(user, password)tuple, None/ omitted → local socket auth.
Credentials.from_env() reads TN_CREDS. Credentials may also travel in the
target (wss://root:secret@nas); an OTP follows the password after a newline,
percent-encoded in a URI as %0A.
CLI
pytruenas --help
pytruenas query user -f username=root nas.example.com
pytruenas call system.info nas.example.com # any method by dotted name
pytruenas dump-api nas.example.com > api.json
pytruenas generate-typings --path typings --api-version v26.0.0 nas.example.com
The target host(s) are the trailing positional arguments — a command's own
positionals (like query's namespace) come first, then the hosts. Each target
may be comma-separated and supports [A-Z]/[0-9] range expansion (e.g.
'nas[1-3].example.com'); with no target the command runs against localhost.
--parallel N runs several targets concurrently. Filter query with
-f/--filter KEY=VALUE (repeatable).
Typings generator
generate-typings turns a host's API definition into a package of .pyi stubs
so editors and type checkers understand client.api.<namespace>.<method>(...).
It is validated against the full real API (every version in a live dump).
pytruenas generate-typings --path truenasapi_typings/current nas.example.com
Development
py -3.14 -m venv .venv/3.14-nt-amd64
.venv/3.14-nt-amd64/Scripts/python -m pip install -e ".[dev,ssh,config,codegen]"
.venv/3.14-nt-amd64/Scripts/python -m pytest
Supports Python 3.9+. The run() tests need a POSIX shell and skip on Windows,
so verify anything touching command or path dispatch on a real target.
License
MIT — see LICENSE.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pytruenas-0.2.2.tar.gz.
File metadata
- Download URL: pytruenas-0.2.2.tar.gz
- Upload date:
- Size: 158.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a7404b1ef28bb0464654ac2d1948fc5cd0180aae6b2c4dfe747354d7535ac378
|
|
| MD5 |
4d07f9708bc7e7493993f0b5ff15ced6
|
|
| BLAKE2b-256 |
0c9b5edfafbdfcb01d1e5a1ee358fc94c36153f5c5d4e80b41c15d30f5037c85
|
Provenance
The following attestation bundles were made for pytruenas-0.2.2.tar.gz:
Publisher:
release.yml on jose-pr/pytruenas
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pytruenas-0.2.2.tar.gz -
Subject digest:
a7404b1ef28bb0464654ac2d1948fc5cd0180aae6b2c4dfe747354d7535ac378 - Sigstore transparency entry: 2278587105
- Sigstore integration time:
-
Permalink:
jose-pr/pytruenas@5cb0efd3fc0c7bdc9e135d1cc3eb268fef40f3be -
Branch / Tag:
refs/tags/v0.2.2 - Owner: https://github.com/jose-pr
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@5cb0efd3fc0c7bdc9e135d1cc3eb268fef40f3be -
Trigger Event:
push
-
Statement type:
File details
Details for the file pytruenas-0.2.2-py3-none-any.whl.
File metadata
- Download URL: pytruenas-0.2.2-py3-none-any.whl
- Upload date:
- Size: 105.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
989c9ebe8c0c1ad74e27eaa0eeced9a70a7f632d23452f650949e8ab982d7a42
|
|
| MD5 |
5390e2978ba688cd562ae7227f65d9a9
|
|
| BLAKE2b-256 |
cbb5c09e93f71087378ac8dd570c683cc71c901cc0c5aae973b70f97da34ebc8
|
Provenance
The following attestation bundles were made for pytruenas-0.2.2-py3-none-any.whl:
Publisher:
release.yml on jose-pr/pytruenas
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pytruenas-0.2.2-py3-none-any.whl -
Subject digest:
989c9ebe8c0c1ad74e27eaa0eeced9a70a7f632d23452f650949e8ab982d7a42 - Sigstore transparency entry: 2278587201
- Sigstore integration time:
-
Permalink:
jose-pr/pytruenas@5cb0efd3fc0c7bdc9e135d1cc3eb268fef40f3be -
Branch / Tag:
refs/tags/v0.2.2 - Owner: https://github.com/jose-pr
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@5cb0efd3fc0c7bdc9e135d1cc3eb268fef40f3be -
Trigger Event:
push
-
Statement type: