Skip to main content
Version: v5

Applications

The contents of this page primarily relate to application components. The term "components" in the Operations API and CLI generally refers to applications specifically. See the Components Overview for a full explanation of terminology.

Harper offers several approaches to managing applications that differ between local development and remote Harper instances.

Local Development

dev and run Commands

Added in: v4.2.0

The quickest way to run an application locally is with the dev command inside the application directory:

harper dev .

The dev command watches for file changes and restarts Harper worker threads automatically.

The run command is similar but does not watch for changes. Use run when the main thread needs to be restarted (the dev command does not restart the main thread).

Stop either process with SIGINT (Ctrl+C).

Deploying to a Local Harper Instance

To mimic interaction with a hosted Harper instance locally:

  1. Start Harper: harper

  2. Deploy the application:

    harper deploy \
    project=<name> \
    package=<path-to-project> \
    restart=true
    • Omit target to deploy to the locally running instance.
    • Setting package=<path-to-project> creates a symlink so file changes are picked up automatically between restarts.
    • restart=true restarts worker threads after deploy. Use restart=rolling for a rolling restart.
  3. Use harper restart in another terminal to restart threads at any time.

  4. Remove an application: harper drop_component project=<name>

Not all component operations are available via CLI. When in doubt, use the Operations API via direct HTTP requests to the local Harper instance.

Example:

harper deploy \
project=test-application \
package=/Users/dev/test-application \
restart=true

Use package=$(pwd) if your current directory is the application directory.

Remote Management

Managing applications on a remote Harper instance uses the same operations as local management. The recommended approach is to log in first using harper login to store an authentication token:

# Log in once
harper login <remote>
# Provide your username and password when prompted

# Subsequently deploy without credentials
harper deploy \
project=<name> \
package=<package> \
target=<remote> \
restart=true \
replicated=true

Alternatively, credentials can be provided via environment variables (recommended for CI/CD):

export HARPER_CLI_USERNAME=<username>
export HARPER_CLI_PASSWORD=<password>
harper deploy \
project=<name> \
package=<package> \
target=<remote> \
restart=true \
replicated=true

Or directly via command parameters (not recommended for production):

harper deploy \
project=<name> \
package=<package> \
username=<username> \
password=<password> \
target=<remote> \
restart=true \
replicated=true

Package Sources

When deploying remotely, the package field can be any valid npm dependency value:

  • Omit package to package and deploy the current local directory
  • npm package: package="@harperdb/status-check"
  • GitHub: package="HarperDB/status-check" or package="https://github.com/HarperDB/status-check"
  • Private repo (SSH): package="git+ssh://git@github.com:HarperDB/secret-app.git"
  • Tarball: package="https://example.com/application.tar.gz"

When using git tags, use the semver directive for reliable versioning:

HarperDB/application-template#semver:v1.0.0

Harper generates a package.json from component configurations and uses a form of npm install to resolve them. This is why specifying a local file path creates a symlink (changes are picked up between restarts without redeploying).

For SSH-based private repos, use the Add SSH Key operation to register keys first.

Deploying by Reference

Available since: v5.2.0

Omitting package uploads a snapshot of your working directory. The result is an anonymous artifact: nothing records which commit it came from, so reproducing it later — or stepping back to a previous release — means finding those exact files again.

Deploying by reference sends a pinned git reference instead, and the cluster fetches that exact commit. Redeploying the same reference is an exact redeploy, and rolling back is deploying an older one.

harper deploy by_ref=true builds that reference from the local git repository, so you don't assemble the URL yourself:

harper deploy by_ref=true restart=true replicated=true

This resolves the repository's origin remote and the current commit, then deploys package=git+https://github.com/<owner>/<repo>.git#<full commit SHA>.

Parameters:

  • by_ref - Build the package reference from the local repository.
  • ref (optional) - Deploy a specific commit, tag, or branch instead of HEAD. Implies by_ref.
  • credential (optional) - Git host whose stored credential authenticates the clone, e.g. github.com. Omit for public repositories.
