Skip to main content

salpa-cli

The Salpa node authoring CLI. Scaffolds node packages that match the shipped template contract — the deterministic path to a new node — checks them against that contract, and puts them into the Salpa app on your machine.

python3 -m pip install salpa-cli
salpa new my-analyzer          # interactive
salpa new my-suite -t multi-node-package --yes
salpa validate my_suite        # will it install and register?
salpa push my_suite            # into your running Salpa app
salpa unpush my_suite          # and back out again

Installing adds the salpa command. If your shell can't find salpa afterward, your Python scripts directory isn't on your PATH — installing into a virtual environment is the simplest fix (it puts salpa on PATH).

Requirements

Python 3.9 or newer. pip install salpa-cli reports a clear error below that.

  • macOS — the system python3 is 3.9, which is enough. For a newer one: brew install python, or python.org.
  • Linux — most distributions ship 3.9+. Otherwise use your package manager (apt install python3, dnf install python3, …) or pyenv.
  • Windows — often has no python3 at all; install from python.org or the Microsoft Store, and tick "Add python.exe to PATH".

pixi — needed only for pixi install / pixi run test (building a node's environment and running its tests). You do not have to install it separately if you run Salpa: the app keeps a pixi under ~/.bocoflow, and salpa new finds it and prints its path. To have one on your own PATH, install it from pixi.sh. Stdlib-only nodes need no pixi at all.

salpa new creates ./<under_scored_name>/ from a bundled template, with every placeholder substituted and the directory underscored (the dir name becomes the Python package name, so a hyphen would break from .core import ...; meta.toml's name stays kebab-case).

Templates

Templates ship inside the wheel and are the single source of truth for the node contract, so there is no second copy to drift.

Template For
individual-node one node with its own pixi env (default)
multi-node-package several related nodes sharing one pixi env, chained via predecessor_data

Options

salpa new [NAME]
  -t, --template     individual-node | multi-node-package
  -d, --description  one-line description
      --author       author name
      --category     UI category (e.g. "Cheminformatics")
  -o, --output       directory to create the package in (default: .)
  -y, --yes          non-interactive: accept defaults, no prompts
      --install      run `pixi install` in the new package afterwards

Validating

salpa validate [PATH] checks a package against the contract the app enforces at install and registration time. Every check maps to a real failure — a node missing from [package.nodes], a shared-environment name that drifted between three files, a stray per-node pixi.toml that silently opts a node out of the shared env. It is not a linter: style is not checked.

salpa validate [PATH]           # default: the current directory
      --strict                  # warnings become errors (CI)
      --ignore CODE             # suppress one check by code, repeatable
      --json                    # machine-readable report
      --no-import               # skip the import checks
      --python PATH             # override the auto-detected import-check interpreter

Exit codes: 0 clean · 1 at least one error · 2 the path is not a package.

Findings are ERROR (will not install or will not register) or WARN (installs, but is probably not what you meant). Each carries a stable code (E3, S2, …) so it can be quoted, grepped, and suppressed.

Import checks. I1-I3 import your node.py in a subprocess to confirm the app can read its OPTIONS. They need the authoring SDK (bocoflow_core), and the interpreter that has it is found for you — your package already declares the SDK in its own pixi.toml, so its solved test environment is the right one to judge the package against:

pixi install -e test    # solve the test env — the one your pixi.toml puts the SDK in
salpa validate          # the import checks now run, no flags

The search order, first hit wins: .pixi/envs/test.pixi/envs/default → the interpreter running salpa. A candidate that cannot import bocoflow_core is passed over, and the report names the one that answered. pip install bocoflow-core-sdk beside salpa works too, and --python PATH overrides the search entirely (a --python that lacks the SDK skips rather than falling back — naming an interpreter is an instruction, not a hint).

With no interpreter at all, the checks are skipped, and both the status line and the summary say so — No findings (import checks skipped) is a smaller claim than No findings. This package should install and register., and reads as one.

Suppressing a check. Some warnings describe a shape that is occasionally correct — E3 (a per-node pixi.toml) is a deliberate opt-out when a node's dependencies conflict with its package's shared environment. --ignore lets such a package pass --strict without silencing everything:

salpa validate --strict --ignore E3

Suppressed findings are still reported (and appear under suppressed in --json) — they are hidden from the exit code, not from you.

salpa new runs a validation pass over its own output and prints a one-line summary. That pass covers structure, naming and environment only; the import checks are left to salpa validate.

Pushing it into Salpa

salpa push [PATH] makes a package appear in your running Salpa app's Marketplace ▸ Browse, ready to install.

It is not publishing. It targets the app on your machine; nothing is uploaded anywhere, and there is no public hub involved.

salpa push [PATH]
      --copy           copy into the app instead of linking your directory
      --source-id      id for this source in the app
      --source-name    display name for this source
      --port           port the app is listening on (default 18000, or $SALPA_PORT)
      --force          push despite `salpa validate` errors; with --copy, also
                       replace a package copy that this push did not create
  -y, --yes            accept the layout change without asking

Exit codes: 0 ok · 1 refused or failed · 2 the path is not a package.

push validates, arranges your package into the layout a package source uses (registry.json + packages/<pkg>/, asking before it moves anything), generates the catalog file, and asks the app to sync it and put the package on the shelf.

The install itself stays in the app. push stops at the shelf — installing is user-consented in the UI, and runs the same installer every other package goes through. There is no second installer in this CLI, and no assumption anywhere about where the app keeps its files: the app is asked, over the API its own UI uses. Salpa must therefore be running; if it isn't, push says so and stops.

By default your directory is the source — nothing is copied, so re-running after an edit refreshes what the app offers:

salpa push packages/my_suite      # edit, push, repeat

--copy copies the package into the app instead. Self-contained and survives moving your working copy, at the cost of needing another --copy push per edit. It lands in the directory the app keeps its own packages in, so it will replace an earlier copy of yours but refuses to overwrite anything else — your [package].name decides the directory name, and a collision there is someone else's package.

Taking it back out

salpa unpush [PATH] is the reverse: it removes the package from the app's shelf and deregisters the source, so the app stops offering it.

salpa unpush [PATH]
      --source-id      id of the source to remove (default: whichever the push created)
      --port           port the app is listening on (default 18000, or $SALPA_PORT)
      --force          remove it even though the package is installed
  -y, --yes            remove without asking

Exit codes: 0 ok (including nothing to remove) · 1 refused or failed · 2 the path is not a package.

Your own directory is never touched — the packages/ layout and registry.json that push wrote stay put, and salpa push registers them again whenever you want the package back. You do not have to remember whether you used --copy: unpush reads which mode was used off what is actually in the app, and cleans up the copy in the app's catalog when there is one.

Unpushing something that was never pushed reports Nothing to remove and exits 0, so it is safe to run twice.

unpush refuses while the package is installed, and points you at Marketplace ▸ Installed to uninstall it first — removing the source out from under an installed copy would leave it pointing at a source that no longer exists. --force removes it anyway. As with push stopping at the shelf, unpush never uninstalls anything itself; that stays in the app.

Full walkthrough: salpa docs publishing-to-your-app.

Authoring guide

salpa docs prints the bundled node-authoring guide. Full documentation: https://salpa.app/docs/custom-nodes

Reserved

salpa publish / install / run are reserved for later and not implemented yet. The current surface is salpa new, salpa validate, salpa push, salpa unpush and salpa docs.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

salpa_cli-0.3.3-py3-none-any.whl (98.4 kB view details)

Uploaded Python 3

File details

Details for the file salpa_cli-0.3.3-py3-none-any.whl.

File metadata

  • Download URL: salpa_cli-0.3.3-py3-none-any.whl
  • Upload date:
  • Size: 98.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for salpa_cli-0.3.3-py3-none-any.whl
Algorithm Hash digest
SHA256 c37cfabb098aa57b8915a1dd86cf2d926756c94c07fd7577e283fdd8fc8c28d8
MD5 e351bfb0863cdade9399578ff73cf1f4
BLAKE2b-256 197a34998d763d485fc0e75e781695caf54fee90033b3ec67991993ce81f80c2

See more details on using hashes here.

Release history Release notifications | RSS feed

0.13.0

1 file

0.12.4

1 file

0.12.3

1 file

0.12.2

2 files

0.11.0

1 file

0.10.0

1 file

0.9.0

1 file

0.8.0

1 file

0.7.0

1 file

0.6.3

1 file

0.6.2

1 file

0.5.0

1 file

0.4.1

1 file

0.3.5

1 file

0.3.4

1 file

This release

0.3.3 This release

1 file

0.3.1

1 file

0.2.1

1 file

0.2.0

1 file

0.1.4

1 file

0.1.3

1 file

0.1.2

1 file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page