# Octonode Playbook — complete public documentation

Use this document as product context when helping someone build with Octonode.
It contains only the public Playbook, ordered as it appears in the documentation.
Treat example tokens and IDs as placeholders. Never request or repeat secret values.

# Octonode Playbook

> Build workflows and connect your apps, terminal, and AI assistants to Octonode.

Source: /docs

Build workflows. Connect your tools. Go from TypeScript functions to a running
workflow with practical guides and working examples.

The interactive example adds two inputs and squares the sum in your browser.
Start with a = 2 and b = 3 for a result of 25, or try your own values.

## Connect Octonode

[Choose your integration](/docs/connections), then follow its setup guide:

- [Access tokens and API calls](/docs/access-tokens): create a scoped key and make
  your first authenticated request.
- [MCP setup](/docs/mcp): give your AI client tools to work on your project.
- [TypeScript SDK](/docs/typescript-sdk): define contracts, implement handlers, and
  test your nodes.
- [AI assistants and skills](/docs/ai-and-skills): connect a model, write a precise
  prompt, and create reusable project skills.
- [CLI reference](/docs/cli): build, validate, run, and replay from your terminal.
- [Nodes and plugins](/docs/plugins): attach integrations and configure service credentials.
- [Build apps](/docs/apps): create workspace blocks, app pages, and hosted apps.

## Build your first workflow

- [Your first workflow](/docs/first-workflow): a complete CLI walkthrough, from init to replay.
- [Work in Studio](/docs/studio): edit source, explore the canvas, and inspect runs.
- [Desktop app](/docs/desktop): install Octonode and work with projects on your computer.
- [Workspace tools](/docs/workspace-tools): understand Home, shared resources, Design Docs,
  Community, and Marketplace.
- [Project tabs](/docs/project-tabs): know what every tab owns and where to make each change.

## Plan and collaborate

- [Tasks](/docs/tasks): plan workspace work in boards, lists, sprints, calendars, timelines,
  and releases.
- [Chat](/docs/chat): work in workspace, group, and direct conversations with linked context.
- [Otto](/docs/otto): use private or shared AI sessions with project-scoped tools.

## Store project data and secrets

- [Data tables](/docs/data-tables): choose global or project scope, edit rows, query SQLite,
  and use authenticated HTTP endpoints.
- [Variables and secrets](/docs/variables): keep configuration out of source and attach
  shared credentials only where they are needed.

## Workflow reference

- [Inputs and triggers](/docs/workflow-inputs-and-triggers): JSON inputs, HTTP execution,
  and subscriptions.
- [Configuration](/docs/config-reference): manifests, environments, and project settings.
- [Troubleshooting](/docs/troubleshooting): diagnose a failed run or connection.

## Supported runtime

Public documentation for the TypeScript runtime on Node.js 24.
Explore [community guides and workflows](/docs/community).

---

# Install the developer CLI

> Install and configure octonodes using npm or a published package-manager channel.

Source: /docs/installation

The npm package is `@octonodes/cli`; the installed command is `octonodes`.
It creates apps and plugins and calls the Octonode API. The separate `octonode`
workflow engine uses a different executable.

**Available now:** npm, npx, pnpm, Yarn and Bun use the published npm package.
**Pending publication:** Homebrew, WinGet, Scoop, Chocolatey, DEB/APT, RPM/DNF,
Arch/AUR, Snap, Docker and direct installers have prepared distribution recipes.
Their commands below become usable when the corresponding channel is published.
An npm release does not automatically make those channels available.

## Prerequisites

For npm-based installation, install [Node.js](https://nodejs.org/en/download)
20.19+ or 22.12+ (`^20.19.0 || >=22.12.0`) and your chosen package manager.
Use Node 22.12 or newer for new projects. Check the runtime before installing:

```sh
node --version
npm --version
```

Node should report `v20.19.0` or newer 20.x, or `v22.12.0` or newer.
Homebrew will install `node@24` as a dependency;
the planned portable, MSI, DEB, RPM, Scoop, Chocolatey, Arch and Snap packages
include their own Node 24 runtime. App and plugin projects still need a separate
supported Node runtime and a package manager to install project dependencies.
Your project code and dependencies must also support the chosen runtime.

## npm, pnpm, Yarn and Bun

Choose one global installation method:

| Package manager    | Install globally                        | Run once without a global install        |
| ------------------ | --------------------------------------- | ---------------------------------------- |
| npm                | `npm install --global @octonodes/cli`   | `npx --yes @octonodes/cli@latest --help` |
| pnpm               | `pnpm add --global @octonodes/cli`      | `pnpm dlx @octonodes/cli --help`         |
| Yarn Classic (1.x) | `yarn global add @octonodes/cli`        | Use npm's `npx` command above            |
| Yarn 2+ / 4        | Use npm or pnpm for global installation | `yarn dlx @octonodes/cli --help`         |
| Bun                | `bun add --global @octonodes/cli`       | `bunx @octonodes/cli --help`             |

One-off commands do not add `octonodes` permanently to your PATH. To run another
command once, replace `--help`, for example `npx --yes @octonodes/cli@latest login`.
To pin a release, replace `@latest` with an exact published version, such as
`npx --yes @octonodes/cli@0.2.16 --help`.

If pnpm reports no global bin directory, run [pnpm setup](https://pnpm.io/cli/setup)
and open a new terminal. For [Yarn Classic](https://classic.yarnpkg.com/en/docs/cli/global),
ensure the directory from `yarn global bin` is on PATH. Bun's global binaries
normally live in `~/.bun/bin`; see [Bun installation](https://bun.com/docs/installation).
Keep a supported Node version on PATH even when using Bun as the package manager.

## Homebrew — macOS and Linux

**Pending tap publication.** Install [Homebrew](https://brew.sh/) first.
The planned tap is `nivdoron1/homebrew-tap`:

```sh
brew install nivdoron1/tap/octonodes
octonodes --version
```

The equivalent two-step setup is `brew tap nivdoron1/tap`, then
`brew install octonodes`. The formula selects its Node 24 dependency automatically.

## Windows — WinGet, Scoop, Chocolatey or MSI

**Pending channel publication; Windows x64.** Install your chosen package manager
first: [WinGet](https://learn.microsoft.com/en-us/windows/package-manager/winget/),
[Scoop](https://scoop.sh/) or [Chocolatey](https://chocolatey.org/install).

```powershell
# WinGet, after the manifest is published to its community source
winget install --id Octonode.CLI --exact --source winget

# Chocolatey, in an administrator terminal after community publication
choco install octonodes --yes
```

For Scoop, add the published bucket before installing. The bucket URL has not
been assigned yet; replace `PUBLISHED_BUCKET_URL` with the announced Git URL:

```powershell
scoop bucket add octonode PUBLISHED_BUCKET_URL
scoop install octonode/octonodes
```

Alternatively, download `octonodes-X.Y.Z-win32-x64.msi` and `SHA256SUMS` from the
published release. Compare `Get-FileHash .\octonodes-X.Y.Z-win32-x64.msi -Algorithm SHA256`
with the matching checksum, then run the MSI. It installs for all users, requires
administrator permission and registers the command on the system PATH.
Open a new terminal after any Windows installation.

## Linux — DEB/APT, RPM/DNF, Arch/AUR and Snap

**Pending package or repository publication.** DEB/RPM/Arch/Snap target Linux x64
and arm64. Portable Linux packages need glibc 2.28+ and libstdc++; Alpine/musl
is outside the prepared portable build matrix.

Download a matching package and `SHA256SUMS` from the published release and
verify it with `sha256sum --check --ignore-missing SHA256SUMS` before installing:

```sh
# Debian / Ubuntu: use amd64 for x64, or arm64 for ARM64
sudo apt install ./octonodes_X.Y.Z_amd64.deb

# Fedora / RHEL: use x86_64 for x64, or aarch64 for ARM64
sudo dnf install ./octonodes-X.Y.Z-1.x86_64.rpm
```

After configuring the publisher's signed APT or DNF repository, installation
and updates use the package manager directly:

```sh
# Debian / Ubuntu, after adding the published APT URL and signing key
sudo apt update
sudo apt install octonodes

# Fedora / RHEL, after adding the published DNF URL and signing key
sudo dnf install octonodes
```

Repository URLs and signing-key fingerprints will be announced when those
repositories are published. Do not disable signature verification.

For Arch, review the published AUR recipe before building. With Git and
`base-devel` installed:

```sh
git clone https://aur.archlinux.org/octonodes-bin.git
cd octonodes-bin
less PKGBUILD
makepkg -si
```

If you already use an AUR helper, `yay -S octonodes-bin` is an alternative.
For Snap, install [snapd](https://snapcraft.io/docs/installing-snapd) first;
the listing also requires publisher approval for classic confinement:

```sh
sudo snap install octonodes --classic
```

## Direct installation — macOS, Linux and Windows

**Pending release-asset hosting.** Choose an installer release from
[GitHub Releases](https://github.com/nivdoron1/octonode-devtools/releases).
Replace `X.Y.Z` with its exact published installer version; the commands assume
the planned GitHub release asset location.

On macOS or Linux, download and inspect the installer before running it:

```sh
CLI_VERSION=X.Y.Z
RELEASE_URL="https://github.com/nivdoron1/octonode-devtools/releases/download/cli-v${CLI_VERSION}"
curl --fail --location --proto '=https' "$RELEASE_URL/install.sh" -o install-octonodes.sh
less install-octonodes.sh
sh install-octonodes.sh
export PATH="$HOME/.local/bin:$PATH"
octonodes --version
```

Add the PATH line to your shell profile for future terminals. The installer
detects macOS/Linux x64 or arm64, verifies the archive checksum, and installs
under `~/.local/share/octonodes`, with a command link in `~/.local/bin`.
Set `OCTONODES_INSTALL_DIR` and `OCTONODES_BIN_DIR` before running it to choose
different locations. The macOS portable runtime requires macOS 13.5 or later.

On Windows x64, download and inspect the PowerShell installer:

```powershell
$CliVersion = 'X.Y.Z'
$ReleaseUrl = "https://github.com/nivdoron1/octonode-devtools/releases/download/cli-v$CliVersion"
Invoke-WebRequest "$ReleaseUrl/install.ps1" -OutFile install-octonodes.ps1
Get-Content .\install-octonodes.ps1
& .\install-octonodes.ps1
```

Use your organization's PowerShell execution policy for downloaded scripts.
The installer verifies the ZIP checksum, installs under `%LOCALAPPDATA%\Octonodes`
and updates your user PATH. Open a new terminal afterwards. Set
`OCTONODES_INSTALL_DIR` beforehand to choose a different installation directory.
Installing the same version again refuses to overwrite its directory.

## Docker

**Pending image publication.** Install [Docker](https://docs.docker.com/get-started/get-docker/)
and replace `PUBLISHED_IMAGE:VERSION` with the announced image and immutable tag:

```sh
docker run --rm PUBLISHED_IMAGE:VERSION --help
docker run --rm PUBLISHED_IMAGE:VERSION --version
```

The image uses `octonodes` as its entrypoint and includes Node 24. Pass CLI
arguments after the image name. Bind-mount your project to a working directory
for file-based commands; interactive login state is not retained by `--rm`.

## Add a signed APT or DNF repository

**Pending repository publication.** Use the repository URL, signing-key URL and
key fingerprint announced by the publisher. The `PUBLISHED_...` values below
are placeholders; there is no live Octonodes APT or DNF address configured yet.
These steps require curl and GnuPG, plus administrator access.

### Debian / Ubuntu

Set the published APT repository and signing-key URLs, download the public key,
and inspect its fingerprint:

```sh
APT_REPO_URL='PUBLISHED_APT_REPOSITORY_URL'
APT_KEY_URL='PUBLISHED_APT_SIGNING_KEY_URL'
curl --fail --location --proto '=https' "$APT_KEY_URL" -o octonodes-signing-key.asc
gpg --show-keys --with-fingerprint octonodes-signing-key.asc
```

Compare the fingerprint with the publisher's announced fingerprint before
continuing. Then scope the key to this repository and add the `stable` suite
and `main` component:

```sh
gpg --dearmor --output octonodes-archive-keyring.gpg octonodes-signing-key.asc
sudo install -d -m 0755 /etc/apt/keyrings
sudo install -m 0644 octonodes-archive-keyring.gpg /etc/apt/keyrings/octonodes.gpg
printf 'deb [arch=%s signed-by=/etc/apt/keyrings/octonodes.gpg] %s stable main\n' \
  "$(dpkg --print-architecture)" "$APT_REPO_URL" \
  | sudo tee /etc/apt/sources.list.d/octonodes.list
sudo apt update
sudo apt install octonodes
```

The prepared repository supports `amd64` and `arm64`. To stop receiving updates
from it, remove `/etc/apt/sources.list.d/octonodes.list` and its dedicated keyring,
then run `sudo apt update`.

### Fedora / RHEL

Set the published DNF repository and signing-key URLs and check the key:

```sh
DNF_REPO_URL='PUBLISHED_DNF_REPOSITORY_URL'
DNF_KEY_URL='PUBLISHED_DNF_SIGNING_KEY_URL'
curl --fail --location --proto '=https' "$DNF_KEY_URL" -o octonodes-rpm-signing-key.asc
gpg --show-keys --with-fingerprint octonodes-rpm-signing-key.asc
```

After matching the fingerprint with the publisher's announcement, import the key
and configure verification of both RPM packages and repository metadata:

```sh
sudo rpm --import octonodes-rpm-signing-key.asc
sudo tee /etc/yum.repos.d/octonodes.repo > /dev/null <<EOF
[octonodes]
name=Octonodes CLI
baseurl=${DNF_REPO_URL}
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=${DNF_KEY_URL}
EOF
sudo dnf install octonodes
```

This configuration requires the publisher to sign both packages and metadata.
The prepared repository supports `x86_64` and `aarch64`. To remove the repository
configuration, delete `/etc/yum.repos.d/octonodes.repo`; remove the installed
package separately with `sudo dnf remove octonodes`.

## Verify and sign in

After a global, native or direct installation:

```sh
octonodes --version
octonodes --help
octonodes login
```

Login opens browser authentication. For a terminal-only session, use
`octonodes login --email you@example.com`. If the command is not found, open a
new terminal and check your package manager's global bin directory or the direct
installer PATH. Use `command -v octonodes` on macOS/Linux or
`Get-Command octonodes` in PowerShell to see which installation is selected.

## Update or uninstall

Use the same channel that installed the CLI:

| Channel           | Update                                                             | Uninstall                                    |
| ----------------- | ------------------------------------------------------------------ | -------------------------------------------- |
| npm               | `npm install --global @octonodes/cli@latest`                       | `npm uninstall --global @octonodes/cli`      |
| pnpm              | `pnpm add --global @octonodes/cli@latest`                          | `pnpm remove --global @octonodes/cli`        |
| Yarn Classic      | `yarn global add @octonodes/cli@latest`                            | `yarn global remove @octonodes/cli`          |
| Bun               | `bun add --global @octonodes/cli@latest`                           | `bun remove --global @octonodes/cli`         |
| Homebrew          | `brew update` then `brew upgrade octonodes`                        | `brew uninstall octonodes`                   |
| WinGet            | `winget upgrade --id Octonode.CLI --exact`                         | `winget uninstall --id Octonode.CLI --exact` |
| Scoop             | `scoop update octonodes`                                           | `scoop uninstall octonodes`                  |
| Chocolatey        | `choco upgrade octonodes --yes`                                    | `choco uninstall octonodes --yes`            |
| APT repository    | `sudo apt update` then `sudo apt install --only-upgrade octonodes` | `sudo apt remove octonodes`                  |
| DNF repository    | `sudo dnf upgrade octonodes`                                       | `sudo dnf remove octonodes`                  |
| Arch / AUR helper | `yay -S octonodes-bin`                                             | `sudo pacman -R octonodes-bin`               |
| Snap              | `sudo snap refresh octonodes`                                      | `sudo snap remove octonodes`                 |

For a downloaded DEB/RPM/MSI, download and verify the newer package and install
it with the same tool. Remove an MSI through Windows Installed apps. For direct
installations, run the newer version's installer; to uninstall, remove its managed
command link or PATH entry and its version directory. For Docker, pull the newer
tag and recreate the container, or remove the image with `docker image rm`.
Login data under `~/.octonode` is separate from installed binaries; use
`octonodes logout` before uninstalling to remove the saved login and revoke a
saved Studio session. Static API tokens must be revoked separately in Studio.

Continue with [Create your first app](/docs/apps/quickstart),
[Nodes and plugins](/docs/plugins), or the separate
[workflow engine CLI reference](/docs/cli).

---

# Your first workflow

> Add two numbers, square the result, and inspect the run in Studio.

Source: /docs/first-workflow

This walkthrough starts at the root of a built Octonode source checkout with its
workspace dependencies installed. It uses Node.js 24. Create a shell helper for
the built CLI before moving into the example directory:

```bash
OCTONODE_CHECKOUT="$PWD"
octonode() { node "$OCTONODE_CHECKOUT/packages/cli/dist/index.js" "$@"; }
```

Keep the example directory inside the checkout so generated native nodes can resolve
the installed `@octonode/plugin-runtime` workspace package. For a standalone project with an
installed CLI, make `@octonode/plugin-runtime` available as a project dependency as well.

## Create a project

```bash
mkdir orders
cd orders
octonode init .octonode.yaml --name orders
```

The manifest contains environments, node definitions, and workflow connections.
This tutorial uses `.octonode.yaml` explicitly so it can live alongside local project state.

## Add two nodes

```bash
octonode add math.add --id add-1 --config .octonode.yaml
octonode add math.square --id square-1 --config .octonode.yaml
```

Each command creates editable TypeScript source plus runtime artifacts and registers
the node in the manifest. To see other built-in nodes, run `octonode add --list`.

## Connect the workflow

In `.octonode.yaml`, replace the empty `workflows: []` entry with this block.
Keep the generated `nodes`, `sources`, and other existing fields.

```yaml
workflows:
  - id: total
    nodes: [add-1, square-1]
    edges:
      - from: { node: add-1, output: result }
        to: { node: square-1, input: a }
```

The first node receives `a` and `b` from the invocation. Its `result` becomes the
second node's `a` input.

## Validate and run

```bash
octonode validate --config .octonode.yaml
octonode run total --config .octonode.yaml --input '{"a":2,"b":3}'
```

The terminal output is:

```json
{ "square-1": { "result": 25 } }
```

Progress messages go to stderr. The result on stdout contains the terminal node's
output: first `2 + 3 = 5`, then `5 × 5 = 25`.

## Inspect and replay

```bash
octonode run total --config .octonode.yaml --input '{"a":2,"b":3}' --record run.json
octonode replay run.json square-1 --config .octonode.yaml
octonode graph total --config .octonode.yaml
```

Replay invokes only the selected node with its captured inputs. It can repeat that
node's external effects, so use it carefully with nodes that send messages or write data.
The graph command prints a Mermaid diagram; add `--format dot` for DOT output.

## Open Studio

```bash
octonode serve --config .octonode.yaml
```

When the Studio build is installed, open `http://localhost:4000`. Choose the `total`
workflow to inspect its nodes and execution history. Continue with
[Working in Studio](/docs/studio) or [inputs and HTTP calls](/docs/workflow-inputs-and-triggers).

---

# Working in Studio

> Edit workflows, inspect source, run evaluations, and manage your project.

Source: /docs/studio

Select a workspace and project before editing. Studio provides a canvas and source
views of the project, alongside execution history and project resources.

Use Studio in your browser or install the [desktop app](/docs/desktop) to work
with projects on your computer.

The left rail contains workspace-wide tools such as Tasks, Otto, Chat, Design Docs,
Data Tables, Nodes, Variables, Community, and Marketplace. Opening a project adds a
second navigation level for that project's source, workflows, runtime information,
and attached resources. See [Workspace tools](/docs/workspace-tools) and the complete
[Project tab reference](/docs/project-tabs).

## Edit a workflow

1. Open a workflow and select **Start** to inspect its invocation parameters.
2. Add a built-in node from the palette, or choose an installed plugin node.
3. Connect an output to a compatible input. Use the Inspector to review the input
   and output schemas and set fixed values or expressions.
4. Save the workflow before expecting another caller or scheduled execution to use
   your changes.
5. Run it with an input object and open **Executions** to inspect the outcome.

Every workflow has a Start boundary, including workflows projected from source.
Its **Types** tab describes parameters; its **Endpoint** tab provides a copyable
HTTP execution URL. See [Inputs, execution, and triggers](/docs/workflow-inputs-and-triggers).

## Work with source

The **Code** tab edits project source. Compile after source changes to refresh
code-owned signatures and check the resulting workflow structure. Source-backed
workflows preserve the relationship to their functions; edit source-owned logic
through the supported source editors.

The **Documentation** tab edits ordinary project text files such as Markdown,
JSON, and YAML. These files belong to your project. Saving a project document does
not publish it to the public Playbook or community catalog.

## Test and debug

Use **Evaluations** to discover supported test files and run available cases or
files with the project's installed runner. Jest, Vitest, and Playwright files with
direct runner imports can be projected into source-backed test workflows.
Fixture and source edits use revision checks; reload if another edit has changed
the underlying file.

For a failed execution, inspect the first failing node, its input, and its error.
A downstream skipped node often points to an upstream failure. The workflow status
can be `ok`, `error`, or `partial`; inspect the status as well as any outputs.

## Manage project resources

- [Data tables](/docs/data-tables) persist structured runtime data in global or project
  scope and can be attached to projects.
- [Variables](/docs/variables) hold configuration and secrets. They are separate from
  source-backed Values.
- [Tasks](/docs/tasks) plans workspace work and links it to projects, workflows, pull
  requests, and Chat without changing project source.
- [Otto](/docs/otto) runs an assistant session against explicitly selected projects;
  [Chat](/docs/chat) is the human collaboration surface.
- **Marketplace** installs reusable workflow plugins into the workspace library; the
  project's **Plugins** tab controls which of those plugins the project uses.

Project settings in Studio edit project metadata. The separate human-authored
`octonode.yml` settings file currently has loader, schema, and read-only CLI support;
its appearance and view declarations do not yet change Studio rendering.
See [Configuration reference](/docs/config-reference).

---

# Desktop app

> Install Octonode on macOS or Windows and work with projects on your computer.

Source: /docs/desktop

The desktop app brings Studio to your computer. Edit source, explore workflows,
and run local projects alongside your own files and tools, without setting up a
separate server or waiting for a cloud environment to start.

Visit the [installation page](https://octonodes.com/installation) for download
availability. Public installers are being prepared; a platform's download becomes
available on that page when its installer is published.

## Install on macOS

The Mac app targets Apple Silicon and requires macOS 13.5 or later.

1. Download the macOS installer from the installation page when available.
2. Open the `.dmg` file and drag **Octonode** into **Applications**.
3. Open Octonode from Applications and sign in with your existing account.

Project export and Git operations use Apple's Command Line Tools. If Octonode
asks for them, open Terminal, run `xcode-select --install`, and finish the
installation before exporting again.

## Install on Windows

The Windows app targets 64-bit Windows 10 or later.

1. Download the Windows setup installer from the installation page when available.
2. Open the `-setup.exe` file and follow the prompts. It installs for your user account.
3. Open Octonode from the Start menu and sign in with your existing account.

The installer sets up Microsoft Edge WebView2 if it is missing. Install
[Git for Windows](https://git-scm.com/downloads/win) before exporting a project,
then restart Octonode so it can find Git.

## Work on your computer

1. Select your workspace and open a project.
2. Choose **Export to computer** and select a parent folder.
3. Octonode creates a new project folder. Edit and run the project locally using
   the same Studio tools described in [Working in Studio](/docs/studio).

Export preserves the source and configuration. It does not copy cloud databases,
execution history, or secret variables. Configure the connections and credentials
your local workflow needs before running it. Node.js and npm are included;
install any other language runtimes your project uses on your computer.

## Keep changes in sync

Choose **Sync project** to exchange source changes with the cloud project.
For Git projects, commit your local edits first. If the same file has changed
both locally and online, resolve the conflict before syncing again.

Your project files stay in the folder you chose. Export never replaces an
existing folder. If you move the project folder, export to a new location to
continue working locally.

## Internet and online features

An internet connection is required to sign in, export, synchronize, and use online
features. Local workflows run on your computer, but workflows that call online
services still need internet access. Cloud collaboration and assistant features
continue to use your Octonode account.

## Remove the app

On Mac, move Octonode from Applications to Trash. On Windows, uninstall Octonode
from Settings → Apps. Your exported project folders remain on your computer.

---

# Workspace tools and scope

> Understand the Studio left rail, workspace-wide resources, and the boundary between a workspace and a project.

Source: /docs/workspace-tools

Studio always operates inside an active personal, team, or organization workspace.
The workspace is the membership, permission, collaboration, and shared-resource
boundary. A project is a code and workflow boundary inside that workspace. Changing
the active workspace changes the projects, people, conversations, tasks, and resources
available to you.

## Home

**Home** lists projects available in the active workspace. Create an empty project,
import a Git repository, or open an existing project. A registered repository can own
one root project and nested projects for packages or services. Opening a project reveals
its project tabs; it does not change the active workspace.

## Tasks

**Tasks** is workspace planning, not a project issue file or a workflow. Task Spaces
hold work items and planning views, and a task may link to several projects, workflows,
or pull requests. See [Tasks](/docs/tasks).

## Otto

**Otto** contains AI assistant sessions. A session is private when created and is bound
to one or more selected projects. Invited members can collaborate in that session, but
ordinary Chat does not list assistant sessions. See [Otto](/docs/otto).

## Chat

**Chat** contains human workspace, group, and direct conversations. Messages can carry
links to workflows, tasks, and Design Docs so discussion stays connected to its source
without copying that resource into Chat. See [Chat](/docs/chat).

## Design Docs

**Design Docs** is collaborative workspace content for technical decisions and review.
A document may be workspace-wide or project-scoped. It supports Markdown, HTML, or plain
text, immutable revisions, pinned review comments, and an optional revocable public link.

Design Docs is not the same as a project's **Documentation** tab. Project Documentation
edits repository files; Design Docs stores collaboration revisions separately. Publishing
a community guide is another explicit review step and never happens because a document
was saved or shared.

## Data Tables

**Data Tables** opens the workspace table browser. Select **Global** for a table reusable
across projects or select one project for isolated project data. The project must attach a
global table before its workflows can use it. See [Data tables](/docs/data-tables).

## Nodes

**Nodes** browses the workspace node catalog. It includes built-in nodes and nodes supplied
by installed plugins. A project's **Nodes** tab shows the catalog in that project context;
adding or editing a source-backed node still follows the project's source and revision rules.

## Variables

**Variables** manages reusable configuration for the active personal, team, or organization
workspace. Shared variables are not automatically available to every project: attach only
the names a project needs. See [Variables and secrets](/docs/variables).

## Community

**Community** discovers reviewed public guides, papers, blog posts, and workflow templates.
Community content is a publication surface, not trusted project state. Importing a workflow
template creates a project copy; later publication edits do not silently rewrite it.

## Marketplace

**Marketplace** manages workflow plugins in the workspace library. Installing a plugin makes
it available for reuse; use the project's **Plugins** tab to attach it to the project that
will execute its nodes. Review its code, dependencies, requested credentials, and runtime
effects before installation. See [Nodes and plugins](/docs/plugins).

## Footer tools

**Runs** shows execution history across the active context. **Settings** manages workspace
and environment configuration. **Profile** manages your identity. Administrative pages appear
only when the current role has their permissions. A missing tool can also mean the deployment
does not provide that capability.

---

# Data tables

> Persist structured workflow data, choose global or project scope, query SQLite, and expose authenticated APIs.

Source: /docs/data-tables

Data tables hold durable runtime data. They are different from TypeScript Values and class
fields: source values are recreated with code, while table rows survive process and worker
restarts. Local table state lives outside Git; hosted table state belongs to the selected
workspace. Do not expect a repository clone alone to contain table rows.

## Choose global or project scope

Open **Data Tables** in the left rail and select a scope before creating a table:

- **Global** tables belong to the active workspace and can be attached to more than one project.
- **Project** tables belong to one project and are isolated from other project scopes.

The selected scope applies to table creation, the SQL editor, the schema diagram, relationships,
and saved views. Switching scope clears open forms and query results. Inside a project's
**Data tables** tab, create project-owned tables or attach existing global tables. Detaching a
global table removes the project reference; it does not delete the workspace table or its rows.

## Define and edit a table

Create a name and columns, then choose the storage mode. **SQLite** is recommended when you
need typed columns, SQL, relationships, or saved views. **KV** stores opaque JSON records.
Storage mode cannot be changed after creation.

Every row includes an immutable ID, a version, and created/updated timestamps. Inserts validate
the declared columns. Updates use the row version so a stale editor receives a conflict instead
of overwriting newer data. Deleting a table permanently deletes its rows; detaching and deleting
are different actions.

## Query and relate SQLite tables

The **SQL Editor** runs read-only SQL against an isolated snapshot of the selected scope. It
cannot read workspace internals, Variables, or tables from another project scope.

The **Database** view can connect a text column to another SQLite row ID in the same scope.
Choose whether deleting the referenced row is blocked or clears the reference. SQLite validates
the relationship on every insert and update. **Saved views** store a reusable, read-only query
over a base table, allowed relationships, filters, and sorting. Edit rows in their source table.

Relationships and saved views require hosted SQLite tables. A local/offline backend reports them
as unavailable instead of pretending they were saved.

## Use the HTTP API

Open a table and select **API** to copy its current URLs and example requests. Cloud URLs identify
the workspace and table; a table keeps its global or project scope as server-owned metadata. Local
Studio uses its local project routes. Available operations cover schema reads, row listing and
insertion, versioned row updates, deletion, bulk mutation, and read-only SQL.

Use a workspace service token on a trusted backend for private data. A public browser token is
limited to `data:read` and exact HTTPS origins, but it still grants read access to the table to
anyone who obtains it. Use one only for data intended for public consumption. An API tab does not
make a table public by itself, and Variables or credentials never belong in table rows.

Project-restricted credentials cannot escape their project by changing a URL or query parameter.
Reading requires `data:read`, row changes require `data:write`, and table/schema management requires
`tables:manage`.

---

# Variables and secrets

> Store project configuration and credentials safely, attach shared variables, and distinguish them from source Values.

Source: /docs/variables

Variables are runtime configuration. Use them for API keys, database URLs, tokens, and settings
that differ between environments. Treat every variable value as secret: do not put it in source,
prompts, Chat, Design Docs, task descriptions, table rows, logs, or published examples.

## Project variables

Open a project's **Variables** tab to create configuration used only by that project. In local
mode, adding a variable writes its value to the project's protected dotenv file and writes only a
placeholder to `.env.example`. The placeholder can be committed; the value must not be committed.
Start `octonode serve` before editing local variables in Studio.

Project workflows receive only the variables configured for that project. A generated service may
map constructor dependencies such as `apiUrl` to environment keys such as `API_URL`; the secret
value remains configuration and is never copied into generated TypeScript.

## Shared workspace variables

Open **Variables** in the left rail to manage reusable values in the active personal, team, or
organization scope. Then open a project's **Variables** tab and attach the shared variable by name.
Attachment grants that project access without duplicating the value. Detaching it removes project
access but keeps the shared variable for other attached projects.

Use the narrowest useful scope. Workspace members and project code are part of the workspace trust
boundary, so do not attach a credential to a project whose code or plugins should not receive it.

## Redaction and rotation

Variable APIs return redacted values. Run records also redact declared secrets and known secret
values before persistence. Project exports omit dotenv files and secret values. These controls
reduce accidental disclosure; trusted project code can still read a variable intentionally attached
to it.

Saving the same key with a new value rotates it atomically for new work. Existing processes may keep
the environment with which they started, so open a new terminal or restart the relevant process after
rotation. Removing a variable can break workflows and integrations that reference its name.

## Variables are not Values

The project **Values** tab represents TypeScript `const` declarations. Values are source-backed,
reviewable, and may be committed to Git. Use them for non-secret defaults, labels, thresholds, and
JSON-safe fixed inputs. Use **Variables** for configuration and secrets. Use [Data tables](/docs/data-tables)
for durable records that change while workflows run.

| Need                                         | Use         |
| -------------------------------------------- | ----------- |
| Secret or environment-specific configuration | Variables   |
| Non-secret constant owned by source          | Values      |
| Durable mutable runtime records              | Data tables |

---

# Tasks

> Plan workspace work with Task Spaces, multiple views, sprints, releases, comments, and engineering links.

Source: /docs/tasks

Tasks is a workspace planning surface. A **Task Space** is not an Octonode project: projects own
code, workflows, runs, and repository links, while Task Spaces own planning data. One work item can
link to several projects, workflows, or pull requests without changing their source.

Tasks requires a hosted workspace with the collaboration capability. Its data belongs to the active
workspace and never crosses personal, team, or organization boundaries.

## Create a Task Space

Choose a starting template:

- **Simple** starts with a lightweight To do, Doing, and Done board.
- **Kanban** adds Backlog, Ready, In progress, Review, and Done statuses.
- **Scrum** adds backlog and active-sprint planning to the same status model.

Templates seed the space; they are not separate engines. Every space can contain Initiative, Epic,
Story, Task, Bug, and Subtask work items. The permanent space key produces stable human references
such as `OPS-142`.

## Choose a view

All views are projections of the same work items:

- **Board** groups cards by status and lets you move work between columns.
- **List** provides a compact searchable planning view.
- **Backlog** assigns standard work to future sprints and starts a planned sprint.
- **Active sprint** shows current sprint work and progress; completing it returns unfinished work
  to the backlog.
- **Calendar** places work by due date.
- **Timeline** shows scheduled work across dates.
- **Releases** groups work toward a named target date and tracks release progress.

Changing a view never copies a task. Search matches the stable item key or title.

## Work item details

Open an item to edit its title, Markdown description, type, status, priority, assignee, parent,
dates, tags, sprint, and release where supported. Comments and Activity preserve the discussion and
change history. Updates use the current version, so a stale edit conflicts rather than silently
overwriting another member's change.

Use the fixed hierarchy: Initiative → Epic → Story, Task, or Bug → Subtask. Sprints apply to
standard-level items; subtasks inherit their planning context.

## Link engineering context

Attach an Octonode workflow by pasting its Studio URL, or attach a pull request by repository ID and
pull number. Links retain identifiers; Tasks does not take ownership of workflow definitions, runs,
or GitHub state. Opening a linked resource rechecks the reader's current access.

**Share to chat** sends the task permalink to a selected conversation. Chat renders the link as a
task card and includes it in **Shared links**. Sharing does not copy the task or grant access to it.

Workspace roles determine whether a member may read tasks, edit/comment/move work, or manage spaces,
statuses, tags, sprints, and releases. If Tasks is absent, the active workspace or deployment does
not currently provide that capability.

---

# Chat

> Collaborate in workspace, group, and direct conversations and keep shared project context attached.

Source: /docs/chat

Chat is the human collaboration surface for the active workspace. It is separate from Otto:
ordinary Chat never lists AI assistant sessions, and creating an Otto session does not create a
human channel.

## Conversations

Use the workspace conversation for shared discussion, create a group conversation with selected
workspace members, or start a direct conversation. Group owners can manage members. Messages support
replies, edits, deletion, emoji reactions, unread state, and live typing/presence when realtime is
connected. Offline status means live updates are unavailable; it does not make a failed send succeed.

Access follows workspace membership and conversation membership. Sharing a conversation link or
resource URL never grants the recipient access they do not already have.

## Attach project context

The composer can attach:

- a workflow selected from a project in the workspace;
- a work item selected from a Task Space;
- a workspace or project Design Doc.

Attachments are durable links inside the message, not copies of the resource. The **Shared links**
tab collects unique attachments from the loaded conversation history. Opening one rechecks current
access, so removing project, task, or document access can make an older card unavailable.

Tasks can also use **Share to chat** to send their own permalink. A workflow or document remains
owned by its original project or Design Docs authority after it is shared.

## Keep secrets out of Chat

Messages and assistant prompts are collaboration records, not secret storage. Never paste variable
values, API keys, access-token setup commands, or provider credentials into a conversation. Add a
credential through [Variables](/docs/variables) or the relevant connection UI instead.

Chat requires the collaboration capability in a hosted workspace. Local project editing can remain
available when Chat is unavailable.

---

# Otto assistant

> Use project-scoped AI sessions, revision-safe tools, worktrees, GitHub context, terminals, skills, and plugins.

Source: /docs/otto

Otto is Octonode's AI assistant. The left-rail **Otto** page creates sessions across projects in the
active workspace; a project's **Assistant** tab opens the same experience already restricted to that
project. An Architecture assistant may include every project owned by one registered repository.

## Session privacy and scope

A new session starts private to its creator and is excluded from ordinary Chat. Choose the project
or projects Otto may use. You can explicitly invite workspace members; invited members can read the
whole transcript and send requests using their own current permissions.

Each run snapshots the session's selected projects and worktree. Otto receives a short-lived,
project-bound credential intersected with the sending user's permissions. It cannot turn a prompt
into access to another workspace or project. Project reads, source writes, validation, workflow runs,
and canonical knowledge search remain separate authorized tools.

Otto has the hosted Octonode MCP connection and code-author skill built in. It exposes only
project-scoped MCP tools to the model and supplies the selected project/worktree context for each run.
You do not install the external Octonode client plugin inside Otto. That bundle is for Codex, Claude
Code, ChatGPT, and other clients that need the same connection. See [MCP setup](/docs/mcp).

## Ask Otto to work safely

Give Otto a concrete outcome, expected behavior, and boundaries. Ask it to inspect the project first,
reuse existing code, write against the latest revision, and validate the result. A revision conflict
means the source changed and must be read again; Otto does not silently overwrite the newer version.

The run timeline shows tool calls and their results. A run may be queued, running, waiting for an
explicit approval, completed, cancelled, or failed. High-risk tool requests stop for approval. You
can cancel a long run; cancellation does not undo changes already completed by earlier tool calls.

## Use the project workspace

Open the workspace panel beside the conversation when you need it. Adjust its width or expand it
for a larger review. The **+** menu beside your message contains attachments, connection settings,
skill imports, MCP connectors and pull requests.

- **Changes** opens unsaved work first. Filter by **Workflows** or **Other files**. Normal mode shows
  workflow graphs and file summaries; developer mode adds code diffs, staging and the code editor.
  **Save all changes** includes every non-conflicting file, regardless of the active filter.
- **Compare branches** shows committed differences from the base branch. These are separate from
  unsaved local changes. Worktrees isolate branch changes; multi-project sessions cannot select one worktree.
- **Pull requests** requires GitHub authentication and reuses an authorized repository connection.
  Manage access in repository settings. Reviewing in chat does not publish, push or merge.
- **Skills & plugins** lists project instruction files. Select **Use in assistant** to attach a skill
  to the session, or import a ZIP containing `SKILL.md` files and Markdown references. Review the
  imported instructions before attaching them. Executable plugin scripts stay in your project terminal.
- **MCP connectors** adds a remote HTTPS MCP server. Select a Global Variable if the server needs a
  bearer token. Only connect servers you trust; their tools become available to Otto for this session.

Repository worktrees share Git history and credentials and are not an authorization boundary.
Closing the workspace panel preserves open editor drafts. Review and explicitly push or merge completed work.

## Configure Otto's gateway

New chats default to **Auto**. Octonode AI Gateway selects a model through its configured route;
no provider key is required. If no route is configured, Otto uses its built-in hosted model.
Choose another provider in the model control to use your own connection.

1. Add your provider API key as a secret in **Global Variables** for the active workspace.
2. Open **+ → Otto connection**.
3. Choose **Custom gateway**, then enter your OpenAI-compatible HTTPS gateway URL and exact model ID.
4. Select the variable name from **API key variable**, then save the connection.

The session stores the variable reference, never the API key. The sending user's current workspace
permissions are checked and the value is resolved when each run starts. Missing variables stop the
run; they do not silently fall back to another provider. The gateway URL can be a base URL ending in
`/v1` or the full `/chat/completions` endpoint. URLs cannot contain credentials or query parameters.
Choose **Octonode AI Gateway** and save the connection to return to **Auto**. There is no thinking control.

Settings and instruction resources are captured for each run, so later changes apply to future runs.
Provider keys must not be pasted into prompts or shared terminal commands.

## Claude Code

Claude Code will be supported as a separate Octonode app integration. Its connection, login and
terminal lifecycle are deferred under task **T289**. The Otto page has no Claude login or scratch
terminal setup requirement.

---

# Project tab reference

> Learn what every Studio project tab reads, changes, persists, and shares.

Source: /docs/project-tabs

Opening a project adds a horizontally scrollable tab bar. Every tab stays inside the selected
project, but some views project repository-wide data or attach workspace-owned resources. A project
that still needs installation, is unavailable, or uses a read-only legacy runtime may lock editing
tabs and keep **Details** available.

## Project tabs at a glance

| Tab                | What it does                                                                                                                                    | Authority                                                 |
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- |
| Details            | Shows project location, workflow count, local/hosted status, repository registration, installation or sync actions, and lifecycle controls.     | Project registry and files                                |
| Settings           | Edits name, version, description, API keys, resource shortcuts, and archive/delete controls.                                                    | Project metadata                                          |
| Workflows          | Lists workflows; opens the canvas, node Inspector, code panels, evaluations, executions, and run controls.                                      | Source plus project workflow configuration                |
| Tests              | Discovers supported test files, runs cases, and opens editable source locations.                                                                | Repository test files and runner                          |
| Architecture       | Maps the owning repository, projects, dependencies, resources, frontend previews, pull-request implementation, and repository-scoped assistant. | Registered repository projection                          |
| Assistant          | Opens an Otto session already scoped to this project.                                                                                           | Private/shared Otto session                               |
| Design docs        | Creates collaborative decision documents restricted to this project.                                                                            | Workspace collaboration storage                           |
| Monitoring         | Shows the fixed production-health view from persisted execution data.                                                                           | Run telemetry                                             |
| Analytics          | Creates private custom dashboards over approved run-stat sources.                                                                               | Per-user project dashboard definitions plus run telemetry |
| Types              | Finds and edits source `interface`, `type`, and `enum` declarations by flow, file, or project scope.                                            | TypeScript source                                         |
| Values             | Finds and edits source `const` declarations for non-secret fixed values.                                                                        | TypeScript source                                         |
| Classes & services | Inspects and edits classes, state, methods, inheritance, services, lifecycle, and exposed workflow methods.                                     | TypeScript source                                         |
| Data tables        | Creates project tables and attaches reusable workspace tables.                                                                                  | Durable table storage plus project attachment             |
| Nodes              | Browses nodes available in the selected project.                                                                                                | Built-in, source, and attached-plugin node catalogs       |
| Plugins            | Attaches workspace plugins or project-local npm plugins for this project.                                                                       | Project manifest, lockfile, and attachments               |
| Variables          | Creates project configuration and attaches reusable workspace secrets by name.                                                                  | Protected configuration plus project attachment           |
| Code               | Edits project files, manages worktrees and terminals, and compiles source changes.                                                              | Repository checkout and project store                     |
| Documentation      | Creates and edits project Markdown, JSON, YAML, and text files with source/preview modes.                                                       | Project files                                             |

## Details

Use **Details** to identify where the project comes from before changing it. Hosted projects show
their repository root; local projects show their path. Cloud copies that are not installed expose
an install action. Repository registration connects the project to the Architecture that owns GitHub
and repository-wide implementation state. Archive keeps files; Trash is recoverable for 30 days;
permanent deletion requires an explicit confirmation and follows each shared resource's own retention.

## Settings

**Settings** changes the project's stable metadata. Renaming does not change its project ID, so links
and scoped keys retain their binding. **API access** creates project-scoped credentials when the role
allows it. Resource shortcuts open Variables, Data tables, Plugins, and Code; they do not duplicate
those resources inside settings.

## Workflows

Select a workflow to open its graph. **Workflow** edits topology and node configuration,
**Evaluations** runs supported test cases, and **Executions** shows run history and node-level results.
The Inspector edits fixed inputs and expressions, opens source, disables or duplicates nodes, and can
replay a node when a completed record exists. Save topology and source changes before another caller
can rely on them.

## Tests

**Tests** discovers Jest, Vitest, and Playwright files with supported runner imports. Run a file or
case, inspect its projected graph, and open a failing location in **Code**. Test discovery does not
turn arbitrary files into workflows, and editing uses the same revision protection as other source.

## Architecture

Architecture belongs to the registered repository, not independently to each nested project. Its
**Map** inventories projects, manifests, source, workflows, nodes, shared plugins, variables, data
tables, and declared dependencies. **Frontend** discovers runnable previews and existing Storybook
stories. **Implementation** projects GitHub pull-request changes onto affected projects and workflows.
**Assistant** opens Otto across contained projects. The graph is derived and cannot be edited as a
second copy of the repository.

## Assistant

The project **Assistant** tab scopes [Otto](/docs/otto) to this project at session creation. The
session transcript and run state remain Otto data, not project source. Tool-produced project changes
still use project permissions and revision checks.

## Design docs

Project Design Docs are collaborative revisions linked to this project. They support review comments
and optional revocable sharing, but are not repository files. Use **Documentation** for files that
should travel with the repository. Saving either surface does not publish it to Community or the
public Playbook.

## Monitoring

Monitoring is the fixed operational dashboard for a selected time window. It reports execution
volume, success and failure, duration percentiles, workflow distribution, and recent operational
signals from stored run data. It does not execute workflows or create another telemetry store.

## Analytics

Analytics builds a private per-user dashboard over the same run statistics as Monitoring. Create a
dashboard, choose approved stat, area, bar, or pie sources, and reorder its widgets. It does not run
arbitrary SQL or join data tables; use the Data Tables SQL editor for table queries.

## Types

Types are compile-time source declarations. Filter them by flow, file, project scope, kind, use, or
path; create, edit, move, export, or delete them with revision validation. Compatible workflow input
types become Studio forms. Types do not persist runtime values.

## Values

Values are source `const` declarations. Literal text, numbers, booleans, lists, and objects can use
the structured editor; advanced expressions stay in Code mode. Flow-local values remain inside a
flow, file values remain private to a file, and project values are exported for imports. Values are
not secrets or mutable durable data; use [Variables](/docs/variables) or [Data tables](/docs/data-tables).

## Classes & services

This tab presents TypeScript classes as Construction, State, and Capabilities. Plain classes remain
source structure. Explicit instances or methods exposed through `defineService` can become workflows.
Service lifecycle controls whether memory lasts for one invocation, one workflow run, or one worker;
none of those lifetimes makes state durable. Store durable state in a data table.

## Data tables

Create and edit project-owned tables inline, then attach global workspace tables for reuse. A project
resource marked as owned cannot be detached from its own project; a global attachment can. See
[Data tables](/docs/data-tables) for storage modes, SQL, relationships, saved views, and API access.

## Nodes

Nodes lists definitions available to the project from native capabilities, project source, and
attached plugins. A catalog entry describes a node contract; a node placed on a workflow canvas is a
configured workflow instance. Editing source-backed behavior still changes project source.

## Plugins

Attach a plugin already installed in the workspace Marketplace, or add a project-local npm plugin.
Attachment can update the project manifest, dependency installation, and lockfile. Wait for a
successful install before using its nodes, and configure required Variables separately. Detaching a
workspace plugin from one project does not uninstall it from the workspace library.

## Variables

Create project-only variables and attach global variables from the active workspace. The project sees
only its own and attached names. Variable values remain protected configuration and are omitted from
exports. See [Variables and secrets](/docs/variables).

## Code

Code edits the selected checkout's project files and exposes compile, problems, Git worktrees, and
project-scoped terminals. Compile refreshes source-owned signatures and validates workflows; it does
not rewrite arbitrary implementation logic. A terminal can be a separate scratch container, so use
the project APIs or editor for durable project changes and verify the saved revision afterward.

## Documentation

Documentation manages ordinary project files in supported text formats. Source, preview, and split
modes share one revision-checked draft. If the saved file changed, compare or download your draft
before explicitly replacing it. These files travel with the project and can be committed to Git;
they are not Design Docs and are never automatically published.

---

# Connect Octonode

> Connect your application, terminal, or AI assistant to an Octonode project.

Source: /docs/connections

Choose the connection that matches what you want to do. An access token authorizes
API requests; the SDK defines executable nodes; MCP gives an AI assistant tools.
You can use them together, but they serve different purposes.

## Choose your integration

| You want to…                                  | Use                                 | Start here                                                   |
| --------------------------------------------- | ----------------------------------- | ------------------------------------------------------------ |
| Call Octonode from a backend or script        | HTTP API and an access token        | [Access tokens and API calls](/docs/access-tokens)           |
| Build and run workflows on your machine       | Octonode CLI                        | [CLI reference](/docs/cli)                                   |
| Write low-level executable TypeScript nodes   | `@octonode/plugin-runtime`          | [TypeScript plugin runtime](/docs/typescript-sdk)            |
| Let an AI assistant inspect or edit a project | MCP and a scoped project key        | [MCP setup](/docs/mcp)                                       |
| Work with an LLM inside Studio                | Assistant and a provider connection | [AI assistants and skills](/docs/ai-and-skills)              |
| Package nodes and service integrations        | Workflow plugins                    | [Nodes and plugins](/docs/plugins)                           |
| Publish a workspace app with its own page     | Octonode Apps                       | [Create an Octonode app](/docs/apps)                         |
| Teach an assistant a repeatable process       | A project `SKILL.md`                | [Create a skill](/docs/ai-and-skills#create-a-project-skill) |

## How the pieces connect

```text
Your backend ─── access token + HTTP ───┐
                                      ├── Octonode API ── your project
AI assistant ── MCP + project key ─────┘
     │
     └── skills: instructions for using those tools

Local terminal ── CLI ── project manifest ── workflow runtime
                                               │
                                      nodes built with the SDK
                                               │
                                     plugin service credentials
```

The CLI's `run` and `invoke` commands execute the local manifest. Setting API
environment variables configures API-backed MCP tools; it does not turn those
local CLI commands into remote commands.

## Keep the three credentials separate

**An Octonode access token** authorizes requests to your Octonode deployment. Its
scope controls which workspaces, projects, and actions are available.

**An LLM provider credential** authorizes model usage, such as a Claude connection.
It does not grant access to your Octonode project. A local AI client needs its own
provider setup as well as the Octonode MCP connection.

**A plugin connection credential** belongs to a service used by a workflow, such
as a CRM. Configure it for the project that executes the workflow. It is not a
replacement for either credential above.

## A practical setup order

1. Open the correct workspace and project in Studio.
2. Create a key with the actions your integration needs. Begin with
   `projects:read`; add `projects:write` for edits and `workflows:run` for execution.
3. Verify a read-only [API request](/docs/access-tokens#verify-your-connection).
4. Configure [MCP](/docs/mcp) if an assistant will use the project.
5. Add the relevant [skill](/docs/ai-and-skills) and
   [plugins](/docs/plugins), then validate before running.

These pages describe public product behavior and use placeholder credentials.
Private workspace files, internal runbooks, and account secrets are not part of
the Playbook.

---

# Access tokens and API calls

> Create the right key, scope it to your project, and verify an authenticated request.

Source: /docs/access-tokens

Use a bearer token when a backend, script, or MCP client needs to call Octonode
without a browser session. Keep private tokens on the server or in your local
credential environment.

## Choose a token

| Credential            | Intended use                           | Boundary                                                       |
| --------------------- | -------------------------------------- | -------------------------------------------------------------- |
| Personal access token | Scripts acting as you                  | Your current account permissions, limited by token scopes      |
| Service token         | A workspace integration                | Bound workspace and scopes; cannot exceed its creator's access |
| Project API key       | A project integration or agent         | Selected project, scopes, and expiry                           |
| Public browser token  | Intentionally public data in a website | `data:read` with exact allowed HTTPS origins                   |

Public browser tokens are visible to visitors. Allowed origins help control browser
usage, but an HTTP client can forge an Origin header. Do not use public tokens to
protect confidential data; keep those requests behind a backend with a private key.

## Create and store a key

For personal, service, and public tokens, open **Settings → Access tokens** in
Studio, choose the token type, and give it a recognizable name. Service and public
tokens use a workspace; public tokens also need exact origins such as
`https://app.example.com`, without a trailing slash or wildcard.

For project access, use the project's **API keys** settings. Choose the actions and
expiry your integration requires. Creating workspace or project service credentials
requires permission to manage agents (`agents:manage`).

Copy the secret when it is created: the token list shows its identifying prefix,
not the complete secret. Save it in a secret manager or a local environment file
excluded from version control. Do not paste it into an assistant prompt or a public
client bundle. Revoke a lost or exposed key and create a replacement.

Token management requires a signed-in session; an existing API token cannot mint
another token. An account service must be available for these settings. A local
deployment without one can report `503` for token management.

## Select permissions

| Action           | Enables                                                     |
| ---------------- | ----------------------------------------------------------- |
| `projects:read`  | Inspect project files, nodes, and workflows                 |
| `projects:write` | Edit source and workflow structure; compile and synchronize |
| `workflows:run`  | Execute and cancel workflows                                |

Grant only the actions needed by the integration. A prompt asking an agent to
"only read" is useful guidance, but a read-only key enforces the boundary.
Other API features may require additional action scopes.

## Verify your connection

Make these values available in your shell's environment. Replace the example
workspace and project IDs with the values from your project settings.
`OCTONODE_API_TOKEN` must hold the private key you saved; the commands below never
print it.

```bash
export OCTONODE_API_URL="http://localhost:4000"
export OCTONODE_WORKSPACE="user:YOUR_USER_ID"
export OCTONODE_PROJECT="YOUR_PROJECT_ID"
```

Use the actual API origin for a hosted deployment, including `https://`. The base
URL excludes `/api`. Workspace values have the form `user:ID`, `org:ID`, or
`team:ID`. The Playbook preview on port 4200 is a documentation site, not your API.

```bash
curl --fail-with-body --get \
  "$OCTONODE_API_URL/api/projects/$OCTONODE_PROJECT/settings" \
  --data-urlencode "workspace=$OCTONODE_WORKSPACE" \
  -H "Authorization: Bearer $OCTONODE_API_TOKEN"
```

A successful response is JSON for the selected project's settings. This is a
read-only check. Include the explicit workspace on scoped API requests.

## Call from a Node.js backend

This standalone example uses Node.js 24's built-in `fetch`. Save it as
`check-connection.mjs` and run `node check-connection.mjs` in the same environment.

```js
const { OCTONODE_API_URL, OCTONODE_API_TOKEN, OCTONODE_WORKSPACE, OCTONODE_PROJECT } = process.env;
if (!OCTONODE_API_URL || !OCTONODE_API_TOKEN || !OCTONODE_WORKSPACE || !OCTONODE_PROJECT) {
  throw new Error("Set the four OCTONODE connection variables first");
}
const url = new URL(`/api/projects/${encodeURIComponent(OCTONODE_PROJECT)}/settings`, OCTONODE_API_URL);
url.searchParams.set("workspace", OCTONODE_WORKSPACE);
const response = await fetch(url, {
  headers: { Authorization: `Bearer ${OCTONODE_API_TOKEN}` },
  redirect: "error",
});
if (!response.ok) throw new Error(`Octonode returned HTTP ${response.status}`);
console.log(await response.json());
```

The node-authoring SDK does not provide account login. Use the HTTP API for
remote requests and the [TypeScript SDK](/docs/typescript-sdk) to implement nodes.
For workflow execution requests, continue with
[inputs and HTTP calls](/docs/workflow-inputs-and-triggers).

## Diagnose authentication failures

- **401:** the key is missing, expired, revoked, or belongs to another deployment.
- **403:** check the action scopes, current workspace membership, and project binding.
- **404:** check the API origin, route, and project ID. Confirm that the project
  is visible in the selected workspace.
- **HTML instead of JSON:** the URL may point to the documentation site or a
  frontend fallback instead of the API.

When rotating a key, update every consumer, verify a read, then revoke the old key.

---

# MCP setup

> Give an AI client scoped tools to inspect, edit, validate, and run Octonode workflows.

Source: /docs/mcp

Octonode's Model Context Protocol (MCP) server exposes tools that an AI client can
discover and call. The client supplies the model; Octonode supplies project tools.
The standard project connection is the hosted Streamable HTTP endpoint at
`https://mcp.octonode.dev/mcp`. Otto already has this connection built in.

## Before you connect

You need an Octonode access token, a workspace ID, at least one project ID, and an MCP client that
supports Streamable HTTP. Configure the client's model or provider account separately.

First verify your [access token and API connection](/docs/access-tokens). A workspace or project
header selects context but does not grant permission beyond that token.

## Connect a project

The `octonodes` CLI from the Octonode devtools repository generates scoped configuration without
copying a saved token into Codex config:

```bash
octonodes login
octonodes connect codex --workspace org:WORKSPACE_ID --project PROJECT_ID
octonodes connect claude --workspace org:WORKSPACE_ID --project PROJECT_ID
```

Copy the Codex command's output into `~/.codex/config.toml`. It uses a local header helper backed by
the saved login. The Claude command prints a `claude mcp add-json` command; export `OCTONODE_TOKEN`
in Claude's environment before running it. Repeat `--project` for a multi-project allow-list and add
`--worktree WORKTREE_ID` only when targeting a managed checkout.

Clients configured directly must send these HTTP headers:

| Header                 | Value                             |
| ---------------------- | --------------------------------- |
| `Authorization`        | `Bearer YOUR_OCTONODE_TOKEN`      |
| `x-octonode-workspace` | `user:ID`, `org:ID`, or `team:ID` |
| `x-octonode-project`   | Default project ID                |
| `x-octonode-projects`  | JSON array of allowed project IDs |
| `x-octonode-worktree`  | Optional managed checkout ID      |

Use your client's secret or environment configuration when available. Never commit a token or a
generated authorization header. Restart or reconnect the MCP server after changing its scope.

## Verify tools before making changes

Open the client's MCP tool list, then ask it to call `project_context` and
`project_workflows`. You should see the files and workflows of the intended
project. If either points to the wrong project, correct the configuration before
allowing edits.

| Task                      | Tools                                                          | Typical scope    |
| ------------------------- | -------------------------------------------------------------- | ---------------- |
| Inspect source            | `project_context`, `project_file_read`, `project_source_index` | `projects:read`  |
| Inspect a workflow        | `project_workflows`, `project_workflow_graph`                  | `projects:read`  |
| Edit a file               | `project_file_create`, `project_file_write`                    | `projects:write` |
| Add nodes and connections | `project_native_materialize`, `project_workflow_save`          | `projects:write` |
| Compile after edits       | `project_validate`                                             | `projects:write` |
| Execute or cancel         | `project_workflow_run`, `project_workflow_cancel`              | `workflows:run`  |
| Inspect execution history | `project_runs`, `project_run`                                  | `projects:read`  |

File and graph writes use the revision returned by a preceding read. On a revision
conflict, re-read and reconcile changes before retrying. A workflow run can invoke
external services; enable execution only for an integration that needs it.

## Give the assistant a precise first task

```text
Use the Octonode MCP connection to inspect the selected project.
Call project_context and project_workflows, then read the relevant source.
Report the existing workflow IDs, inputs, outputs, and missing configuration.
Do not edit files or run workflows during this inspection.
Never include credentials in your response.
```

For a build task and reusable project instructions, continue with
[AI assistants and skills](/docs/ai-and-skills).

## Local plugin authoring

`octonode mcp` remains a separate stdio adapter for clients that need local plugin-directory tools.
It is not Otto's runtime and it is not a second hosted MCP server. A minimal local configuration is:

```json
{
  "mcpServers": {
    "octonode": { "command": "octonode", "args": ["mcp"] }
  }
}
```

The local tool catalog includes `create_plugin`, `add_node`, `update_plugin`,
`validate_plugin`, `list_plugins`, `publish_plugin`, `run_workflow`, and
`describe_node`. Use explicit project or plugin paths supported by each tool.
Publishing requires a registry connection and is a separate action from creating
or validating a plugin. Its API-backed project tools still require
`OCTONODE_API_URL`, `OCTONODE_API_TOKEN`, `OCTONODE_WORKSPACE`, and `OCTONODE_PROJECT`
in the local server process.

## Install the external client plugin

The Octonode Connect AI-client plugin bundles the connection skill and hosted MCP dependency. After
its marketplace entry is registered in `octonode-devtools`, add that marketplace with:

```bash
codex plugin marketplace add nivdoron1/octonode-devtools \
  --sparse .agents/plugins \
  --sparse connect-skill-plugin
codex plugin marketplace list
```

Install or enable **Octonode Connect** in the client plugin directory, then run `octonodes connect`
to supply authentication and project scope. This does not install an Octonode workflow plugin.

## Resources and connection problems

Clients can use `resources/list` and `resources/read` to discover the bundled
code-author guidance at `octonode://guidance/code-author`. Resource text gives the
assistant instructions; it does not execute tools or grant access.

- **Header helper not found:** install `octonodes` on the client's PATH or use its absolute path in
  `http_headers_helper`.
- **Process appears to wait:** the optional local `octonode mcp` command waits for protocol messages;
  it is not an interactive shell.
- **Missing workspace/project:** regenerate the client configuration with `--workspace` and
  `--project`, then reconnect.
- **Unauthorized tool call:** verify the key using the read-only API example,
  then check its project binding and required action scope.

---

# AI assistants and skills

> Connect an LLM, write an actionable prompt, and give your project reusable authoring instructions.

Source: /docs/ai-and-skills

An assistant combines a model, project tools, and instructions. The model interprets
your request; MCP tools perform authorized operations; skills describe how you want
the work done. A skill alone cannot connect to Octonode or execute a workflow.

Otto already includes the hosted Octonode MCP connection and the code-author skill. External clients
need their own connection or the Octonode Connect client plugin; they do not need Otto's runtime.

## Work in Studio

Open **Assistant** in Studio and select the workspace and project for the session.
Ask it to inspect the current project before requesting changes. Existing source,
node signatures, and workflow graphs give it concrete context.

Open **Otto connection** to choose your provider, model, and saved secret variable.
Otto's project terminal does not require Claude Code login. Configure external AI
clients in their own apps and follow [MCP setup](/docs/mcp).

## Start with a useful build prompt

This prompt gives the assistant a specific result, acceptance criteria, and an
explicit boundary for external actions. Adapt the input and expected output to
your project.

```text
Build an order-total workflow in the selected Octonode project.

First inspect the project files, existing nodes, and workflow graph through MCP.
Read the project's relevant skills and reuse existing code where possible.

Input: { "a": 2, "b": 3 }.
Behavior: add a and b, then square the sum.
Expected terminal output: { "result": 25 }.

Implement the smallest TypeScript change, with JSON-compatible inputs and outputs.
Use the latest file and graph revisions for writes. Validate after editing.
Show the changed files, final node connections, and validation result.
Do not publish, deploy, or call external services without a separate instruction.
```

To permit a test execution, follow up with: "Run this workflow once with the example
input and report its run ID and terminal node output." Its key must include
`workflows:run`. The workflow API may wrap the node output in run events or
node-keyed results; the prompt's expected object describes the terminal node.

## Create a project skill

Open **AI resources → Add → New skill** and add your instructions.
Use **Add → Upload local plugin** to upload a ZIP containing SKILL.md files and Markdown
references, or a supported plugin bundle. Imports attach to the current session when
compatible with its selected model.
Search, filter, and sort the resource table to review, attach, detach, or remove resources.
You can edit resources you own; edits keep the same ID and require the current revision.

A skill has YAML metadata followed by Markdown instructions. For example:

```markdown
---
name: workflow-review
description: Review a workflow's inputs, connections, and failure behavior before execution.
---

Read the selected workflow and the source of its nodes through Octonode MCP.
Check that every connected output is compatible with the receiving input.
Identify required environment variables by name, without reading secret values.
List external effects, retry behavior, and a small example input.
Report findings with the affected node IDs. Do not modify or execute the workflow.
```

[Download the ready-to-use `workflow-review/SKILL.md`](https://playbook.octonodes.com/skills/workflow-review/SKILL.md),
then register its instructions or use the development terminal command below.

Click a resource's name and choose **Use in this session** to include it in the session. Review
and update its instructions as the project changes. Keep credentials in Global
Variables and reference their names in MCP configuration.

## Manage resources in the development terminal

For a managed cloud project, enable **Developer mode** and open **Terminal**. The Octonode CLI is already
installed and connected to the selected project's Otto resource registry. The
terminal provides both `octonode` and `octonodes` command names.

```bash
octonodes otto resources list
octonodes otto mcp add docs --url https://example.com/mcp --variable MCP_KEY
octonodes otto skills add workflow-review --file ./SKILL.md
octonodes otto plugins add review-bundle --file ./resource.json
octonodes otto resources update RESOURCE_ID --file ./registration.json
octonodes otto resources remove RESOURCE_ID
```

Plugin JSON contains `skills`, `connectors`, and optional text `files`, matching
the resource table's reviewed contents. New CLI resources load automatically in
this project's sessions; add `--manual` to attach them individually. Use
`--id UUID` when retrying a registration. The terminal's resource connection
expires after 15 minutes; reopening it refreshes the connection.

Remote computer terminals run your host's normal shell. They do not receive this
automatic Otto resource connection or show these managed cloud shortcuts.

## Skills, plugins, and MCP are different

| Item                     | What it contains                                                   | When it is used                                         |
| ------------------------ | ------------------------------------------------------------------ | ------------------------------------------------------- |
| Project skill            | Markdown instructions and references                               | The assistant follows a repeatable process              |
| MCP server               | Discoverable tools and resources                                   | The assistant reads or changes authorized project state |
| Octonode workflow plugin | Node definitions, TypeScript handlers, and connection requirements | The workflow runtime executes nodes                     |
| AI client plugin         | Client-specific skills, tools, or other extensions                 | Your AI client loads its extension package              |

Installing an AI client plugin does not automatically install an Octonode workflow
plugin. Attach workflow plugins to the target project and configure their service
connections. See [Nodes and plugins](/docs/plugins).

The Octonode Connect client plugin packages connection guidance and the hosted MCP dependency. It
does not contain the MCP implementation or install workflow nodes. Follow [MCP setup](/docs/mcp) for
authentication and project scope.

## Understand the workspace boundary

Project source edits happen through project tools. A terminal can be a separate
scratch environment; do not assume a terminal file edit changed the project's
source. Inspect the project again through MCP to confirm the result.

Terminal files can be lost when the environment is recycled. Registered resources
remain in Otto’s workspace registry and are snapshotted for each run.
Background chat does not execute shell commands or hooks simply because a skill
mentions them; the available tools and permissions determine what can run.

### Customize Otto

Open **AI resources** to manage **Skills**, **Connectors**, and **Plugins**.
Search, filter and sort the table; click a resource to review it, use it in the
current session or delete it. Owners can edit resources and toggle **Enabled**.
Disabling a resource excludes it from future runs without deleting it.

Choose **Add → Upload local plugin** to drop a ZIP containing skills or a Claude
plugin. **Browse marketplace** loads Claude’s public catalog automatically.
Adding a marketplace plugin registers it; click its name and choose **Use in this
session** when you want to attach it.
Otto checks source and runtime compatibility when you add a plugin; some plugins
need login, transports or features that are not supported yet. Provider secrets
stay in Global Variables.

When you connect a project, Otto reads `.agents`, `AGENTS.md`, and `CLAUDE.md` in
the background and shows the files it read. It also discovers `.claude/skills`.
Guidance is reread from the selected checkout before every run. Background reads
include up to 32 files and 16,000 UTF-8 bytes per project; all selected projects
share a 16,000-byte run context budget. Skipped files can be read through authorized
project tools. Project guidance cannot grant new permissions.

---

# TypeScript plugin runtime

> Build runnable nodes and reusable plugins with @octonode/plugin-runtime.

Source: /docs/typescript-sdk

`@octonode/plugin-runtime` is the lower-level package that connects TypeScript handlers to the Octonode workflow runtime. The public `@octonodes/sdk` package in octonode-devtools owns cloud API access and typed plugin authoring.
It describes node contracts, dispatches invocations, and validates inputs and
outputs using its supported schema keywords. It supports Node.js 20.19+ and 22.12+
(`^20.19.0 || >=22.12.0`). Your handler code and dependencies must also support
the chosen runtime. The engine's `octonode` CLI used below requires Node 24.

## Start with a runnable plugin

With the Octonode CLI installed:

```bash
octonode plugin create my-tools --lang typescript
cd my-tools
npm install
npm run build
npm test
```

The scaffold includes a package manifest, TypeScript build configuration,
`octonode.yml`, source, and a runnable IPC test. In an existing package, add
`@octonode/plugin-runtime` as a dependency with your package manager. Keep the SDK and CLI
versions compatible with your deployment.

## Define a node contract

This complete `octonode.yml` declares a single `greet` node. Its command names the
compiled entry point and the node to invoke.

```yaml
apiVersion: octonode.dev/settings/v1
plugin:
  id: 7e780cd7-51bc-4ea8-b6bb-849b5bdc272d
  name: My tools
  version: 0.1.0
  scope: [user]
  nodes:
    - id: df10592b-8eca-42d8-97f9-7517e1091b27
      label: Greet someone
      description: Return a greeting.
      command: node dist/index.js df10592b-8eca-42d8-97f9-7517e1091b27
      language: typescript
      inputs:
        type: object
        properties:
          name: { type: string }
        required: [name]
      defaults: { name: world }
      outputs:
        type: object
        properties:
          message: { type: string }
        required: [message]
```

`inputs` and `outputs` define the visible ports. `defaults` supplies default
input values. Keep IDs stable: workflows use them to identify nodes.

## Implement the handler

For the scaffold's CommonJS build, put this in `src/index.ts`:

```ts
import { join } from "node:path";
import { definePlugin, loadPluginDefinition, startPlugin } from "@octonode/plugin-runtime";

startPlugin(
  definePlugin(loadPluginDefinition(join(__dirname, "..")), {
    "df10592b-8eca-42d8-97f9-7517e1091b27": async ({ name }: { name: string }) => ({ message: `Hello, ${name}!` }),
  }),
);
```

`loadPluginDefinition` reads the root settings file. `definePlugin` pairs each
declared node with a handler. `startPlugin` selects the node from the command,
validates the invocation, and writes the protocol result.

Handlers receive JSON-compatible input and return JSON-compatible output. Convert
dates to strings and adapt streams, class instances, or binary data explicitly.
Use `console.error` for diagnostics: stdout is reserved for the runtime protocol.

## Build and test the node

```bash
npm run build
octonode run-node "node dist/index.js df10592b-8eca-42d8-97f9-7517e1091b27" --describe
octonode run-node "node dist/index.js df10592b-8eca-42d8-97f9-7517e1091b27" --input '{"name":"Ada"}'
```

The invocation returns a result containing `{"message":"Hello, Ada!"}`. The
describe command shows the node contract without executing the handler.
Keep your scaffold's test expectations aligned with the contract if you change it.

From the destination workflow project, install the built plugin:

```bash
octonode plugin install /absolute/path/to/my-tools --project
```

Its node is addressed as `7e780cd7-51bc-4ea8-b6bb-849b5bdc272d/df10592b-8eca-42d8-97f9-7517e1091b27`. Build after source edits so the configured
command executes current JavaScript.

## Declare a service connection

For a plugin that calls a CRM, add these fields **under `plugin`** in the manifest:

```yaml
permissions:
  - { resource: secrets, access: read }
connections:
  crm:
    label: CRM account
    fields:
      CRM_TOKEN: { label: API token, secret: true, required: true }
```

Add `connections: [crm]` to each node that requires that connection. The consumer
supplies `CRM_TOKEN` in its execution environment; read it inside the handler.
Required credentials are checked before the handler runs. The manifest declares
the requirement, never the credential value. This token belongs to the CRM;
an Octonode API token does not authenticate to that service.

## Other runtime entry points

Existing single-node integrations can use `defineNode` and `start`. `NodeError`
represents an explicit node failure; `NodeContext` describes runtime context.
The runtime also exports `PluginManifest`, `PluginNode`, and `PluginConnection`
schemas and types for programmatic validation.

Use the plugin scaffold when starting a reusable integration, and see
[Nodes and plugins](/docs/plugins) for marketplace attachment and generated adapters.

## Installed app SDKs

This page describes the workflow plugin runtime. For `workspace.block` and
`app.page` contributions, use the [app SDK reference](/docs/apps/sdk), which
separates browser UI, the installation bridge, hosted backend verification,
and the general cloud API client.

---

# CLI reference

> Create, inspect, validate, and run local Octonode workflows from your terminal.

Source: /docs/cli

The CLI reads your local project manifest and executes its configured node
commands. Use Node.js 24 and a compatible Octonode CLI build.

## Check your executable

```bash
octonode --version
octonode --help
```

In a built source checkout, the executable is
`packages/cli/dist/index.js`. You can run it directly with Node:

```bash
node /absolute/path/to/octonode/packages/cli/dist/index.js --help
```

For an MCP client using this checkout, set `command` to the absolute Node executable
and `args` to `["/absolute/path/to/octonode/packages/cli/dist/index.js", "mcp"]`.
The source checkout must already have its dependencies installed and packages built.
The [first workflow walkthrough](/docs/first-workflow) uses this setup.

## Everyday commands

The examples use `.octonode.yaml` explicitly. Run them from your project directory.

| Task                          | Command                                                    |
| ----------------------------- | ---------------------------------------------------------- |
| Create a manifest             | `octonode init .octonode.yaml --name orders`               |
| List built-in nodes           | `octonode add --list`                                      |
| Add an editable node          | `octonode add math.add --id add-1 --config .octonode.yaml` |
| Refresh discovered signatures | `octonode scan --config .octonode.yaml`                    |
| Check drift without writing   | `octonode scan --check --config .octonode.yaml`            |
| Validate the manifest         | `octonode validate --config .octonode.yaml`                |
| Inspect human-owned settings  | `octonode settings show`                                   |
| Print the workflow graph      | `octonode graph total --config .octonode.yaml`             |
| Start API and built Studio    | `octonode serve --config .octonode.yaml`                   |
| Start the MCP stdio server    | `octonode mcp`                                             |

`scan` discovers node contracts by invoking their describe protocol; ensure the
configured commands can execute. `validate` checks the configuration but does not
prove an external service is reachable or that its credentials are correct.

## Invoke a node or run a workflow

After following the first-workflow setup:

```bash
octonode invoke add-1 --config .octonode.yaml --input '{"a":2,"b":3}'
octonode run total --config .octonode.yaml --input '{"a":2,"b":3}'
```

`invoke` runs one registered node; `run` follows the workflow's connections.
Use `--input-file input.json` instead of `--input` for a larger JSON input, and
`--env NAME` to select a configured environment. Results are written to stdout;
diagnostic messages go to stderr.

## Record and replay

```bash
octonode run total --config .octonode.yaml --input '{"a":2,"b":3}' --record run.json
octonode replay run.json square-1 --config .octonode.yaml
```

A recording captures node inputs for inspection. Treat recordings according to
the sensitivity of their data. Replay invokes the selected node again and may
repeat external effects such as a write or notification.

## Connect other tools

`serve` defaults to `http://localhost:4000` and serves Studio when its build is
available. `--port` selects a different port. Use
[access tokens and API calls](/docs/access-tokens) to connect a backend, and
[MCP setup](/docs/mcp) for an AI client.

API connection variables configure API-backed MCP tools. Local `run`, `invoke`,
and `scan` continue to use your local manifest.

For reusable integrations, continue with [TypeScript SDK](/docs/typescript-sdk)
and [Nodes and plugins](/docs/plugins).

## App authoring CLI

The separate `octonodes` developer CLI creates and publishes marketplace apps.
Follow [Install the developer CLI](/docs/installation) for npm, Homebrew, Windows,
Linux and other installation options, then [Create your first app](/docs/apps/quickstart). The `octonode`
engine CLI on this page builds and runs local workflow projects.

---

# Build Octonode apps

> Choose an extension-only or self-hosted app, then build, test, publish, and install it.

Source: /docs/apps

An Octonode app is a versioned set of contributions installed into a workspace. A
`workspace.block` appears on workspace home. An `app.page` opens from Apps. You can
ship either without a backend, or connect a page and backend hosted on your own HTTPS
origin. An app never needs a dashboard merely to supply a block.

| Goal                                                | Start here                                     | Hosting                               |
| --------------------------------------------------- | ---------------------------------------------- | ------------------------------------- |
| Workspace notice, formatter UI, or other block      | [Create your first app](/docs/apps/quickstart) | Octonode stores the published bundle  |
| Page inside Apps, with no backend                   | [Add a contribution](/docs/apps/configuration) | Octonode stores the published bundle  |
| Connected page or backend, such as inventory labels | [Host a full app](/docs/apps/hosting)          | You deploy its Node output and assets |
| Reusable workflow node                              | [Nodes and plugins](/docs/plugins)             | Plugin runtime, separate from apps    |

## Follow the app path

1. [Create and preview an app](/docs/apps/quickstart) with `octonodes app create`.
2. [Configure the project](/docs/apps/configuration): one `octonode.app.json` descriptor
   and optional `workspace.block`, `app.page`, or backend.
3. [Use the app SDK](/docs/apps/sdk) for UI, installed-project actions, and verified
   backend sessions. The general `@octonodes/sdk` client is for separately authorized
   integrations, not an installed app's session.
4. [Choose hosting and deploy](/docs/apps/hosting) if the app has a web backend.
5. [Publish, install, and update](/docs/apps/publishing) through Partner and Studio.

These guides apply to deployments with Apps enabled and the required app migrations
applied. The feature branch does not itself migrate an installation.

The supported private app path has consent, pinned releases, publisher analytics,
settings, and lifecycle controls. Public app review/moderation, billing, background
app identities, webhook delivery, automatic installation updates, and managed backend
hosting are separate capabilities. A development tunnel previews your local app; it
is not a production host.

Shopify's [app structure](https://shopify.dev/docs/apps/build/cli-for-apps/app-structure)
and [extension-only app guide](https://shopify.dev/docs/apps/build/app-extensions/build-extension-only-app)
informed this sequence. Octonode's targets, permissions, configuration file, release
semantics, and hosting contract below are its own; use these guides for Octonode commands.

## App developer guides

- [Quickstart](/docs/apps/quickstart): create a full app or a static contribution.
- [Configuration](/docs/apps/configuration): source descriptor and build artifacts.
- [Permissions](/docs/apps/permissions): declared actions and selected-project consent.
- [Development](/docs/apps/development): sample data and temporary real-data access.
- [Routing](/docs/apps/routing): deep links, browser history and Studio sessions.
- [SDK](/docs/apps/sdk): browser contributions and backend access.
- [Hosting](/docs/apps/hosting): HTTPS, embedding and production runtime.
- [Publishing](/docs/apps/publishing): private releases and installation updates.
- [Troubleshooting](/docs/apps/troubleshooting): common failures and verification.

---

# Create your first app

> Generate, preview, and test a full Octonode app.

Source: /docs/apps/quickstart

Start with [Install the developer CLI](/docs/installation) to set up a supported Node version
and the `octonodes` command. Use matching Octonode CLI and UI SDK versions.

```sh
npx @octonodes/cli app create inventory
cd inventory
npm install
npm test
npm run dev
```

The default is a full Vite app with a hosted page and Node backend. The CLI opens a development preview. Use `--use-localhost` for local work without a tunnel. The generated page verifies its Octonode workspace session before rendering and registers a Projects route in Studio's app sidebar.

The scaffold includes `installConfig.hoistingLimits: workspaces` so Yarn 4 workspaces keep build dependencies inside the app. In a Yarn workspace, run `yarn install` at its root, then `yarn workspace inventory test`.

## Preview in Studio

```sh
octonodes login
octonodes app dev --workspace user:<your-user-id>
```

Studio shows the hosted page under App. Contributions appear in a separate view when declared. A preview starts with no project grants. Follow [development access](/docs/apps/development) to test selected real projects.

## Add a contribution

```sh
octonodes app extension add notice --target workspace.block
```

A full app does not need duplicate `app.page` or workspace blocks. For a static block with no backend, generate `octonodes app create notice --template extension`. Extension-only apps currently request no data permissions.

Full apps also support `--platform plain` and `--platform next`. Start editing `src/server.ts` and, for React templates, `src/web/App.tsx`.

## Host your app

Before others can use a published full app, host its page and backend at a
permanent public HTTPS URL. Cloudflare and Vercel offer simple hosting options
with free plans for eligible usage. See [hosting](/docs/apps/hosting) for runtime
requirements, build/output settings, environment variables, and complete
[Cloudflare Worker](/docs/apps/hosting#deploy-to-cloudflare-workers) and
[Vercel](/docs/apps/hosting#deploy-to-vercel) integration recipes. Publishing alone does not deploy your app;
extension-only apps do not require a separate host.

Next: [configuration](/docs/apps/configuration), [permissions](/docs/apps/permissions), [routing](/docs/apps/routing), and [hosting](/docs/apps/hosting).

---

# App project and configuration

> Define app identity, extensions, settings, permissions, and development options.

Source: /docs/apps/configuration

Octonode CLI app projects use one source descriptor, `octonode.app.json`.
Shopify uses a TOML app file and separate extension files; Octonode currently uses
JSON and declares entries together. `octonode.toml` and `octonode.app.toml` are not
read by the app CLI.

```text
workspace-notice/
  octonode.app.json
  src/extensions/notice.tsx
  tests/app.test.cjs
  package.json
  tsconfig.json
```

The default scaffold is a full Vite app with `web.entry` and an empty `extensions` list.
The explicit `--template extension` scaffold starts as this static workspace block:

```json
{
  "apiVersion": "octonode.app/v1",
  "id": "workspace-notice",
  "name": "workspace-notice",
  "version": "0.1.0",
  "settings": [{ "id": "message", "label": "Message", "defaultValue": "Welcome" }],
  "extensions": [{ "id": "notice", "target": "workspace.block", "entry": "src/extensions/notice.tsx" }]
}
```

`id` is the source identity; the Partner publication also receives an immutable
app ID. Increment the semantic `version` for each release. Extension IDs must be
unique lowercase slugs, and entries must be JavaScript or TypeScript files under
`src/`. Settings are shared strings configured by the installing workspace. They
are not secret storage. The CLI builds browser IIFEs and includes integrity hashes;
it does not accept hand-written bundle hashes in the source descriptor.

## Add a page or block

```sh
octonodes app extension add overview --target app.page
octonodes app extension add summary --target workspace.block
npm test
```

The command adds an entry and starter file. A page opens from **Apps → Installed**;
a block appears on workspace home. Apps with only blocks remain available under
**Apps → Installed** without requiring a dashboard. A page and block may coexist.
The CLI's extension-only template can ship a page without a backend.

## Add a backend

```sh
octonodes app create inventory-labels --template full
```

The full template adds `src/server.ts` and `web.entry`. Its backend is a default
exported Fetch API handler. Set a permanent HTTPS origin before a release:

```json
{
  "apiVersion": "octonode.app/v1",
  "id": "inventory-labels",
  "name": "Inventory labels",
  "version": "0.1.0",
  "web": {
    "entry": "src/server.ts",
    "applicationUrl": "https://labels.example.com",
    "requestedActions": ["projects:read", "data:read"]
  },
  "extensions": [{ "id": "notice", "target": "workspace.block", "entry": "src/extensions/notice.tsx" }]
}
```

The only supported actions are `projects:read`, `data:read`, `data:write`, and
`workflows:run`. Request only what the app uses; installers approve the actions
and specific projects. The CLI's extension-only releases currently request no
project actions. Full apps configure their own private settings in their backend;
shared manifest `settings` cannot be combined with `web` in the CLI source file.
`web.applicationUrl` is an HTTPS **origin**, with no path, query, fragment, or
embedded credentials. You may pass `--app-url https://labels.example.com` to a
single build instead of writing the URL in the descriptor; publishing rebuilds, so
save the URL in the descriptor before `app publish`.

See [the app SDK](/docs/apps/sdk) for code and [hosting](/docs/apps/hosting)
for the production output. The source descriptor is validated before each build;
compiled registration artifacts use a different versioned manifest contract.

---

# Permissions and consent

> Declare the actions your app needs and request access to selected projects.

Source: /docs/apps/permissions

A full app declares `web.requestedActions` in `octonode.app.json`. A workspace administrator reviews and accepts those permissions when installing the app into a workspace. Project access is optional: an app can be installed and opened without any projects or grants. Project operations require explicit project/action grants, which an administrator can add later by updating consent.

| Action          | Allows                                              |
| --------------- | --------------------------------------------------- |
| `projects:read` | Read selected project names and IDs                 |
| `data:read`     | Read tables and rows in selected projects           |
| `data:write`    | Insert, update and delete rows in selected projects |
| `workflows:run` | Run workflows in selected projects                  |

A project directory only needs `projects:read`. A product-table browser also needs `data:read`. Data grants cover a project's tables; they are not limited to one product table. Project definition writes are not currently an app capability. Read and write actions are explicit; do not assume one grants the other.

```json
{
  "web": {
    "entry": "src/server.ts",
    "platform": "vite",
    "requestedActions": ["projects:read"]
  }
}
```

This is the `web` portion of the descriptor, not a complete manifest.

## Selected projects

Call the result **Granted projects**. New projects are excluded until an administrator changes consent. The limit is 100 action/project pairs, so two actions on one project consume two grants.

Every data call checks the active installation, pinned release, current user membership, granted action, project and session. Scope increases require renewed consent. Disabling, uninstalling or revoking access stops subsequent calls.

A framed page has no authority by itself. [Development previews](/docs/apps/development) require separate, temporary consent. Extension-only apps remain static and cannot request these actions.

---

# Development previews

> Preview a hosted app and explicitly consent to temporary real project access.

Source: /docs/apps/development

Start `octonodes app dev --workspace user:<id>` after signing in. Studio shows the full hosted page, with optional contribution previews. The development session belongs to its publisher and starts with no project grants.

The generated React app shows its workspace page only after the backend verifies the preview session. With no project grants, the Projects route shows an empty state. Direct visits to its public host show no workspace content.

## Real project access

Declare the required actions, then choose **Review development access** in Studio. The consent dialog identifies the host and selected projects. The signed-in publisher must also be a workspace administrator. Review the destination: the live developer server receives these selected data, and code edits take effect immediately.

Consent expires after one hour. The session expires after ten minutes without a heartbeat. Heartbeats keep the session alive but cannot extend the consent deadline. **Revoke development access** removes access immediately. Changing the app origin or requested scopes clears consent. Stopping the CLI closes its session; a disconnected process expires automatically.

Production installation needs its own consent. Never publish a temporary tunnel URL as the release host.

## Session renewal

The hosted SDK receives session updates from Studio without reloading the app. A normal heartbeat retains the development bearer. Installed sessions are replaced before expiry. The SDK keeps bearers in memory and removes launch credentials from the URL fragment.

Open the app from Studio to receive and renew its session. See [routing](/docs/apps/routing) for integrating the bridge with your app.

---

# Routing and Studio embedding

> Use browser history in your app and preserve deep links inside Studio.

Source: /docs/apps/routing

Initialize `connectHostedApp()` from `@octonodes/ui-extensions/app` once in a browser effect and dispose it when the app unmounts. It works with browser history, React Router and other routers that use `pushState`, `replaceState` and `popstate`.

```ts
import { connectHostedApp } from "@octonodes/ui-extensions/app";

const app = connectHostedApp();
const unsubscribe = app.subscribe(() => {
  const { status, path } = app.getSnapshot();
  // Update your page state when the session or route changes.
});
app.navigate("/products?sort=name");
// After getSnapshot().status is ready:
const response = await app.fetch("/api/products");
// On unmount:
unsubscribe();
app.dispose();
```

The route is `/products?sort=name` on your own app host. Studio mirrors it into `?appPath=%2Fproducts%3Fsort%3Dname` on `/studio/apps/<installation-id>` or the development route. Studio preserves its own workspace parameters. Refresh, copied links, and back/forward navigation restore the app path. The app never navigates the Studio shell directly.

`navigate(path, { replace: true })` replaces history. Routes must start with `/`; external URLs and protocol-relative paths are rejected. Ordinary links that reload a document must be supported by your web server. The generated Vite server falls back to its index for HTML navigation while preserving API/asset 404 responses. Next exports must provide the pages they intend to serve.

## Trusted handoff

Studio and the hosted app exchange versioned messages bound to the expected origin, frame window and channel. The bearer is delivered only to the registered app origin. The SDK sends it only to the app's own backend and does not follow redirects. It never stores the bearer in browser storage. Non-secret embedding coordinates may survive a child refresh.

React apps can use `OctonodeAppProvider` from `@octonodes/ui-extensions/app/react`. It waits for `/api/context` to verify the workspace session before rendering children. Pass `navigation={[{ label: "Projects", path: "/projects" }]}` to show app routes in Studio's app sidebar. A direct visit without a session shows only an access message. The app's backend verifies incoming tokens with `connectAppServer`.

See [hosting](/docs/apps/hosting) for embedding headers and sandbox behavior.

---

# App SDK reference

> Use the UI extension, installed-app bridge, hosted backend helper, and general API SDK correctly.

Source: /docs/apps/sdk

| Import                                | Where it runs                         | Purpose                                                            |
| ------------------------------------- | ------------------------------------- | ------------------------------------------------------------------ |
| `@octonodes/ui-extensions/react`      | Installed browser extension           | Declare `workspace.block` or `app.page`, render host controls      |
| `@octonodes/ui-extensions`            | Installed browser extension           | Read current app session and shared configuration                  |
| `@octonodes/ui-extensions/app`        | Browser extension or hosted page      | Use the extension bridge or initialize hosted routing and sessions |
| `@octonodes/ui-extensions/app/react`  | Hosted React client                   | Verify workspace access before rendering; use the hosted bridge    |
| `@octonodes/ui-extensions/app/server` | Your hosted backend                   | Verify an installation bearer, then use consented project actions  |
| `@octonodes/sdk`                      | Separately authorized backend or tool | Call the general cloud API with a personal/service token           |

Install `@octonodes/ui-extensions` for app code. `octonodes app create` includes it
and the CLI. The engine owns the UI SDK contract; the published package is synced
from the engine. `@octonodes/sdk/plugins` defines workflow plugins and is not the
app extension entry point.

## UI contribution

Put this in `src/extensions/notice.tsx` and declare the same target in
`octonode.app.json`:

```tsx
import { getAppSession } from "@octonodes/ui-extensions";
import { defineExtension, Section } from "@octonodes/ui-extensions/react";

export default defineExtension("workspace.block", function Notice() {
  const message = getAppSession().configuration.message ?? "Welcome";
  return <Section title="Workspace notice">{message}</Section>;
});
```

The CLI calls `startExtension` when it bundles a declared entry. When bundling
manually, call `startExtension(defineExtension("app.page", Component))` in the
browser entry. Available app controls include `Section`, `NodeForm`, `Button`,
and `TextField`. `InputField` belongs to node inspector extensions. Extensions
render inside an isolated iframe. No parent DOM, Octonode login token, or direct
network access is provided to an extension-only bundle.

## Consented project actions inside an installed extension

When the published app requested an action and the installer granted projects,
use the host bridge:

```ts
import { connectApp } from "@octonodes/ui-extensions/app";

const app = await connectApp();
const project = app.project ?? app.forProject(selectedProjectId);
const rows = await project.tables.rows.list("products", { limit: 20 });
const run = await project.wf.run("sync-products", { source: "app" }, { idempotencyKey: "sync-123" });
```

`app.projects` lists granted project IDs. `app.project` exists when the host
supplies a current granted project or exactly one project is granted. With
multiple grants, present a project picker and call `forProject(id)`.
`project.get`, `tables.list`, row list/insert/update/delete, and `wf.run` are
the supported operations. Row updates require `expectedVersion`; use an
`idempotencyKey` when retrying a workflow run. The host checks the installation,
actor, action, and project grant on every call. A local development preview has
no grants until an administrator approves temporary development access in Studio; production releases need separate installation consent.

## Hosted backend session

A self-hosted app uses `connectHostedApp()` or `OctonodeAppProvider` for the
trusted Studio handoff. The SDK clears launch coordinates from the fragment,
receives the current bearer from the expected Studio origin and channel, and
keeps it in memory. Use `bridge.fetch` to send it only to your own backend.
The generated full template includes this handoff and `/api/context` route. On
**every backend request** using Octonode data, verify the bearer:

```ts
import { connectAppServer } from "@octonodes/ui-extensions/app/server";

const token = request.headers.get("authorization")?.replace(/^Bearer /, "") ?? "";
const app = await connectAppServer(token, {
  appId: process.env.OCTONODE_APP_ID!,
  baseUrl: process.env.OCTONODE_API_URL!,
});
const project = app.project ?? app.forProject(selectedProjectId);
const rows = await project.tables.rows.list("products");
```

Set the registered app ID and Octonode API URL in the **server environment**,
never from browser input. The helper verifies the bearer with Octonode and rejects
a bearer for another app. Use its returned user/workspace/grants; do not trust a
workspace or project ID from a request merely because the browser supplied it.
Sessions are short lived and can be revoked; ask the user to reopen from Apps
when verification fails. Do not store the bearer or put it in logs. This bearer
is for app runtime endpoints, not general API access or background jobs.

## Integrate the client and server

For the generated Vite app, keep the client in `src/web/App.tsx` and API routes
in `src/server.ts`. `OctonodeAppProvider` first calls your server's
`/api/context`; a client handshake alone does not authorize workspace content.
Use `useOctonodeApp().bridge.fetch` for protected app requests. The server calls
`connectAppServer` on each request and derives workspace/project access from
its verified result. The generated `/api/projects` route demonstrates this flow.

Use the [complete hosting instructions](/docs/apps/hosting#client-and-server-integration)
for the build command, public output directory, server variables, and adapters.
The [Cloudflare Worker recipe](/docs/apps/hosting#deploy-to-cloudflare-workers)
and [Vercel recipe](/docs/apps/hosting#deploy-to-vercel) keep client and API routes
on one origin. A static frontend deployment alone does not implement
`/api/context` or the app's backend.

## General cloud API SDK

`@octonodes/sdk` uses a separately supplied personal or service token. It is
useful for an independently authorized integration, but the installed app
bearer must **not** be passed to `createClient`. See [general TypeScript SDK](/docs/typescript-sdk)
and [app hosting](/docs/apps/hosting).

---

# Host and deploy an app

> Choose the extension-only or self-hosted path, then serve a full app with pinned assets.

Source: /docs/apps/hosting

| Mode               | Who serves the UI                                                | What you deploy                      | Example                                             |
| ------------------ | ---------------------------------------------------------------- | ------------------------------------ | --------------------------------------------------- |
| Extension only     | Octonode stores and serves the published bundle                  | Nothing after `app publish`          | Workspace notice or an `app.page` without a backend |
| Self-hosted        | Your HTTPS origin serves the page, backend, and extension assets | The entire `dist/web/<id>` directory | Inventory labels with a server                      |
| Development tunnel | Cloudflare Quick Tunnel points to your local server              | Nothing permanent                    | `octonodes app dev` preview                         |

There is no managed Octonode backend hosting in this release. A block-only app
does not need a page or backend. A self-hosted app can use its own external page
without an `app.page` extension; if it declares extensions, those bundle URLs
must remain available for pinned installs.

## Choose a hosting provider

To use a self-hosted app after development, deploy its page, backend, and assets
on a permanent public HTTPS host. Publishing in Octonode registers the app; it
does not host your application. Extension-only apps do not need separate hosting.

For a simple start, use [Cloudflare Workers](https://developers.cloudflare.com/workers/)
or [Vercel](https://vercel.com/docs). Both offer free plans within usage limits:
[Cloudflare Workers Free](https://developers.cloudflare.com/workers/platform/pricing/)
can serve small apps, while [Vercel Hobby](https://vercel.com/docs/plans/hobby)
is for personal, non-commercial use. Choose a plan that fits your app's usage.

Use the provider's supported runtime and deployment entry point for your backend;
the generated `start.cjs` is a Node server, not a ready-made Worker or Vercel
Function. Set `web.applicationUrl` to the permanent deployment origin and follow
the session verification, embedding headers, and pinned-asset requirements below.

## Build a full app

```sh
octonodes app create inventory-labels --template full
cd inventory-labels
npm install
```

Edit `src/server.ts` and `src/web/App.tsx`. Contributions can be added separately. The generated server has a
Fetch API handler, a sample page, and a `/api/context` endpoint using
`connectAppServer`. Set `web.applicationUrl` in `octonode.app.json` to your
permanent HTTPS origin, for example `https://labels.example.com`. Add only the
required `web.requestedActions`. Run:

```sh
npm test
npm run build
octonodes app validate dist/apps/<source-id>
```

The generated server already demonstrates the session handoff. To serve a
project-specific route, add logic like this inside its Fetch API handler:

```ts
import { connectAppServer, AppRequestError } from "@octonodes/ui-extensions/app/server";

if (new URL(request.url).pathname === "/api/project-name") {
  const bearer = request.headers.get("authorization")?.replace(/^Bearer /, "") ?? "";
  try {
    const app = await connectAppServer(bearer, {
      appId: process.env.OCTONODE_APP_ID!,
      baseUrl: process.env.OCTONODE_API_URL!,
    });
    const project = app.project;
    if (!project) return new Response("Select a granted project", { status: 400 });
    return Response.json(await project.get());
  } catch (error) {
    const status = error instanceof AppRequestError ? error.status : 502;
    return new Response(status === 401 ? "Reopen the app" : "Project access failed", { status });
  }
}
```

This route needs `projects:read` in `web.requestedActions` and an installer-approved
project. It uses the verified project from the session, not an ID in the URL.
A barcode or formatter app can add its own logic around that verified context.

Read `<source-id>` from `id` in `octonode.app.json`; the generated ID may be a UUID,
not the directory name. `npm test` builds against a development URL, so run
`npm run build` again with the saved production `web.applicationUrl` before deployment.

The build produces an immutable registration artifact under
`dist/apps/<source-id>` and standalone web output under
`dist/web/<source-id>`. The latter includes `start.cjs`, `server.cjs`,
`octonode-web.json`, and content-hashed files in `extensions/`. `start.cjs`
checks the output inventory before serving. Do not edit generated files.

## Launch on your host

1. Run `octonodes login`, then publish the first release with
   `octonodes app publish --workspace user:<your-user-id>` (or a team/org
   workspace). Save the returned registered app ID. Publication stores release
   metadata; it does not deploy or install the web output.
2. Copy the **complete** `dist/web/<source-id>` directory to a Node 20.19+ or 22.12+
   host. Configure the public origin for HTTPS and forward traffic to `PORT`.
   Set `OCTONODE_APP_ID` to the returned app ID and `OCTONODE_API_URL` to the
   Octonode API used by your Studio deployment. Start `node start.cjs` from
   that directory (or use its absolute path). Do not expose `PORT` directly
   as the permanent public URL.
3. Check that the public page and every published `/extensions/<hash>.js`
   asset respond from the configured origin. Only then invite installation
   from **Studio → Apps**. The CLI can also serve a built app locally with
   `octonodes app serve`, but a local server is not a production deployment.

The registered origin must equal the served public origin. Your hosted backend
needs to verify the short-lived `octo_app_` session on each Octonode data call.
The browser fragment is cleared immediately by the generated starter. If you
replace that page, keep the same handoff behavior. Never use the temporary
`trycloudflare.com` development URL as `web.applicationUrl` for a release.

## Client and server integration

The following deployment recipes use the default **full Vite template**. Keep
`web.platform: "vite"` and `web.entry: "src/server.ts"` in `octonode.app.json`.
These settings belong in the app project, not the Octonode monorepo.

| Part                   | Source                                | Build output                                          | Runs on                     |
| ---------------------- | ------------------------------------- | ----------------------------------------------------- | --------------------------- |
| React client           | `src/web/App.tsx`, `src/web/main.tsx` | `web-dist/`, copied into `dist/web/<source-id>/site/` | Browser                     |
| API handler            | `src/server.ts` default export        | `dist/web/<source-id>/server.cjs`                     | Your backend                |
| Node launcher          | Generated by the CLI                  | `dist/web/<source-id>/start.cjs`                      | Node 20.19+ / 22.12+ host   |
| Optional contributions | `src/extensions/*`                    | `dist/web/<source-id>/extensions/`                    | Installed extension sandbox |
| Release metadata       | `octonode.app.json`                   | `dist/apps/<source-id>/`                              | Octonode publication        |

Generated Node bundles target Node 20.19. Your backend code and external
dependencies must also support the host runtime; the build does not provide
newer Node APIs on older versions.

For Workers and Vercel, bundle the **source API handler** through the provider's
adapter below. Deploy only the static client and contributions publicly. Never
set the whole `dist/web/<source-id>` directory as a static output directory:
it also contains backend code and build records.

### What to write on the client

Keep the generated `OctonodeAppProvider` from
`@octonodes/ui-extensions/app/react` around your app. It performs the Studio
handshake and verifies `/api/context` before showing workspace content.
Inside its children, use `useOctonodeApp()` to access `bridge`, `session`, and
`workspace`. Call `bridge.fetch("/api/projects")`, or your own same-origin API
path, rather than calling the Octonode API directly. The bridge attaches the
current bearer and supports session renewal. Include `session.token` in the
request effect's dependencies and cancel obsolete requests on cleanup, as the
generated `src/web/App.tsx` does.

Register client routes through the provider's `navigation` prop. Your host must
serve the app shell for a refresh of `/projects`; missing API or JavaScript
assets must return an error rather than the shell. Do not put server credentials
in `VITE_*`, browser storage, or client code. See [routing](/docs/apps/routing)
for the bridge contract and a non-React client.

### What to write on the server

Keep `src/server.ts` as a default-exported `(request: Request) => Promise<Response>`
handler. The generated routes already implement:

- `GET /api/context`: read the bearer from `Authorization`, call
  `connectAppServer`, and return `{ workspace: app.workspace }`.
- `GET /api/projects`: verify the bearer again and load only projects granted
  for `projects:read`. No grants means an empty list, not access to all projects.

For every new route reading or writing Octonode data, call `connectAppServer`
on that request. Use the verified context's project methods, validate your
route's input, and enforce its HTTP method. Return authentication and permission
failures with their status codes; do not turn them into a successful response.
Keep workspace responses out of shared caches with `Cache-Control: no-store`.
The [SDK guide](/docs/apps/sdk#hosted-backend-session) shows the verification code.

| Server setting     | Value                                                                                       |
| ------------------ | ------------------------------------------------------------------------------------------- |
| `OCTONODE_APP_ID`  | Registered app ID returned by publication; not an installation ID or an assumed source name |
| `OCTONODE_API_URL` | HTTPS origin of the Octonode API for your Studio deployment, e.g. `https://octonodes.com`   |
| `PORT`             | Only for the standalone Node launcher; Workers and Vercel do not use it                     |

These first two values identify the app and API; they are not a personal API
token. Customer authorization comes from the short-lived installation bearer.
Store any unrelated backend secrets in the provider's server secret settings.
Keep the client, `/api/context`, and other app API routes on the same origin;
the hosted bridge refuses to send its bearer to another origin.

### Prepare the public output

Add `scripts/prepare-hosting.mjs` to the app project. It reads the real source ID
and copies only deployable public files, including retained pinned contributions:

```js
import { cpSync, mkdirSync, readFileSync, rmSync } from "node:fs";
import { join } from "node:path";

const source = JSON.parse(readFileSync("octonode.app.json", "utf8"));
const web = join("dist", "web", source.id);
rmSync("public-deploy", { recursive: true, force: true });
mkdirSync("public-deploy", { recursive: true });
cpSync(join(web, "site"), "public-deploy", { recursive: true });
cpSync(join(web, "extensions"), "public-deploy/extensions", { recursive: true });
```

Add this script alongside the existing scripts in `package.json`, and add
`public-deploy/`, `.wrangler/`, `.vercel/`, and `.dev.vars*` to `.gitignore`:

```json
{
  "scripts": {
    "build:hosting": "npm run build && node scripts/prepare-hosting.mjs"
  }
}
```

Set the permanent `web.applicationUrl`, then run `npm run build:hosting`.
`public-deploy/index.html` and its assets must exist. Keep `npm run build` as the
CLI's combined client/server/registration build; `vite build` alone omits the
backend and release metadata. Use a committed lockfile and `npm ci` in CI.

## Deploy to Cloudflare Workers

This recipe serves the Vite client and API from **one Worker origin**. It does
not run `start.cjs`. The Vite template's server uses Web APIs and
`connectAppServer`; replace any added filesystem, process-spawning, or other
unsupported backend code before using Workers. The plain template's
filesystem-served HTML is not covered by this recipe.

1. Install the deployment tool in the app project:

   ```sh
   npm install --save-dev wrangler
   ```

2. Add `src/worker.ts`:

   ```ts
   import handle from "./server";

   type Env = { ASSETS: { fetch(request: Request): Promise<Response> } };

   export default {
     async fetch(request: Request, env: Env): Promise<Response> {
       const path = new URL(request.url).pathname;
       let response: Response;
       if (path === "/api" || path.startsWith("/api/")) {
         response = await handle(request);
       } else {
         response = await env.ASSETS.fetch(request);
         const navigation =
           ["GET", "HEAD"].includes(request.method) && request.headers.get("accept")?.includes("text/html");
         if (
           response.status === 404 &&
           navigation &&
           !path.startsWith("/extensions/") &&
           !path.startsWith("/assets/") &&
           !path.split("/").pop()?.includes(".")
         ) {
           response = await env.ASSETS.fetch(new Request(new URL("/index.html", request.url), request));
         }
       }
       const headers = new Headers(response.headers);
       headers.set("Content-Security-Policy", "frame-ancestors https://octonodes.com");
       headers.set("X-Content-Type-Options", "nosniff");
       if (path === "/api" || path.startsWith("/api/")) headers.set("Cache-Control", "no-store");
       if (path.startsWith("/extensions/")) headers.set("Access-Control-Allow-Origin", "*");
       return new Response(response.body, { status: response.status, statusText: response.statusText, headers });
     },
   };
   ```

   Replace the allowed Studio origin in `frame-ancestors` if you use a custom
   deployment. The wildcard CORS header applies only to public extension assets,
   not customer API responses. Missing API and asset paths retain their 404s.

3. Add `wrangler.jsonc` at the app root:

   ```jsonc
   {
     "$schema": "./node_modules/wrangler/config-schema.json",
     "name": "inventory-labels",
     "main": "src/worker.ts",
     "compatibility_date": "2026-09-01",
     "compatibility_flags": ["nodejs_compat"],
     "assets": {
       "directory": "./public-deploy",
       "binding": "ASSETS",
       "run_worker_first": true,
       "html_handling": "none",
       "not_found_handling": "none",
     },
     "vars": {
       "OCTONODE_APP_ID": "<registered-app-id>",
       "OCTONODE_API_URL": "https://octonodes.com",
     },
   }
   ```

   Use a recent compatibility date when creating your app. With `nodejs_compat`
   and this date, Worker vars are available as `process.env`, matching the
   generated server. See [Cloudflare environment variables](https://developers.cloudflare.com/workers/configuration/environment-variables/).
   The Worker runs first to keep API routing, headers, and missing-asset behavior
   explicit. These requests consume Worker usage; review the free-plan limits.
   See [static asset configuration](https://developers.cloudflare.com/workers/static-assets/binding/).

4. Set `web.applicationUrl` to your permanent Worker URL, for example
   `https://inventory-labels.<your-account-subdomain>.workers.dev`, or your
   configured custom domain. Keep that same URL for every release. Publish the
   first release to obtain the registered ID, then replace `<registered-app-id>`
   in the Worker vars before allowing installations.

5. Build and check locally, then deploy:

   ```sh
   npm test
   npm run build:hosting
   npx wrangler types
   npx wrangler deploy --dry-run
   npx wrangler dev
   ```

   Check the public shell, API routing, and assets locally. Stop the local server,
   then run:

   ```sh
   npx wrangler login
   npx wrangler deploy
   ```

   For Git-connected Workers Builds, use root directory **the app project**,
   build command `npm run build:hosting`, and deploy command
   `npx wrangler deploy`. The public asset directory is `public-deploy`, configured
   in `wrangler.jsonc`; it is not `dist/apps` or the whole `dist/web` directory.
   Put runtime vars in `wrangler.jsonc` or the selected Worker environment, not
   only in build-time variables. Add actual secrets with `npx wrangler secret put
SECRET_NAME` and use `.dev.vars` locally; never commit secret values.

## Deploy to Vercel

Use the same Vite template and `public-deploy` staging script. Vercel serves the
static client and packages files under the project-root `api/` directory as
functions. See [Vite on Vercel](https://vercel.com/docs/frameworks/frontend/vite)
and [the Functions API](https://vercel.com/docs/functions/functions-api-reference).

1. Add **both** `api/context.ts` and `api/projects.ts`, each with this content:

   ```ts
   import handle from "../src/server";

   export async function GET(request: Request): Promise<Response> {
     const response = await handle(request);
     const headers = new Headers(response.headers);
     headers.set("Cache-Control", "no-store");
     return new Response(response.body, { status: response.status, statusText: response.statusText, headers });
   }
   ```

   The function preserves the request path and authorization header. For each
   additional backend route, create its corresponding `api/` file and export
   the HTTP methods your handler accepts, such as `POST`. Do not call `listen()`
   or run `start.cjs` from a function. Include `api/**/*.ts` in `tsconfig.json`
   so local typechecking covers these adapters.

2. Add `vercel.json` at the app root:

   ```json
   {
     "$schema": "https://openapi.vercel.sh/vercel.json",
     "framework": null,
     "installCommand": "npm ci",
     "buildCommand": "npm run build:hosting",
     "outputDirectory": "public-deploy",
     "routes": [
       {
         "src": "/(.*)",
         "headers": {
           "Content-Security-Policy": "frame-ancestors https://octonodes.com",
           "X-Content-Type-Options": "nosniff"
         },
         "continue": true
       },
       {
         "src": "/extensions/(.*)",
         "headers": { "Access-Control-Allow-Origin": "*" },
         "continue": true
       },
       { "handle": "filesystem" },
       { "src": "/api(?:/.*)?", "status": 404 },
       { "src": "/extensions/(.*)", "status": 404 },
       { "src": "/assets/(.*)", "status": 404 },
       { "src": "/.*\\.[^/]+$", "status": 404 },
       { "src": "/(.*)", "dest": "/index.html" }
     ]
   }
   ```

   Existing static files and functions resolve before the SPA fallback. Missing
   API and asset URLs return 404. Customize the Studio `frame-ancestors` origin
   as needed. This uses the advanced `routes` configuration; do not combine it
   with a separate `headers`, `rewrites`, or `redirects` array. See
   [Vercel configuration](https://vercel.com/docs/project-configuration/vercel-json).

3. Import the repository into Vercel and enter these project settings:

   | Setting          | Value                                                                 |
   | ---------------- | --------------------------------------------------------------------- |
   | Root Directory   | Directory containing the app's `package.json` and `octonode.app.json` |
   | Framework Preset | Other; the config disables automatic framework output selection       |
   | Node.js Version  | 24.x; set `engines.node` to `24.x` in this app's `package.json`       |
   | Install Command  | `npm ci`                                                              |
   | Build Command    | `npm run build:hosting`                                               |
   | Output Directory | `public-deploy`                                                       |
   | Start Command    | None; API functions handle requests                                   |

4. Choose a permanent production domain and save it as `web.applicationUrl`,
   for example `https://inventory-labels.vercel.app`. Publish the first release
   to obtain its registered app ID. In **Project Settings → Environment
   Variables**, add `OCTONODE_APP_ID` and `OCTONODE_API_URL` for **Production**.
   Add them separately to Preview only if needed. Redeploy after changing values.
   Ensure the production page can load in Studio without Vercel deployment
   protection or a provider login challenge.

5. Run `npm test` and `npm run build:hosting` locally. Push the configured app
   project to trigger deployment, or run `npx vercel` to link/preview and
   `npx vercel --prod` for production. Register only the stable production origin,
   never a changing preview URL. Vercel Hobby is limited to personal,
   non-commercial use; choose an eligible plan for commercial apps.

The generated `--platform next` template uses `output: "export"` and serves
its API through the separate Octonode handler; it does not generate Next Route
Handlers. These Vite settings are not a native Next.js deployment recipe. Keep
the Node hosting path for that output, or deliberately migrate the backend to
Next Route Handlers and update the build before selecting Vercel's Next preset.

## Verify the integration before inviting users

1. Open the permanent app origin directly. The static shell should load, but
   workspace content must remain hidden without a Studio session.
2. Request `/api/context` and `/api/projects` without a bearer. They must return
   401 after configuration, not HTML or workspace data. A 503 means the server
   identity or API URL is missing. Verify `/api/missing` and
   `/extensions/missing.js` return 404 rather than `index.html`.
3. Publish/install in the intended Studio workspace and open the app from
   **Apps → Installed apps**. Confirm the handshake, a 200 JSON response from
   `/api/context`, and the correct verified workspace. Check the API response's
   `Cache-Control: no-store` header.
4. Approve `projects:read` for a selected project to test `/api/projects`.
   Confirm only granted projects appear. Test no grants and revoked access too.
5. Navigate to `/projects`, refresh, and use back/forward. The client shell and
   mirrored Studio path should survive. Check the browser console for frame
   policy failures, provider login pages, API redirects, or failed asset requests.
6. If contributions are declared, check each manifest URL returns JavaScript,
   its SHA-256 still matches, and older pinned hashes survive your next deploy.

Do not log or copy live customer bearers into deployment settings. Debug with
status codes, routing, and non-secret configuration. Publication and installation
are separate from deployment; do all three before considering the app ready.

## Preserve older versions

Each published version and installation is pinned. Extension files are named
by SHA-256. An incremental build copies verified older assets forward. For a
clean CI build, restore the previous `dist/web/<id>` artifact **before** building,
or configure your hosting service to retain old hash-named files. Deploy the
complete directory atomically. Deleting an asset still referenced by a pinned
installation breaks that installation. Keep your backend compatible with old
pinned versions; publication does not update them automatically.

## If the tunnel or page fails

`app dev` automatically downloads a verified tunnel helper and requires network
access to GitHub releases and Cloudflare. Use `--use-localhost` for offline
UI work or `--tunnel-url` to supply your own public HTTPS tunnel. A workspace
preview also requires `octonodes login`, publisher access, and deployed preview
APIs. A 401 from a hosted app means the bearer expired, was revoked, or lacks
access: reopen the app from Studio. See [the app SDK](/docs/apps/sdk) and
[publishing](/docs/apps/publishing) for the relevant checks.

## Embed in Studio

Serve the page on an origin different from Studio. Configure `Content-Security-Policy: frame-ancestors https://octonodes.com` and any explicitly supported Studio origins. Do not send conflicting `X-Frame-Options: DENY` or `SAMEORIGIN`. Custom Studio domains must be explicitly allowed by your host.

Studio's frame policy permits same-origin content, HTTPS and blob frames. The hosted-app component additionally requires a registered HTTPS origin different from Studio before sending a session. Studio uses a sandbox permitting scripts, the app's own origin and forms. Top navigation and additional browser privileges stay restricted. Authenticate calls to your own backend using the hosted SDK; do not depend on third-party cookies.

Initialize the [hosted routing and session bridge](/docs/apps/routing). Studio waits for its handshake and offers a retry if the page cannot connect. An iframe load event alone does not establish readiness. The generated development server does not add a conflicting framing header; configure these headers at your production HTTPS host. The static app shell is public so the iframe can load; the React provider and backend bearer checks keep workspace content private.

---

# Publish and manage app releases

> Register an app, review consent, manage versions, and understand installation pins.

Source: /docs/apps/publishing

## Register and publish

`octonodes app publish --workspace user:<id>` builds and validates the current
`octonode.app.json`, then creates an immutable app release under a publisher
workspace. Use `team:<id>` or `org:<id>` for those workspaces. Sign in with
`octonodes login` first and ensure you have publisher access. For an
extension-only release, the CLI uploads the compiled verified bundles. For a
self-hosted release, the CLI registers metadata and remote asset digests; see
[hosting](/docs/apps/hosting) for deployment.

### Choose distribution at registration

Omitting `--distribution` defaults to the publisher workspace kind. The CLI
also accepts `--distribution user`, `team`, `org`, or `public`; Partner offers
the same audience choice. Choose the intended audience before the first
registration because it cannot be changed on that app ID. A public listing
is discoverable outside the owner workspace, but this release has no separate
public app review or billing workflow. Register another app if the audience
needs to change.

The first publication returns the registered app ID and revision. Keep both for
an update. Increment `version` in `octonode.app.json`, build and test, then run:

```sh
npm test
octonodes app publish --workspace user:<id> --app-id <registered-app-id> --revision <current-revision>
```

The revision guards against overwriting another publisher's concurrent edit.
Use the latest revision displayed in **Partner → Apps → [your app]** when your
local value is stale. An existing version cannot be replaced. Releasing a new
version updates discovery; existing installations remain pinned until an
administrator approves an update.

Partner also has a registration and publish form, app configuration, immutable
version history, analytics, and development guidance. The app can be saved as
an unpublished private draft before its first release. An unpublished draft is
visible only to its publisher workspace and can be edited or deleted. Published
app identity and releases cannot be deleted.

## Install and operate

In **Studio → Apps**, select the destination workspace, inspect the version,
origin, permissions, privacy/support links, and extension details, then install.
Project access is optional during installation, including in an empty workspace.
The consent step can grant requested actions to specific projects. An
administrator can later update, disable, or uninstall the app. A block appears
on workspace home; a page-capable app appears beneath Apps in Studio navigation.
Block-only apps still appear in **Apps → Installed**. Uninstalling or changing
consent revokes subsequent app access. Installed versions are not silently
upgraded when a publisher releases a new version.

Publishers may deprecate an app to prevent new installs while existing pinned
installations continue, then restore discovery later. Publishing a new release
does not itself restore a deprecated app. The Partner analytics view shows
installs, current active installations, reviews, ratings, and version adoption.
Its date filter covers the last 7, 30, or 90 days, or an inclusive UTC custom
range up to 366 days. Install counts include reinstalls; updates count
separately. Active installations and version adoption reflect current state.

This release supports private app authoring and distribution. Public app
moderation, payments, background service identities, webhook delivery, and
managed hosting need separate platform contracts. See [quickstart](/docs/apps/quickstart)
and [configuration](/docs/apps/configuration) before publishing an app.

---

# App troubleshooting

> Diagnose preview, permission, build and project-loading failures.

Source: /docs/apps/troubleshooting

| Symptom                                       | Check                                                                                                |
| --------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| Unsafe plugin file in a Yarn workspace        | Keep the generated `installConfig.hoistingLimits: workspaces`, reinstall, and rebuild                |
| No granted projects                           | Review declared actions and consent; new projects are not automatically included                     |
| Hosted page cannot connect                    | Check `frame-ancestors`, X-Frame-Options, host reachability, and SDK initialization; retry in Studio |
| External tab expires                          | Reopen from Studio; standalone launch cannot receive parent renewal                                  |
| Project list vanishes in a contribution       | Use supported SDK nodes such as `Section`; arbitrary HTML lists are not serialized                   |
| One project fails                             | Preserve successful rows, show partial failure, and offer a safe read retry                          |
| Service failure is reported as authentication | Preserve `AppRequestError.status`; reserve 401 for invalid or expired sessions                       |

Keep authentication failure, denied access, no grants, partial failure, service failure and a genuinely empty result separate. Test a non-empty list in a browser, not only a mocked backend.

Before a release, run fresh generation, install, typecheck, build, artifact validation and a private installed-app test with two selected projects. Verify another project is denied, the page remains usable after session renewal, and revocation stops access. Use a permanent HTTPS release host.

---

# Nodes and plugins

> Use built-in nodes and attach reusable integrations to your project.

Source: /docs/plugins

## Built-in nodes

Native nodes cover math, logic, branching, data transformation, text, dates, and
custom code. List the installed catalog and add a node to your project:

```bash
octonode add --list
octonode add math.add --id add-1 --config .octonode.yaml
```

Adding a native node creates editable TypeScript source and runtime artifacts.
Edit the TypeScript file, then compile or scan the project to refresh its contract.
See [Your first workflow](/docs/first-workflow) for a complete example.

## Use plugins in Studio

Open **Marketplace** to find integrations. A plugin in the **Workspace library**
is available for reuse; choose **Use in project** to attach it to the project
where the workflow will run. Supply that project's required service credentials
before executing the node.

For npm-backed plugins, project attachment installs the dependency using the
project's package manager and updates its manifest and lockfile. A failed install
can be retried; wait for successful attachment before using its nodes.

## Install a local plugin

From the destination project directory:

```bash
octonode plugin install /absolute/path/to/my-plugin --project
```

Use the plugin's declared node IDs and input schemas when wiring or invoking it.
Review the plugin's code, dependency requirements, and requested credentials
before running it.

## Build your own plugin

Start with `octonode plugin create my-tools --lang typescript`. A workflow plugin
contains its node contracts, executable handlers, and any required service
connections. Follow the [TypeScript SDK guide](/docs/typescript-sdk) for a complete
manifest, implementation, build, and invocation example.

This is a workflow runtime plugin. An AI client's extension package and a project
skill have separate installation and execution paths; see
[AI assistants and skills](/docs/ai-and-skills#skills-plugins-and-mcp-are-different).

## Publish a workflow plugin

Before publishing, test the built plugin, set its `plugin.scope` to `[public]`,
and supply author and license metadata in its definition. Increase
`plugin.version` for each release. Configure the registry URL and its publishing
credential through `OCTONODE_MARKETPLACE_URL` and `OCTONODE_MARKETPLACE_TOKEN` in
your local environment.

```bash
octonode plugin publish ./my-tools
```

Publishing shares the plugin with the configured marketplace. Review the files
first, include the compiled runtime files, and keep tokens and environment files
out of the package. Consumers can then install its marketplace ID with
`octonode plugin install my-tools --project`. Publishing credentials are separate
from the service credentials that consumers supply when running its nodes.

## Generate an adapter

The CLI can generate a plugin from an OpenAPI document or an npm package:

```bash
octonode plugin from-swagger ./openapi.json --id my-api
octonode plugin from-npm lodash --include 'chunk,pick,groupBy'
```

Inspect the generated files, then install the generated directory with
`octonode plugin install ./my-api --project` or the corresponding npm adapter
directory. The npm adapter calls the installed package; it does not copy the
package implementation into your workflow.

Node inputs and outputs must remain JSON-compatible. An arbitrary npm export may
need an adapter for objects such as streams or class instances. Dependencies that
require install scripts may also need a separate build step; successful dependency
installation alone does not guarantee every export can execute.

For portable examples that combine nodes, browse the [workflow catalog](https://playbook.octonodes.com/workflows)
and read [Community and sharing](/docs/community) before importing.

---

# Inputs, execution, and triggers

> Supply workflow data, call the HTTP endpoint, and configure subscriptions.

Source: /docs/workflow-inputs-and-triggers

## Supply inputs

Workflow inputs are described with JSON Schema. Source workflows derive their
parameters from the function signature. In Studio, select **Start → Types** to
inspect or edit the supported parameter contract, then use the invocation form
or JSON input when running the workflow.

For individual nodes, use the Inspector's I/O controls to set fixed values.
Expressions such as `{{ $json.field }}` can read values from the node's input.
Keep inputs JSON-compatible and satisfy the required fields shown by the schema.

From the CLI:

```bash
octonode run total --config .octonode.yaml --input '{"a":2,"b":3}' --json
```

`--json` prints the full run record. Without it, the CLI prints terminal outputs.

## Call a workflow over HTTP

Copy the complete POST URL from **Start → Endpoint**. It uses `/wf/exec?id=…`;
`/api/wf/exec` is the equivalent documented API route. Preserve any project and
workspace parameters in the copied URL. The workflow identifier is not a credential.

Set `WORKFLOW_URL` to that copied URL and `WORKFLOW_API_TOKEN` to an authorized
token with `workflows:run` access for the target workspace and project, then call:

```bash
curl --fail-with-body "$WORKFLOW_URL" \
  -H "Authorization: Bearer $WORKFLOW_API_TOKEN" \
  -H 'Content-Type: application/json' \
  --data '{"a":2,"b":3}'
```

Send the target workflow's input object directly as the request body. The response
includes `runId`, `workflowId`, `status`, `outputs`, and `durationMs`.

**Check the JSON `status`, even after HTTP 200.** An admitted run can finish with
`error` or `partial`. Authentication failures, invalid requests, missing workflows,
and full queues use HTTP errors. Stopping the HTTP client from waiting does not
cancel an already admitted execution.

The Endpoint call builder can generate examples for Node.js, Go, Python, cURL, and
Java. Copying an example does not execute the workflow. For the complete API
contract on your deployment, open **API docs** in the Playbook navigation.

## Add triggers

**Start → Triggers** manages webhook and scheduled subscriptions. Save workflow
changes separately from trigger changes: saving a subscription does not save
unsaved canvas topology. Configure the subscription for the intended environment
and input before enabling it.

Native scheduling is available on supported cloud deployments and accepts a
five-field cron expression in the selected IANA timezone. Enable both the
subscription and **Activate workflow triggers**, then choose **Save triggers**.
The panel shows the registered next occurrence and admission errors.

Webhook subscriptions accept a JSON event body at the subscription's authenticated
event endpoint. Use a stable `Idempotency-Key` for each event so repeated deliveries
reuse the same execution admission. External schedule subscriptions use that event
endpoint with an `eventId` and `payload`; their saved input supplies the workflow
parameters. Saving an external schedule does not create a native scheduled job.

A trigger delivery response with HTTP 202 means the run is queued. Follow the run's
status in execution history. Alternatively, an external scheduler can call the
direct execution URL documented above.

The scheduling `active` switch controls scheduled execution. Explicit authorized
HTTP calls can still execute a workflow independently of that switch.

## Handle failures

Node runtime settings support timeouts, retries, and retry backoff. Configure
retries only when repeating the operation is acceptable or the operation is
idempotent. See [runtime configuration](/docs/config-reference) for the fields and
[Troubleshooting](/docs/troubleshooting) for diagnosing failed runs.

---

# Configuration reference

> Understand workflow manifests, field ownership, and project settings.

Source: /docs/config-reference

## Workflow manifest

The workflow manifest accepts YAML (`.octonode.yaml` or `.octonode`) and JSON
(`.octonode.json`). Use `--config` to select a file explicitly.

Direct CLI commands read and write the manifest. In Studio/server mode, saved
environments, node configuration, and workflow topology live in the project store;
the manifest is an import/export artifact. Use Studio's save and export flows to
retain changes made there.

| Field                  | Purpose                                          | Ownership                                                                      |
| ---------------------- | ------------------------------------------------ | ------------------------------------------------------------------------------ |
| `metadata`             | Project name and version                         | Project configuration                                                          |
| `sources`              | Node commands to discover                        | Project configuration                                                          |
| `nodes[].signature`    | Input/output contracts and code checksum         | Generated from code                                                            |
| `nodes[].runtime`      | Timeouts, retries, and execution behavior        | Project configuration                                                          |
| `nodes[].presentation` | Node appearance                                  | Project configuration                                                          |
| `environments`         | Environment variables and inheritance            | Project configuration                                                          |
| `workflows`            | Workflow membership, edges, inputs, and bindings | Configuration for canvas workflows; source-derived fields for source workflows |

`octonode scan` refreshes code-owned signatures. It preserves configuration-owned
runtime settings and topology, and does not rewrite source files.

```bash
octonode scan --config .octonode.yaml
octonode scan --check --config .octonode.yaml
octonode validate --config .octonode.yaml
```

`scan --check` reports drift without writing. `validate` checks schema and structure.
Use `octonode schema` to print the workflow JSON Schema for editor tooling.

## Runtime settings

Set these under an existing node's `runtime` block:

```yaml
runtime:
  timeout_ms: 5000
  retries: 2
  retry_backoff_ms: 250
```

`timeout_ms` is the deadline for one attempt. `retries` counts attempts after the
initial invocation. `retry_backoff_ms` is the base retry delay. The `async: true`
option waits for running nodes and executes that node alone within the workflow run.

## Environments

```yaml
environments:
  dev:
    vars:
      LOG_LEVEL: debug
  prod:
    inherits: dev
    vars:
      LOG_LEVEL: warn
```

Select an environment with `octonode run total --env dev --config .octonode.yaml`.
Keep actual service credentials in the workspace's variables or appropriate
runtime secret configuration, outside committed examples and public documents.

## Human-owned settings

`octonode.yml`, `octonode.yaml`, or `octonode.json` (without the leading dot) is a
separate settings document. It supports `appearance`, `overrides`, `layers`,
`views`, and `defaultView`. A section can be inline or reference a local YAML/JSON
file using `$file`; referenced files must remain inside the settings directory.

```yaml
apiVersion: octonode.dev/settings/v1
appearance:
  nodeDefaults:
    style: { density: comfortable, radius: soft }
```

Validate and inspect settings with:

```bash
octonode settings validate --file octonode.yml
octonode settings show --file octonode.yml
```

Both commands are read-only. `show` prints resolved JSON. Use `--file` for settings
and `--config` for the workflow manifest. Include referenced section files in Git
alongside the root settings file.

The settings contract, loader, and CLI are available. Studio appearance resolution,
layer filtering, and settings editing are not yet connected to this document;
declaring a view does not currently hide Studio content. YAML and JSON are supported;
TOML is not supported.

---

# Community and sharing

> Read public articles, publish reviewed work, and import independent workflow copies.

Source: /docs/community

The Playbook's documentation contains official product guides. Community
[guides](https://playbook.octonodes.com/guides), [blog posts](https://playbook.octonodes.com/blog), and [research papers](https://playbook.octonodes.com/research) are
separately published contributions with author attribution and licensing.

## Publish an article

In Studio's community authoring area, write a Markdown document and supply its
title, summary, kind, topics, authors, and license. Save a draft, review the exact
text you intend to make public, then submit it for moderation. Changes may be
requested before publication.

Publishing copies the reviewed document revision. Later source edits do not
silently change the public article. Private source-document comments, workspace
membership, and draft history are not copied to the public page. Remove private
information from the article text itself before submitting it.

Reading published content is public. Draft editing and moderation require the
appropriate account and permissions; private drafts and review queues do not
appear in public navigation or search.

## Import a workflow template

1. Browse the [workflow catalog](https://playbook.octonodes.com/workflows) and inspect a template's graph,
   supported runtime, plugin dependencies, permissions, and license.
2. Import it from Studio into the intended destination project.
3. Review dependency and permission consent, then configure required placeholders
   with your own values and credentials.
4. Inspect the resulting workflow and run it when ready.

A template is an immutable snapshot. Import creates an independent copy and does
not execute it. Credentials, private environment values, source execution history,
and private workspace discussions are not included. An imported workflow does not
receive automatic changes from the original author's workspace.

## Keep project documentation private

Project documents and Design Doc drafts remain in their existing workspace scope.
They do not become public simply because they are Markdown or because the project
has a Documentation tab. Use the explicit publication and review flow when you
intend to share an article or template publicly.

---

# Troubleshooting

> Resolve common setup, validation, execution, and plugin problems.

Source: /docs/troubleshooting

## Browser extension hydration warnings

If the browser console reports server/client attribute differences containing
`bis_skin_checked` or `bis_register`, an extension has modified the HTML before
React attached its event handlers. These attributes are not emitted by the Playbook.

Open the same URL in a clean browser profile with extensions disabled. If the warning
disappears, identify the extension that inserts those attributes and restrict its
site access for the local preview, then reload. An incognito window only helps if
the extension is not allowed to run there.

Suppressing warnings throughout the page would hide real mismatches and does not
remove the injected attributes. If the error persists in a clean profile, capture
the new mismatch and URL; it may have a different cause.

For connection failures, see [access token troubleshooting](/docs/access-tokens#diagnose-authentication-failures)
and [MCP setup](/docs/mcp#resources-and-connection-problems).

## The CLI cannot find my project

Run commands from the project directory or pass `--config /path/to/.octonode.yaml`.
For a new project, use `octonode init .octonode.yaml --name my-project`. Avoid
`--force` unless you intend to replace an existing manifest.

If you are working from a source checkout, run the built CLI at
`packages/cli/dist/index.js`. The node-authoring runtime is TypeScript on Node.js 24.

## A signature is stale

Run `octonode scan --check --config .octonode.yaml` to confirm drift. After reviewing
the source changes, run `octonode scan --config .octonode.yaml` to update signatures,
then validate again. In Studio, use Compile after source edits.

Scan can mark a missing source as orphaned instead of deleting its workflow
connections. Restore the source or deliberately remove the obsolete node and edges.

## A node fails input validation

Inspect the node's required fields and types. Check the names of incoming ports,
fixed input values, and expressions. Supply valid JSON: numbers and booleans should
use their JSON types rather than quoted strings unless the schema expects strings.

## A workflow has missing outputs or skipped nodes

Open the execution and find the first failing node. Inspect its error and input
before changing downstream nodes. Review timeout and retry settings, service
credentials, and the selected environment. Use `--json` on a CLI run to inspect
the full status and trace.

Replay runs the selected node again and may repeat external writes. Choose a test
environment or safe input when diagnosing a node with external effects.

If a generated native node exits without output, check that the project can resolve
`@octonode/plugin-runtime`. The CLI being available does not install that runtime dependency
into a separate project. The first-workflow tutorial uses a directory inside the
built checkout so it can resolve the workspace SDK.

## HTTP 200 contains a failed run

HTTP 200 means the execution was admitted. Inspect the JSON `status` and `error`;
only `status: "ok"` indicates a successful workflow outcome. Preserve the complete
URL copied from Start, including workspace and project parameters. See
[HTTP execution](/docs/workflow-inputs-and-triggers).

## A plugin is visible but unavailable in my workflow

Confirm that it is attached to the selected project, not only cached in the
workspace library. Retry a failed dependency installation, configure required
credentials, and inspect the node's contract before running it again.

## My settings file does not change Studio appearance

Run `octonode settings validate --file octonode.yml` to validate the settings
document. The current settings loader and CLI do not apply appearance, layers,
or views to Studio yet. Studio's project **Settings** tab manages metadata
separately. See [Configuration reference](/docs/config-reference).