# Deploy a specific tag
harper deploy ref=v1.2.0 restart=true replicated=true

# Roll back by deploying an older commit
harper deploy ref=9f8c2a1 restart=true replicated=true

A reference is pinned to a SHA, not to the name you typed. Tags and branches are resolved locally and the full commit SHA is what ships. This matters on a cluster: peers resolve the package independently, so a tag that moves mid-deploy — or a branch that advances — could otherwise leave nodes running different code.

Commit and push first. The cluster clones from the remote, so it only sees commits that have been pushed. by_ref warns when the working tree is dirty, since uncommitted changes won't be part of the deploy.

Private repositories

Pass credential=<host> for a private repository. The CLI attaches a credentials reference naming a secret that the cluster resolves in memory at clone time, so no token travels in the operation body or lands on disk:

harper deploy by_ref=true credential=github.com restart=true replicated=true

Provision that credential once with harper deploy setup=true. See Private-source deploy credentials for how the secret is named and resolved, and add_ssh_key for the SSH-key alternative.

note

Deploying by reference means the cluster installs and builds the component from source. If your application needs a build step that can't run on the node, keep shipping the built output as a payload deploy instead.

Provisioning a Deploy Credential

Available since: v5.2.0

harper deploy setup=true provisions the credential a private deploy needs. It's interactive, and runs once per component and source:

harper deploy setup=true

It asks which private source needs a credential (a GitHub repository or an npm registry) and sources a token — from your gh CLI session, or one you paste — then:

  1. Fetches the cluster's public key with get_secrets_public_key.
  2. Encrypts the token locally into an enc:v1: envelope.
  3. Stores only the ciphertext via set_secret, granted to the component.
  4. Prints the credentials reference for the deploy to use.

The plaintext never leaves your machine: the operations API, its logs, and replication only ever carry the envelope, and the cluster decrypts it in memory at deploy time. This requires a cluster with secrets custody (Harper Pro / Fabric) — see Client-side encryption.

Because the stored token is durable, later deploys — including re-fetching an older reference — reuse it without re-entering anything.

note

Rolling back to the immediately previous version needs no credential at all: revert_component swaps in the retained previous build without re-fetching from the source.

Dependency Management

Harper uses npm and package.json for dependency management.

During application loading, Harper follows this resolution order to determine how to install dependencies:

  1. If node_modules exists, or if package.json is absent — skip installation
  2. Check the application's harper-config.yaml for install: { command, timeout } fields
  3. Derive the package manager from package.json#devEngines#packageManager
  4. Default to npm install

The add_component and deploy_component operations support install_command and install_timeout fields for customizing this behavior.

Example harper-config.yaml with Custom Install

myApp:
package: ./my-app
install:
command: yarn install
timeout: 600000 # 10 minutes
allowInstallScripts: true

Example package.json with devEngines

{
"name": "my-app",
"version": "1.0.0",
"devEngines": {
"packageManager": {
"name": "pnpm",
"onFail": "error"
}
}
}

If you plan to use an alternative package manager, ensure it is installed on the host machine. Harper does not support the "onFail": "download" option and falls back to "onFail": "error" behavior.

Advanced: Direct harper-config.yaml Configuration

Applications can be added to Harper by adding them directly to harper-config.yaml (located in the Harper rootPath, typically ~/hdb).

status-check:
package: '@harperdb/status-check'

The entry name does not need to match a package.json dependency. Harper transforms these entries into a package.json and runs npm install.

Any valid npm dependency specifier works:

myGithubComponent:
package: HarperDB-Add-Ons/package#v2.2.0
myNPMComponent:
package: harper
myTarBall:
package: /Users/harper/cool-component.tar
myLocal:
package: /Users/harper/local
myWebsite:
package: https://harperdb-component

Harper generates a package.json and installs all components into <componentsRoot> (default: ~/hdb/components). A symlink back to <rootPath>/node_modules is created for dependency resolution.

Use harper get_configuration to find the rootPath and componentsRoot values on your instance.

Operations API

