Spec-driven network API CLI for operators, with first-class ClearPass support
Project description
_ _ _ _
| \ | | ___| |_| | ___ ___ _ __ ___
| \| |/ _ \ __| |/ _ \ / _ \| '_ ` _ \
| |\ | __/ |_| | (_) | (_) | | | | | |
|_| \_|\___|\__|_|\___/ \___/|_| |_| |_|
Weave your network APIs into one CLI.
About
netloom is a spec-driven network API CLI for operators and automation engineers.
It discovers available API actions from vendor documentation, turns them into a
consistent command surface, and keeps the workflow centered around operational
tasks like listing objects, replaying payloads, refreshing API caches, and
copying configuration between environments.
[!NOTE] The runtime is organized so shared CLI logic lives in
netloom/and vendor-specific behavior lives undernetloom/plugins/<plugin>/. ClearPass is currently the only bundled plugin. The CLI and repo layout are already modular, so adding more plugins does not require changing the shared command surface. More vendor support is planned for the future.
Version: 1.8.3
Detailed changelog documented in CHANGELOG.md.
Highlights
- shared modular runtime under
netloom/ - plugin-specific code under
netloom/plugins/<plugin>/ - built-in
load,server,cache, andcopyworkflows - profile-aware configuration through
~/.config/netloom/plugins/<plugin>/ - dynamic API discovery from live vendor documentation
- structured JSON, CSV, and raw output
- shell completion and context-aware help
Planned features
The roadmap is focused on improving the core CLI first, then expanding automation workflows, and finally adding broader user-experience features.
ClearPass privilege-aware cache filtering and the default visible/full catalog
split are now in place through v1.8.3. The next step is to keep expanding
mapping coverage and tighten action-level visibility where that can be verified
safely.
Phase 1: Access-aware discovery and comparison
- add a
netloom <module> <service> diff --from=X --to=Yaction to compare config between<profiles>within a<service> - continue refining the visible catalog so action-level exposure matches the active API client as closely as verified mappings allow
- keep the explicit opt-in full catalog view for troubleshooting, vendor doc comparison, and mapping validation
- continue expanding the verified ClearPass privilege mapping table as Aruba adds or changes endpoints and privilege keys
Phase 2: Safe multi-service workflows
- implement
netloom <module> copy --from=X --to=Yto copy all config from all<services>within a<module> - add structured copy and diff plans with stable JSON output for automation and review
- add validation and dry-run helpers to verify whether objects and payloads are safe to apply before changes are made
Phase 3: Change tracking and UX expansion
- add version control support for exported configs, plans, and environment comparisons
- add a GUI on top of the stabilized CLI workflows
Installation
Standard install:
pip install netloom-tool
Install directly from GitHub:
pip install git+https://github.com/mathias-granlund/netloom
Install the bundled man pages:
netloom-install-manpage
man netloom
man netloom-clearpass
First run
[!NOTE] Load a plugin and build the API cache before expecting context-aware help, completion, or live module/service discovery to work well. This creates the active plugin marker at ~/.config/netloom/config.env
netloom load clearpass
netloom cache update
netloom server use dev
netloom identities endpoint list --limit=10
Configuration
[!TIP] Example templates are included as defaults.env.example, profiles.env.example, and credentials.env.example. Copy them into the plugin directory ~/.config/netloom/plugins/<plugin>/
The runtime separates global plugin selection from plugin-specific profile settings:
~/.config/netloom/config.env
~/.config/netloom/plugins/<plugin>/defaults.env
~/.config/netloom/plugins/<plugin>/profiles/<profile>.env
~/.config/netloom/plugins/<plugin>/credentials/<profile>.env
config.env usually only needs the active plugin and is normally managed with:
netloom load clearpass
defaults.env holds the active profile and any plugin-wide fallback values:
NETLOOM_ACTIVE_PROFILE="prod"
NETLOOM_VERIFY_SSL="true"
NETLOOM_TIMEOUT="30"
Required per-profile connection settings in profiles/<profile>.env:
NETLOOM_SERVER="clearpass.example.com:443"
Required per-profile credentials in credentials/<profile>.env:
NETLOOM_CLIENT_ID="your-client-id"
NETLOOM_CLIENT_SECRET="your-client-secret"
[!IMPORTANT] Direct
NETLOOM_*environment variables still override profile files when they are set in the current shell session.
CLI syntax
netloom load [list | show | <plugin>]
netloom server [list | show | use <profile>]
netloom cache [clear | update]
netloom <module> <service> <action> [options] [flags]
netloom <module> <service> copy --from=SOURCE --to=TARGET [options] [flags]
netloom [--help | ?]
netloom --version
Examples:
netloom load clearpass
netloom server use dev
netloom cache update
netloom identities endpoint list --limit=10
netloom identities endpoint list --filter=name:equals:TEST
netloom policyelements network-device get --id=1337 --console
netloom policyelements network-device update --id=1337 --description="Core switch"
netloom policyelements network-device copy --from=dev --to=prod --filter='{"description":{"$contains":"Core switch"}}' --dry-run
Command-line token overrides are supported:
netloom identities endpoint list --api-token=your-token
netloom identities endpoint list --token-file=./token.json
[!CAUTION]
--api-token,--token-file, and especially--decrypttogether with--consolecan expose sensitive data in shell history or terminal output.
When --filter= is used, both shorthand and full JSON syntax are available:
Simple shorthand for common filters:
--filter=name:equals:TEST
--filter=name:contains:guest
--filter=id:in:1,2,3
--filter=enabled:exists:true
Supported shorthand operators:
equalsnot-equalscontainsinnot-ingtgteltlteexists
Use full JSON for advanced cases such as $and, $or, $not, regex, or
nested expressions.
[!IMPORTANT] JSON filter expressions are passed as strings, so shell quoting matters.
Key is equal to 'value' '{"key":{"$eq":"value"}}'
Key is one of a list of values '{"key":{"$in":["value1", "value2"]}}'
Key is not one of a list of values '{"key":{"$nin":["value1", "value2"]}}'
Key contains a substring 'value' '{"key":{"$contains":"value"}}'
key is not equal to 'value' '{"key":{"$ne":"value"}}'
Key is greater than 'value' '{"key":{"$gt":"value"}}'
Key is greater than or equal to 'value' '{"key":{"$gte":"value"}}'
Key is less than 'value' '{"key":{"$lt":"value"}}'
Key is less than or equal to 'value' '{"key":{"$lte":"value"}}'
Key matches a regex (case-sensitive) '{"key":{"$regex":"regex"}}'
Key exists (not null value) '{"key":{"$exists":true}}'
Key is absent / does not exist '{"key":{"$exists":false}}'
Combining filter expressions with AND '{"$and":[filter1, filter2,...]}'
Combining filter expressions with OR '{"$or":[filter1, filter2,...]}'
Inverting a filter expression '{"$not":{filter}}'
Global options
| Option | Description |
|---|---|
--log-level=LEVEL |
Set logging level |
--console |
Print API response to terminal |
--limit=N |
Page size for list/get --all requests |
--offset=N |
Pagination offset |
--sort=+-field |
Sort results |
--filter=JSON|FIELD:OP:VALUE |
Server-side filter applied across all fetched pages |
--calculate-count=true/false |
Request total count |
--csv-fieldnames=a,b,c |
Fields and order for CSV output |
--file=FILE |
Bulk import JSON/CSV |
--out=FILE |
Override output file |
--api-token=TOKEN |
Use an existing bearer token instead of logging in |
--token-file=FILE |
Load a bearer token from JSON or plain text |
--help |
Context-aware help |
--version |
Show version |
--encrypt=enable/disable |
Mask or show secret fields |
--decrypt |
Shortcut for showing secrets |
Discovery and cache
The active plugin discovers modules and services at runtime. The current ClearPass plugin uses live vendor docs such as:
/api-docs/api/apigility/documentation/<Module-v1>
The generated cache stores actions as:
module -> service -> action -> {method, paths, params, response metadata, body hints}
For ClearPass, netloom cache update also checks /api/oauth/privileges,
stores the full discovered catalog, and builds a stricter default visible view
from verified privilege mappings so help, completion, and normal command
discovery better match what the active API client can actually use.
By default, the CLI uses the visible catalog view. When you need to troubleshoot or compare against the raw vendor docs, use the full retained catalog view:
netloom --catalog-view=full ?
netloom --catalog-view=full <module> <service> <action> --help
Refresh the cache:
netloom cache clear
netloom cache update
Default paths
On Linux and macOS the defaults are:
cache: ~/.cache/netloom/
state: ~/.local/state/netloom/
responses: ~/.local/state/netloom/responses/
app logs: ~/.local/state/netloom/logs/
config: ~/.config/netloom/config.env
plugins: ~/.config/netloom/plugins/<plugin>/
These can be overridden with:
NETLOOM_CACHE_DIRNETLOOM_STATE_DIRNETLOOM_OUT_DIRNETLOOM_APP_LOG_DIRNETLOOM_CONFIG_DIR
Bash completion
[!TIP] Completion quality depends on the local API cache. If module or service names look incomplete, run
netloom cache updatefirst.
Run once per session:
source /path/to/netloom/scripts/netloom-completion.bash
Permanent completion setup:
mkdir -p ~/.bash_completion.d
cp /path/to/netloom/scripts/netloom-completion.bash ~/.bash_completion.d
cat >> ~/.bashrc <<'EOF'
if [ -d "$HOME/.bash_completion.d" ]; then
for f in "$HOME"/.bash_completion.d/*; do
[ -r "$f" ] && source "$f"
done
fi
EOF
Architecture
The repository layout is now centered on a shared netloom/ runtime and
plugin-specific folders under netloom/plugins/.
.
|-- CHANGELOG.md
|-- README.md
|-- RELEASING.md
|-- RELEASE_NOTES.md
|-- pyproject.toml
|-- defaults.env.example
|-- profiles.env.example
|-- credentials.env.example
|-- examples/
|-- man/
| |-- netloom.1
| `-- netloom-clearpass.7
|-- scripts/
| `-- netloom-completion.bash
|-- tests/
`-- netloom/
|-- __init__.py
|-- __main__.py
|-- install_manpage.py
|-- cli/
| |-- commands.py
| |-- completion.py
| |-- copy.py
| |-- help.py
| |-- load.py
| |-- main.py
| |-- parser.py
| `-- server.py
|-- core/
| |-- config.py
| |-- help.py
| |-- pagination.py
| |-- plugin.py
| `-- resolver.py
|-- io/
| |-- files.py
| `-- output.py
|-- logging/
| `-- setup.py
|-- data/
| `-- man/
| |-- netloom.1
| `-- netloom-clearpass.7
`-- plugins/
`-- clearpass/
|-- catalog.py
|-- client.py
|-- copy_hooks.py
|-- help.py
`-- plugin.py
Development
Development install:
pip install -e .[dev]
Run tests:
pytest -q
Run lint and formatting:
ruff check .
ruff format .
Build release artifacts locally:
python -m build
python -m twine check dist/*
Release guidance is documented in RELEASING.md.
License
Proprietary / Internal Use
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 netloom_tool-1.8.3.tar.gz.
File metadata
- Download URL: netloom_tool-1.8.3.tar.gz
- Upload date:
- Size: 96.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2ba87712bd98a326cfc4c3d1df2f407ccf5d08505785f7df4dc8d97ef733e652
|
|
| MD5 |
e993643f6ede488d8567e79f49f68bed
|
|
| BLAKE2b-256 |
6796383ba43f4fc9ef97b203d102724379a41a63491c20d625ae5746dea74355
|
Provenance
The following attestation bundles were made for netloom_tool-1.8.3.tar.gz:
Publisher:
package.yml on mathias-granlund/netloom
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
netloom_tool-1.8.3.tar.gz -
Subject digest:
2ba87712bd98a326cfc4c3d1df2f407ccf5d08505785f7df4dc8d97ef733e652 - Sigstore transparency entry: 1146153813
- Sigstore integration time:
-
Permalink:
mathias-granlund/netloom@deb6c82c5b6a4424c49aeea97b145b31f51d7e83 -
Branch / Tag:
refs/tags/v1.8.3 - Owner: https://github.com/mathias-granlund
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
package.yml@deb6c82c5b6a4424c49aeea97b145b31f51d7e83 -
Trigger Event:
push
-
Statement type:
File details
Details for the file netloom_tool-1.8.3-py3-none-any.whl.
File metadata
- Download URL: netloom_tool-1.8.3-py3-none-any.whl
- Upload date:
- Size: 69.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
37621ad00c984f158f077b0219b17b5f8364761eb8a0434e5256b052dd9dbaa3
|
|
| MD5 |
bd7f3c5e949f70ae47360bc1ba9fb3bb
|
|
| BLAKE2b-256 |
1ddb83b17365337a6eebff64ce0ac1d63836471469f7862478bb7893eea4f9ad
|
Provenance
The following attestation bundles were made for netloom_tool-1.8.3-py3-none-any.whl:
Publisher:
package.yml on mathias-granlund/netloom
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
netloom_tool-1.8.3-py3-none-any.whl -
Subject digest:
37621ad00c984f158f077b0219b17b5f8364761eb8a0434e5256b052dd9dbaa3 - Sigstore transparency entry: 1146153845
- Sigstore integration time:
-
Permalink:
mathias-granlund/netloom@deb6c82c5b6a4424c49aeea97b145b31f51d7e83 -
Branch / Tag:
refs/tags/v1.8.3 - Owner: https://github.com/mathias-granlund
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
package.yml@deb6c82c5b6a4424c49aeea97b145b31f51d7e83 -
Trigger Event:
push
-
Statement type: