Manage Solutions with CLI
Once your project is initialized, you can build IoT solutions with Claude, manage multi-target deployments, and work with entities directly from the terminal. This page covers the full solution lifecycle — from first prompt to production push.
Haven’t set up the CLI yet? Start with Getting Started with CLI.
Building Solutions with Claude
Section titled “Building Solutions with Claude”The AI-first workflow is short: ask Claude for a solution, review what it built, run tb push <slug> when Claude tells you it’s ready.
-
You ask. Describe the solution you want. Claude designs the full IoT solution for you — devices and their hierarchy, dashboards, alarms, calculated metrics, and customers and users. It also generates demo telemetry emulators so your dashboards have data from day one, and validates the design against ThingsBoard throughout the process.
-
You review. By default, Claude pauses for your approval after each design step — first the entity model, then the dashboards. You can also tell Claude to run autonomously and just show you the final result.
-
You deploy. When Claude says the solution is ready, run
tb push <slug>. Add--run-tasksto also generate demo telemetry and backfill calculated fields with historical inputs:Terminal window tb push smart-building --run-tasks -
You iterate. Ask Claude for changes — “add a humidity sensor to each room”, “split the kitchen dashboard”. Claude regenerates the affected pieces, and you re-run
tb push. Push is idempotent: ThingsBoard tracks entity identity by external ID, so the same solution can be pushed many times with no duplication.
How to Phrase Your Request
Section titled “How to Phrase Your Request”Claude does its best work when you mention these things up front. It will ask if you don’t, but doing so means fewer follow-up questions:
- Domain & entities — what’s being monitored or controlled. Sensors, vehicles, machines, meters, infrastructure.
- Hierarchy — are these standalone devices, or are they grouped inside container assets (a building, a fleet, a site)?
- Customers & users — single tenant, or multiple independent customers / sites that should see only their own data?
- Alarms & metrics — specific thresholds or derived values you care about. Optional; Claude proposes sensible defaults if you don’t specify.
Example prompts:
- “Create a smart house monitoring solution with a few temperature, humidity, and motion sensors per room.”
- “Build a fleet tracking system for two delivery customers, with location and battery alarms.”
What Claude Has Access To
Section titled “What Claude Has Access To”/create-solution is the umbrella command; behind the scenes Claude uses purpose-built skills for entity generation, dashboards, alarms, calculated fields, and emulators. These ship with the CLI and update automatically with it.
Solutions & Multi-Target Deployment
Section titled “Solutions & Multi-Target Deployment”ThingsBoard CLI treats your tenant configuration as code: entity definitions live in your project on disk, and tb push deploys them to ThingsBoard. The same solution can be pushed to multiple ThingsBoard targets — dev, staging, prod — without code changes.
Each entity directory under the project root holds entities that aren’t part of any solution. Solutions are self-contained slices under solutions/<slug>/ with the same directory layout.
To start a new solution by hand (without Claude):
tb solution new smart-buildingWhen a solution is on disk, you can target it from anywhere in the project with the --solution flag:
tb device save --solution smart-building --json '{"name": "Sensor-01", "type": "Temperature Sensor"}'Pulling an Existing Solution
Section titled “Pulling an Existing Solution”If you already have a solution deployed in ThingsBoard and want to bring it under CLI management, use the interactive pull to select exactly which entities to import into your project.
tb pull -iThe CLI opens a terminal UI that lets you browse your ThingsBoard tenant across all entity types, including entity groups. Select the entities you want and press Enter to import them.
- Press
spaceto toggle selection on an individual entity. - Press
mon an entity group to automatically select all entities in that group. - Press
ato select all entities in the current view.
Use owner:<name> or server:<query> in the search bar to filter by owner or run a server-side query.
Once pulled, the entities land in your project files and are tracked by the CLI — any subsequent tb push will keep them in sync with ThingsBoard.
Multi-Target Push: dev → staging → prod
Section titled “Multi-Target Push: dev → staging → prod”The same solution can be deployed to multiple ThingsBoard environments by pushing it under different config profiles:
tb push smart-building --profile devtb push smart-building --profile stagingtb push smart-building --profile prodThe CLI writes no state files to your project — push to the same target twice and existing entities are updated, not duplicated. Develop and test against dev, promote to staging once you’re happy, and ship to prod with the exact same files.
Validating without Pushing
Section titled “Validating without Pushing”tb validate # validate root entitiestb validate smart-building # validate one solutionValidation is a dry-run against the target ThingsBoard instance. Combine it with --profile <name> to validate against any environment.
What --run-tasks Does
Section titled “What --run-tasks Does”tb push --run-tasks does the regular push and then runs two extra steps:
- Telemetry emulators. The CLI writes synthetic telemetry for the devices Claude set up emulators for, so dashboards have something to display.
- Calculated field backfill. The CLI replays historical inputs through each calculated field expression so derived values are populated for the time range covered by the emulators.
Both steps are safe to omit on subsequent pushes once the data exists — they are most useful on the very first push to a fresh tenant.
Pulling Changes Back from ThingsBoard
Section titled “Pulling Changes Back from ThingsBoard”tb pull is the inverse of push: it fetches the current server state for entities you already track locally and rewrites the JSON files on disk. Reach for it when someone tweaked a dashboard in the UI, when you want a fresh local copy of what’s running on staging, or when you need to bring a server-created entity into the project.
tb pull # refresh every locally-tracked entity in the current solution (auto-detected from cwd)tb pull --solution smart-building # same, with the solution named explicitlytb pull dashboard --all # refresh every dashboard in the current solutiontb pull device <uuid> # fetch a single entity by its server-internal UUIDtb pull device <uuid1> <uuid2> # …or several at onceThe UUID form is the way to pick up entities that exist on the server but aren’t in the project yet — pass the entity’s internal ID and the CLI writes a fresh file under the right directory.
A few flags worth knowing about:
--dry-runprints the planned writes (created / updated / renamed) without touching disk. Use it to preview changes before they land.--with-credentialsincludes device credentials in the pulled files. Off by default; opt in only when you want them committed alongside the device JSON.--forceskips the safety check that aborts when target files have uncommitted git changes.
By default, tb pull refuses to overwrite files with uncommitted local changes, so it never silently clobbers work in progress. Commit, stash, or pass --force to proceed.
Limitations
Section titled “Limitations”tb pushhas no automatic rollback. If you push a broken solution, fix it locally and push again.- Entity identity is tracked server-side by external ID. UI edits to project-managed entities are overwritten on the next
tb pushunless youtb pullthem back first. Brand-new entities created outside the CLI can also be brought into the project withtb pull.
Troubleshooting
Section titled “Troubleshooting”“No entities to push”
The solution or project root has no entity files yet. Generate some with Claude or create them manually with tb device save (or another entity command), then push again.
“Commands target the wrong solution”
Don’t cd into solution directories to scope commands. Always use --solution <name> — the flag works from anywhere inside your project and is more reliable than relying on the current directory.