Component operations are restricted to super_user roles.

add_component

Creates a new component project in the component root directory using a template.

  • project (required) — Name of the project to create
  • template (optional) — Git URL of a template repository. Defaults to https://github.com/HarperFast/application-template
  • install_command (optional) — Install command. Defaults to npm install
  • install_timeout (optional) — Install timeout in milliseconds. Defaults to 300000 (5 minutes)
  • install_allow_scripts (optional) — Allow install scripts to run. Defaults to false, which causes --ignore-scripts to be passed to the install command (this is ignored with install_command).
  • replicated (optional) — Replicate to all cluster nodes
{
"operation": "add_component",
"project": "my-component"
}

deploy_component

Deploys a component using a package reference or a base64-encoded .tar payload.

  • project (required) — Name of the project
  • package (optional) — Any valid npm reference (GitHub, npm, tarball, local path, URL)
  • payload (optional) — Base64-encoded .tar file content
  • force (optional) — Allow deploying over protected core components. Defaults to false
  • restart (optional)true for immediate restart, 'rolling' for sequential cluster restart
  • replicated (optional) — Replicate to all cluster nodes
  • install_command (optional) — Install command override
  • install_timeout (optional) — Install timeout override in milliseconds
  • install_allow_scripts (optional) — Allow install scripts to run. Defaults to false, which causes --ignore-scripts to be passed to the install command (this is ignored with install_command).
{
"operation": "deploy_component",
"project": "my-component",
"package": "HarperDB/application-template#semver:v1.0.0",
"replicated": true,
"restart": "rolling"
}

drop_component

Deletes a component project or a specific file within it.

  • project (required) — Project name
  • file (optional) — Path relative to project folder. If omitted, deletes the entire project
  • replicated (optional) — Replicate deletion to all cluster nodes
  • restart (optional) — Restart Harper after dropping
{
"operation": "drop_component",
"project": "my-component"
}

package_component

Packages a project folder as a base64-encoded .tar string.

  • project (required) — Project name
  • skip_node_modules (optional) — Exclude node_modules from the package
{
"operation": "package_component",
"project": "my-component",
"skip_node_modules": true
}

get_components

Returns all local component files, folders, and configuration from harper-config.yaml.

{
"operation": "get_components"
}

get_component_file

Returns the contents of a file within a component project.

  • project (required) — Project name
  • file (required) — Path relative to project folder
  • encoding (optional) — File encoding. Defaults to utf8
{
"operation": "get_component_file",
"project": "my-component",
"file": "resources.js"
}

set_component_file

Creates or updates a file within a component project.

  • project (required) — Project name
  • file (required) — Path relative to project folder
  • payload (required) — File content to write
  • encoding (optional) — File encoding. Defaults to utf8
  • replicated (optional) — Replicate update to all cluster nodes
{
"operation": "set_component_file",
"project": "my-component",
"file": "test.js",
"payload": "console.log('hello world')"
}

SSH Key Management

For deploying from private repositories, SSH keys must be registered on the Harper instance.

add_ssh_key

  • name (required) — Key name
  • key (required) — Private key contents (must be ed25519; use \n for line breaks with trailing \n)
  • host (required) — Host alias for SSH config (used in package URL)
  • hostname (required) — Actual domain (e.g., github.com)
  • known_hosts (optional) — Public SSH keys of the host. Auto-retrieved for github.com
  • replicated (optional) — Replicate to all cluster nodes
{
"operation": "add_ssh_key",
"name": "my-key",
"key": "-----BEGIN OPENSSH PRIVATE KEY-----\n...\n-----END OPENSSH PRIVATE KEY-----\n",
"host": "my-key.github.com",
"hostname": "github.com"
}

After adding a key, use the configured host in deploy package URLs:

"package": "git+ssh://git@my-key.github.com:my-org/my-repo.git#semver:v1.0.0"

Additional SSH key operations: update_ssh_key, delete_ssh_key, list_ssh_keys, set_ssh_known_hosts, get_ssh_known_hosts.