Skip to content

Managing Apps

Once a bundle is installed, NimbleBrain tracks its lifecycle from startup through crashes and recovery. You can start, stop, and inspect bundles through the CLI, API, or web UI.

Every installed bundle is in one of five states:

starting ──→ running ──→ crashed ──→ dead
│ │
└──→ stopped ←────────┘
└──→ starting (explicit restart)
StateMeaning
startingMCP server process is being spawned
runningProcess is alive and responding to tool calls
crashedProcess exited unexpectedly. The health monitor will attempt automatic restart.
deadRestart attempts exhausted. Must be explicitly restarted.
stoppedManually stopped by you. Will not auto-restart.
Terminal window
nb bundle list
Configured bundles:
@nimblebraininc/ipinfo (named)
@nimblebraininc/granola (named)
../mcp-servers/hello (local)

For JSON output:

Terminal window
nb bundle list --json
[{"name":"@nimblebraininc/ipinfo"},{"name":"@nimblebraininc/granola"},{"path":"../mcp-servers/hello"}]

The nb status command shows live health data when the server is running:

Terminal window
nb status
Bundles: 3 configured
@nimblebraininc/ipinfo
@nimblebraininc/granola
@nimblebraininc/postgres
Skills: 2 loaded
Bundle health:
ipinfo: running (uptime: 7200s, restarts: 0)
granola: running (uptime: 7200s, restarts: 0)
postgres: crashed (uptime: n/a, restarts: 3)

The health endpoint is also available unauthenticated:

Terminal window
curl http://localhost:27247/v1/bundles/health
[
{"name": "ipinfo", "state": "running", "uptime": 7200000, "restartCount": 0},
{"name": "granola", "state": "running", "uptime": 7200000, "restartCount": 0},
{"name": "postgres", "state": "crashed", "uptime": null, "restartCount": 3}
]

Stop a running bundle:

Terminal window
curl -X POST http://localhost:27247/v1/apps/granola/stop

Start a stopped or dead bundle:

Terminal window
curl -X POST http://localhost:27247/v1/apps/granola/start
Terminal window
nb bundle remove @nimblebraininc/granola
Removed "@nimblebraininc/granola" from config. Run nb reload to apply.

Uninstalling a bundle:

  1. Checks the protected flag — rejects if protected
  2. Stops the MCP server process
  3. Removes the source from the tool registry
  4. Removes the entry from nimblebrain.json atomically
  5. Clears the bundle’s credential file for this workspace (best-effort; a failure logs a warning but doesn’t block the uninstall)
  6. Emits a bundle.uninstalled event

Bundle data (Upjack entity state, bundle-owned files under {workDir}/workspaces/{wsId}/data/{bundle}) is preserved. Only credentials are cleared. Credentials in other workspaces are untouched.

Mark a bundle as protected in nimblebrain.json to prevent removal via nb__manage_app or the API:

{
"bundles": [
{
"name": "@nimblebraininc/ipinfo",
"protected": true
}
]
}

Attempting to uninstall a protected bundle produces an error:

Cannot uninstall "ipinfo": bundle is protected

When a bundle is installed from mpak, NimbleBrain records its MTF (mpak Trust Framework) trust score. The score is a number from 0 to 100, stored in the config and available in the GET /v1/apps response.

Trust scores are fetched via mpak info <name> --json at install time and stored in the bundle’s config entry:

{
"name": "@nimblebraininc/granola",
"trustScore": 85
}

Local and remote bundles do not have trust scores (they report null).

See Credentials for setting API keys and secrets. Short version: export the env var the bundle declares, or run nb config set <bundle> <key>=<value> -w <wsId>.

After changing nimblebrain.json (adding, removing, or modifying bundle entries), signal the running server to reload:

Terminal window
nb reload
Reload signal sent. Running runtime will pick up changes.

This writes a timestamp to ~/.nimblebrain/.reload. The running runtime watches for this sentinel and reloads bundles and skills without restarting the process.