The Synapse genpkg tool can be used to generate a Storm Package containing new Storm commands and Storm modules from a YAML definition and optionally push it to a Cortex or PkgRepo.


genpkg is executed from an operating system command shell. The command usage is as follows:

usage: [-h] [--push <url>] [--save <path>] [--optic <path>] <pkgfile>


  • pkgfile is the path to the Storm Package YAML file.

  • --save takes a file name to save the completed package JSON as.

  • --push takes an optional Telepath URL to a Cortex or PkgRepo for the package to be pushed to.

  • --optic takes an optional path to a directory containing Optic module files.

Package Layout

The expected filesystem layout for a Storm package is:

├── commands/
│   └── foocmd
├── modules/
│   └── foomod
└── optic/
    └── index.html

Commands and modules defined in the package YAML file are expected to have corresponding files containing the Storm code for their implementation. It is not required to have both commands and modules in a Storm package; you may have a package with only commands, or only modules.

Package YAML

A Storm package YAML may contain the following definitions:

  • name: Name of the Storm package.

  • version: Version of the Storm package. A Cortex may contain multiple versions of the same package.

  • synapse_minversion: Optional minimum required Synapse version a Cortex must be running to load the package.

  • onload: Optional Storm code to run in a Cortex when the package is loaded.

  • modules: Storm module definitions.

  • commands: Storm command definitions.

The example below shows the YAML included in the foopkg.yml file.


name: foopkg
version: 1.0.0
synapse_minversion: [2, 23, 0]

onload: $lib.import(foomod).onload()

  - name: foomod
      srcguid: f751f9ad20e75547be230ae1a425fb9f

  - name: foocmd
    descr: |
      One line description on the first line.
      Followed by a more detailed description talking about what the command does and any
      useful additional information.

        # A couple examples of the command
        inet:ipv4 | foocmd
        inet:ipv4 | limit 1 | foocmd --yield
    asroot: true
      - - --debug
        - default: false
          action: store_true
          help: Show verbose debug output.

      - - --yield
        - default: false
          action: store_true
          help: Yield the newly created nodes.

      - - --timeout
        - default: 0
          type: int
          help: Specify a timeout in seconds.
      srcguid: f751f9ad20e75547be230ae1a425fb9f
        - inet:ipv4
        - inet:ipv4
        - [ foodata, file:bytes ]


Modules can be used to expose reusable Storm functions. Each module defines a name, which is used for importing elsewhere via $lib.import(), and optionally a modconf dictionary containing additional configuration values which will be accessible in the module’s Storm via $modconf.

The example below shows the Storm code included in the foomod file.


function onload() {
    [ meta:source=$modconf.srcguid
    fini { return($lib.null) }

function bar(x, y) {
    return ($($x + $y))


Multiple Storm commands can be added to a Storm service package, with each defining the following attributes:

  • name: Name of the Storm command to expose in the Cortex.

  • descr: Description of the command which will be available in help displays.

  • asroot: Whether the command should be run with root permissions. This allows users to be granted access to run the command without requiring them to have all the permissions needed by the Storm command. An example asroot permission for foocmd would be ('storm', 'asroot', 'cmd', 'asroot', 'foocmd').

  • cmdargs: An optional list of arguments for the command.

  • cmdconf: An optional dictionary of additional configuration variables to provide to the command Storm execution.

  • forms: List of input and output forms for the command, as well as a list of nodedata keys and the corresponding form on which they may be set by the service.

The example below shows the Storm code included in the foocmd file.


$foo = $lib.import(foomod)

[:asn = $, $(20))]

$, $

Building the Example Package

To build the package and push it directly to a Cortex:

python -m --push tcp://user:[email protected]:27492 foopkg.yml


Users must have the pkg.add permission to add a package to a Cortex.

Once the package has been successfully pushed to the Cortex, the additional Storm Commands will be listed in the output of storm help under the package they were loaded from:

package: foopkg
foocmd                      : One line description on the first line.

The new commands may now be used like any other Storm command:

cli> storm inet:ipv4= | foocmd
Executing query at 2022/12/05 20:24:28.458
        .created = 2022/12/05 20:24:28.451
        :asn = 40
        :type = private
complete. 1 nodes in 25 ms (40/sec).

If immediately pushing the package to a Cortex is not desired, it can instead be built and saved to foo.json to load later:

python -m --save foo.json foopkg.yml