CLI tool for bootstrapping and managing P4N4 projects
Project description
p4n4-cli
Command-line tool for bootstrapping and managing P4N4 projects — Platform for Nexus Neural Network Nodes.
p4n4 scaffolds, configures, and orchestrates the P4N4 stack: the MING IoT services, Edge Impulse inference, and the Gen AI layer. It wraps docker compose with project-aware defaults and a guided setup flow.
Part of the p4n4 platform — an EdgeAI + GenAI integration platform for IoT deployments.
Table of Contents
- Overview
- Repository Map
- Prerequisites
- Installation
- Local Development
- Quick Start
- Project Structure
- Commands
- Layers
- Configuration Reference
- Default Ports
- Source Repos
- Resources
- License
Overview
P4N4 is a unified developer platform for IoT and Edge AI. It combines the MING stack (Mosquitto, InfluxDB, Node-RED, Grafana), Edge Impulse on-device ML inference, and a Gen AI layer (n8n, Letta, Ollama) into a single composable system.
p4n4-cli manages the full lifecycle — init, run, inspect, and tear down — from your terminal. Stack files are always fetched from the canonical source repos at init time, so projects are never pinned to a snapshot bundled inside the CLI.
Repository Map
| Repository | Description |
|---|---|
| p4n4 | Umbrella repo — architecture, ADRs, cross-cutting docs |
| p4n4-iot | IoT stack: Mosquitto · InfluxDB · Node-RED · Grafana |
| p4n4-ai | GenAI stack: Ollama · Letta · n8n |
| p4n4-edge | Edge Impulse inference stack |
| p4n4-api | Rust REST API gateway (port 8000) |
| p4n4-lib | Shared Rust library (pip install p4n4lib for Python bindings) |
| p4n4-cli | This repo — Python CLI (pip install p4n4) |
| p4n4-templates | Community template registry |
| p4n4-docs | Full technical documentation site |
Prerequisites
- Python 3.11+
- Git (required by
p4n4 initto clone stack repos) - Docker v24+ (with Compose v2)
- pipx (recommended for isolated installation)
- At least 4 GB RAM available to Docker (8 GB recommended when running Ollama)
Install pipx if you don't have it:
# macOS
brew install pipx && pipx ensurepath
# Linux / WSL
python3 -m pip install --user pipx && python3 -m pipx ensurepath
Installation
pipx install p4n4
Or with plain pip:
pip install p4n4
Verify:
p4n4 --version
Upgrade / uninstall:
pipx upgrade p4n4
pipx uninstall p4n4
Local Development
# 1. Clone the repo
git clone https://github.com/raisga/p4n4-cli.git
cd p4n4-cli
# 2. Create the virtual environment
uv venv
source .venv/bin/activate
# 3. Install in editable mode with dev extras
uv pip install -e ".[dev]"
# 4. Verify
p4n4 --help
# 5. Run tests
pytest tests/ -v
# 6. Lint
ruff check .
Quick Start
# Scaffold a new IoT project (fetches latest files from p4n4-iot)
p4n4 init my-project
cd my-project
# Validate the generated config
p4n4 validate
# Start the MING stack
p4n4 up
# Check service health
p4n4 status
# Tail logs from a specific service
p4n4 logs grafana
# Stop the stack
p4n4 down
Scaffold a GenAI project instead:
p4n4 init my-ai-project --layer ai
cd my-ai-project
p4n4 up
Scaffold with all layers:
p4n4 init my-full-project --layer all
cd my-full-project
p4n4 up
p4n4 up --ai
No internet access? Point --source-iot / --source-ai at local checkouts:
p4n4 init my-project --source-iot ../p4n4-iot
p4n4 init my-ai-project --layer ai --source-ai ../p4n4-ai
Once the IoT stack is up:
| Service | URL |
|---|---|
| Grafana | http://localhost:3000 |
| Node-RED | http://localhost:1880 |
| InfluxDB | http://localhost:8086 |
Once the AI stack is up:
| Service | URL |
|---|---|
| n8n | http://localhost:5678 |
| Letta | http://localhost:8283 |
| Ollama | http://localhost:11434 |
Project Structure
After p4n4 init, the project directory contains files sourced from the relevant stack repo(s). Stack files are never modified by the CLI after scaffolding.
IoT layer (--layer iot, the default):
my-project/
├── .p4n4.json # Manifest (project name, active layers, schema version)
├── .env # Credentials and config (auto-generated secrets)
├── docker-compose.yml # Stack orchestration (sourced from p4n4-iot)
├── config/
│ ├── mosquitto/
│ │ ├── mosquitto.conf # MQTT broker config
│ │ ├── passwd.example # Auth template for production hardening
│ │ └── acl.example # ACL template
│ ├── node-red/
│ │ ├── settings.js # Node-RED runtime settings
│ │ └── flows.json # MQTT → InfluxDB pipeline
│ └── grafana/
│ └── provisioning/
│ ├── datasources/
│ │ └── datasources.yml # Pre-configured InfluxDB datasources (5 buckets)
│ └── dashboards/
│ ├── dashboards.yml
│ └── json/
│ └── iot-overview.json
└── scripts/
├── init-buckets.sh # Creates additional InfluxDB buckets on first run
├── init-sandbox.sh
└── selector.sh
AI layer (--layer ai):
my-ai-project/
├── .p4n4.json # Manifest
├── .env # Credentials and config (auto-generated secrets)
├── docker-compose.yml # Stack orchestration (sourced from p4n4-ai)
├── config/
│ ├── letta/
│ │ └── letta.conf # Letta agent server config
│ ├── n8n/
│ │ └── workflows/ # Pre-built n8n workflow definitions
│ │ ├── alert-enrichment.json
│ │ ├── device-onboarding.json
│ │ ├── incident-escalation.json
│ │ └── scheduled-digest.json
│ └── ollama/ # Ollama model storage (populated at runtime)
└── scripts/
├── pull-models.sh # Pull default Ollama models
└── selector.sh
Commands
p4n4 init
Scaffold a new P4N4 project. Clones the canonical stack repo(s) at init time so the project always starts from the latest source.
p4n4 init <project-name> [options]
| Flag | Description | Default |
|---|---|---|
--layer <name> |
Layers to enable: iot, ai, edge, all, or comma-separated |
iot |
--no-interactive |
Skip the wizard and use generated defaults | — |
--source-iot <path> |
Local p4n4-iot checkout (skips git clone; useful offline) | — |
--source-ai <path> |
Local p4n4-ai checkout (skips git clone; useful offline) | — |
The interactive wizard prompts for InfluxDB org, timezone, and admin passwords. When the ai layer is active it also prompts for Letta, n8n, and n8n encryption key values. All secrets default to randomly generated values if left blank.
# IoT stack, interactive wizard (default)
p4n4 init sensor-network
# GenAI stack, non-interactive
p4n4 init my-ai-project --layer ai --no-interactive
# All layers enabled
p4n4 init my-full-project --layer all
# From local checkouts (no network required)
p4n4 init sensor-network --source-iot ../p4n4-iot --no-interactive
p4n4 init my-ai-project --layer ai --source-ai ../p4n4-ai --no-interactive
p4n4 up
Start the project stack (docker compose up -d).
p4n4 up [options]
| Flag | Description |
|---|---|
--ai |
Start Gen AI services only |
--edge |
Start Edge AI services only |
--build |
Rebuild images before starting |
--pull |
Pull the latest images before starting |
p4n4 up
p4n4 up --pull
p4n4 up --ai
p4n4 up --edge
p4n4 down
Stop all running services.
p4n4 down [options]
| Flag | Description |
|---|---|
--volumes |
Also remove persistent data volumes (destructive — prompts for confirmation) |
p4n4 down
# Full teardown — deletes all stored data
p4n4 down --volumes
p4n4 status
Print a service status table.
p4n4 status
Stack status — my-project
┏━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Service ┃ Status ┃ Health ┃ Ports ┃
┡━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━┩
│ mqtt │ running │ healthy │ 1883→1883/tcp │
│ influxdb │ running │ healthy │ 8086→8086/tcp │
│ node-red │ running │ healthy │ 1880→1880/tcp │
│ grafana │ running │ healthy │ 3000→3000/tcp │
└───────────┴─────────┴─────────┴───────────────────────┘
p4n4 logs
Stream logs from all services or a specific one.
p4n4 logs [service] [options]
| Flag | Description | Default |
|---|---|---|
--tail <n> |
Lines from end of existing logs | 100 |
--no-follow |
Print once and exit | — |
p4n4 logs
p4n4 logs node-red
p4n4 logs influxdb --tail 50 --no-follow
p4n4 secret
Rotate secrets in .env with new randomly generated values. Prompts for confirmation before writing. Rotates whichever of the following keys are present:
- IoT layer:
INFLUXDB_PASSWORD,INFLUXDB_TOKEN,GRAFANA_PASSWORD - AI layer:
LETTA_SERVER_PASSWORD,N8N_BASIC_AUTH_PASSWORD,N8N_ENCRYPTION_KEY
p4n4 secret
Run p4n4 down && p4n4 up after rotating secrets to apply them.
p4n4 validate
Check that .p4n4.json, .env, and all required config files are present and valid for the active layers.
p4n4 validate
p4n4 add
Add a layer or service to an existing project.
p4n4 add <component>
Not yet implemented.
p4n4 remove
Remove a layer or service from an existing project.
p4n4 remove <component>
Not yet implemented.
p4n4 upgrade
Pull the latest Docker images for all active services.
p4n4 upgrade
Not yet implemented.
p4n4 ei
Manage Edge Impulse model deployment and inference.
p4n4 ei deploy
p4n4 ei run
| Subcommand | Description |
|---|---|
deploy |
Deploy a trained Edge Impulse model to the edge device |
run |
Run inference and publish results over MQTT |
Not yet implemented.
p4n4 template
Browse and apply community project templates.
p4n4 template search [query]
p4n4 template apply <name>
Not yet implemented.
Layers
P4N4 is organized into three composable layers.
IoT — MING Stack
| Service | Role |
|---|---|
| Mosquitto | MQTT broker — central message bus |
| InfluxDB | Time-series database (5 pre-configured buckets) |
| Node-RED | Flow engine for MQTT routing and pipeline logic |
| Grafana | Real-time dashboarding and alerting |
Edge
| Service | Role |
|---|---|
| Edge Impulse | On-device ML inference; publishes results over MQTT |
Gen AI
| Service | Role |
|---|---|
| n8n | Workflow automation bridging IoT and AI layers |
| Letta | Stateful AI agent framework with long-term memory |
| Ollama | Local LLM runtime for open-weight models |
All three stacks communicate over a shared p4n4-net Docker bridge network owned by p4n4-iot. The CLI handles network creation and stack ordering automatically.
Configuration Reference
.env is generated by p4n4 init with random secrets. Use p4n4 secret to rotate credentials at any time.
IoT layer:
TZ=UTC
# InfluxDB
INFLUXDB_USERNAME=admin
INFLUXDB_PASSWORD=<generated>
INFLUXDB_ORG=ming
INFLUXDB_TOKEN=<generated>
INFLUXDB_BUCKET=raw_telemetry
INFLUXDB_BUCKET_PROCESSED=processed_metrics
INFLUXDB_BUCKET_AI_EVENTS=ai_events
INFLUXDB_BUCKET_HEALTH=system_health
INFLUXDB_SANDBOX_BUCKET=sandbox
INFLUXDB_SANDBOX_RETENTION=30d
# Grafana
GRAFANA_USER=admin
GRAFANA_PASSWORD=<generated>
AI layer:
# Letta
LETTA_SERVER_PASSWORD=<generated>
# n8n
N8N_BASIC_AUTH_USER=admin
N8N_BASIC_AUTH_PASSWORD=<generated>
N8N_ENCRYPTION_KEY=<generated> # 32+ characters
N8N_HOST=localhost
# Shared InfluxDB (must match p4n4-iot values when used alongside it)
INFLUXDB_TOKEN=<generated>
INFLUXDB_ORG=ming
INFLUXDB_BUCKET=raw_telemetry
Default Ports
| Service | Port | Stack |
|---|---|---|
| MQTT (Mosquitto) | 1883 (MQTT), 9001 (WebSocket) |
iot |
| InfluxDB | 8086 |
iot |
| Node-RED | 1880 |
iot |
| Grafana | 3000 |
iot |
| n8n | 5678 |
ai |
| Letta | 8283 |
ai |
| Ollama | 11434 |
ai |
| Edge Impulse Runner | 8080 (health endpoint) |
edge |
| p4n4 REST API | 8000 |
api |
Source Repos
Stack files are fetched from these repos at p4n4 init time. URLs are defined in p4n4/sources.yaml and can be overridden per-layer via --source-iot / --source-ai, or by editing the file to point at a fork or mirror.
| Layer | Repo |
|---|---|
| IoT | https://github.com/raisga/p4n4-iot |
| AI | https://github.com/raisga/p4n4-ai |
| Edge | https://github.com/raisga/p4n4-edge |
| Templates | https://github.com/raisga/p4n4-templates |
Resources
- p4n4.com — Platform overview
- Full documentation — MkDocs reference site
- p4n4-iot — MING stack source
- p4n4-ai — GenAI stack source
- p4n4-edge — Edge AI stack source
- p4n4-templates — Community template registry
- MING Stack Tutorial — IIoT data stack tutorial (XIV SBESC, 2024)
- MING Stack with Edge Impulse — Integration guide
- Edge Impulse Linux SDK (Python)
- Eclipse Mosquitto · InfluxDB · Node-RED · Grafana
- Ollama · Letta · n8n
License
This project is licensed under the MIT License.
Project details
Release history Release notifications | RSS feed
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 p4n4-0.1.1.tar.gz.
File metadata
- Download URL: p4n4-0.1.1.tar.gz
- Upload date:
- Size: 17.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4d62164e5434ae7919ad7001fc06392bb6db460a23316142ad1f2acd391fbc56
|
|
| MD5 |
7a15b886325c600b81107456b8a4ae89
|
|
| BLAKE2b-256 |
0a398b6d6eea9158dba1945bc3d8c9a8408a076c290252d4fb546d75c30b078b
|
Provenance
The following attestation bundles were made for p4n4-0.1.1.tar.gz:
Publisher:
publish.yml on raisga/p4n4-cli
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
p4n4-0.1.1.tar.gz -
Subject digest:
4d62164e5434ae7919ad7001fc06392bb6db460a23316142ad1f2acd391fbc56 - Sigstore transparency entry: 1540106119
- Sigstore integration time:
-
Permalink:
raisga/p4n4-cli@a622d76df9ece6f1adaff1eb88ff875637a9a69a -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/raisga
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@a622d76df9ece6f1adaff1eb88ff875637a9a69a -
Trigger Event:
release
-
Statement type:
File details
Details for the file p4n4-0.1.1-py3-none-any.whl.
File metadata
- Download URL: p4n4-0.1.1-py3-none-any.whl
- Upload date:
- Size: 21.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
585cdf1350a0aed2353decf48fe733758b8ed000567ed330012fe7d85137cfa5
|
|
| MD5 |
0afbd15826126db3d4a5f49e5db5a536
|
|
| BLAKE2b-256 |
ac1d1a8941689d9d01e4b2b6e2b5c2d36b42714c1e633b6233f9eb63d9721aea
|
Provenance
The following attestation bundles were made for p4n4-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on raisga/p4n4-cli
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
p4n4-0.1.1-py3-none-any.whl -
Subject digest:
585cdf1350a0aed2353decf48fe733758b8ed000567ed330012fe7d85137cfa5 - Sigstore transparency entry: 1540106234
- Sigstore integration time:
-
Permalink:
raisga/p4n4-cli@a622d76df9ece6f1adaff1eb88ff875637a9a69a -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/raisga
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@a622d76df9ece6f1adaff1eb88ff875637a9a69a -
Trigger Event:
release
-
Statement type: