self 4658b76241
CI / Test (push) Failing after 22s
feat: prefix Kobold plugin slug
Rename Kobold and Trust plugin identity references to tribe-one-prefixed slugs across runtime API, e2e fixtures, and docs.
2026-06-17 22:33:25 +02:00
2026-05-27 16:19:27 +02:00
2026-06-17 22:33:25 +02:00
2026-06-17 22:33:25 +02:00
2026-06-17 22:33:25 +02:00
2026-06-17 22:33:25 +02:00
2026-05-27 16:19:27 +02:00
2026-05-27 16:19:27 +02:00
2026-05-27 16:19:27 +02:00
2026-05-27 19:06:21 +02:00
2026-05-27 16:19:27 +02:00
2026-05-27 16:19:27 +02:00
2026-06-17 22:33:25 +02:00
2026-06-17 22:33:25 +02:00
2026-05-27 19:06:21 +02:00
2026-05-28 20:07:06 +02:00
2026-06-17 22:33:25 +02:00

Kobold

Distributed dataset and lightweight data-application plugin for Tribes OS.

Getting Started

  1. Edit manifest.json - set description, capabilities, requirements
  2. Implement your plugin in lib/kobold/plugin.ex
  3. Run validation, smoke checks, and tests:
mix deps.get
mix tribes.plugin.validate
scripts/plugin smoke
scripts/plugin test

If you are using the shared tribes devenv, run through the local helper instead:

devenv shell -- plugin validate
devenv shell -- plugin smoke
devenv shell -- plugin test
devenv shell -- plugin precommit

Generate AshPostgres resource migrations through the same wrapper so they target the host Tribes.Repo and the plugin migration directory:

plugin ash.codegen update_example_resources

Manual Ecto migrations are the rare exception for schema work not derived from Ash resources:

plugin ecto.migration add_example_table

Development

For local development alongside a Tribes checkout:

# Symlink into the host plugins directory once
cd ../tribes
ln -s ../tribes-plugin-kobold plugins/kobold

# Start Tribes dev server
iex --sname dev -S mix phx.server

Then edit the plugin in its own repo. In development, the host watches symlinked external plugins and automatically:

  • runs mix compile for Elixir/HEEx or manifest changes
  • runs npm run build --prefix assets when assets/package.json is present and plugin asset files change
  • reloads the plugin in the running Tribes VM
  • triggers a Phoenix browser reload after the rebuild finishes

Browser hooks for external plugins should live in plugin JS assets declared in manifest.json assets.global_js and register themselves through window.TribesPluginHooks. Phoenix colocated hooks are not auto-imported from external plugin OTP apps by the host app.js bundle.

That means the normal edit/compile loop is:

cd /path/to/tribes-plugin-kobold
mix deps.get

# in another terminal
cd /path/to/tribes
iex --sname dev -S mix phx.server

Inside the plugin repo's devenv shell, the plugin helper forwards to the host devenv automatically:

plugin validate
plugin smoke
plugin test
plugin precommit

If your plugin does not need a custom frontend pipeline, you can skip assets/package.json and write browser-ready files directly under assets/js and assets/css; the host dev watcher will copy them into priv/static for you in development. The default generator uses TypeScript under assets/ts.

LiveView Hooks

External plugins do not participate in the host asset bundle, so the host cannot statically import arbitrary plugin phoenix-colocated/<otp_app> modules. Register browser hooks from your plugin JS instead:

window.TribesPluginHooks = window.TribesPluginHooks ?? {};
window.TribesPluginHooks.TribeOneTribesPluginKoboldExample = {
  mounted() {
    console.info("kobold hook mounted");
  }
};

Keep the compiled JS file listed in manifest.json assets.global_js so it loads before the host LiveSocket connects.

Project Structure

kobold/
|-- manifest.json           # Plugin metadata (Nix build + runtime)
|-- mix.exs                 # Dependencies
|-- config/                 # Host-backed test config
|-- lib/
|   |-- kobold/
|   |   |-- plugin.ex       # Tribes.Plugin entry point
|   |   `-- application.ex  # OTP supervision tree (optional)
|   `-- kobold_web/
|       `-- live/           # LiveView pages
|-- assets/                 # TS/CSS (one bundle per plugin)
|   |-- ts/                 # TypeScript browser entry points
|   |-- package.json        # Optional build script used by dev + Guix packaging
|   |-- tsconfig.json       # TypeScript compiler settings
|   `-- package-lock.json   # Optional, recommended for reproducible builds
|-- priv/
|   |-- static/             # Built assets for release
|   `-- repo/migrations/    # Ecto migrations
|-- scripts/
|   `-- plugin              # Shared devenv/non-devenv test wrapper
`-- test/

Manifest

manifest.json declares your plugin's identity and capabilities:

{
  "id": "org.tribe-one.plugins.kobold",
  "slug": "tribe-one-kobold",
  "display_name": "Kobold",
  "entry_module": "TribeOne.TribesPlugin.Kobold.Plugin",
  "host_api": "1",
  "otp_app": "tribe_one_kobold",
  "provides": ["some_capability@1"],
  "requires": ["org.tribe-one.caps.ui@1"],
  "enhances_with": ["org.tribe-one.caps.inference@1"]
}
  • entry_module - must be a valid module ending in .Plugin
  • otp_app - required, vendor-prefixed Mix application name
  • provides - capabilities this plugin makes available
  • requires - hard plugin/API contracts (build fails without them)
  • enhances_with - optional dependencies (plugin degrades gracefully)

The default generator includes org.tribe-one.caps.ui@1 because the generated LiveView renders inside the host chrome through Tribes.Plugin.Layouts.app. Keep org.tribe-one.caps.ui@1 when a plugin uses host chrome, imports Tribes.UI.Components, or uses use Tribes.UI.

Plugin Data

If your plugin adds Ash resources that should replicate cluster-wide, use extensions: [AshNostrSync] on those resources and assign a sync lane per resource. The host default lane is bulk; latency-sensitive topology or orchestration resources should opt into control. Keep resource-specific side effects explicit in actions.

Testing

The generated plugin starts with two host-backed test layers:

  • Contract tests (test/kobold/plugin_contract_test.exs) - manifest and runtime spec stay aligned
  • Page tests (test/kobold/home_page_test.exs) - the plugin renders through the real host page pipeline

Run them with:

mix tribes.plugin.validate
scripts/plugin smoke
scripts/plugin test

Use plugin test / plugin precommit for host-backed tests. The helper invokes Mix with the host database/services and host plugin-manager paths, including built-in providers such as tribes_ui. Raw mix test in a plugin checkout is guarded and prints this guidance; mix raw_test / mix raw_precommit are available only for unusual manual debugging when you have set the same host environment yourself.

Building for Release

MIX_ENV=prod mix compile
devenv shell -- npm run build --prefix assets

mkdir -p dist/kobold
cp -r _build/prod/lib/kobold/ebin dist/kobold/
cp -r priv dist/kobold/
cp manifest.json dist/kobold/

Licence

TODO: Choose a licence.

S
Description
Shared, event-backed databases
Readme 262 KiB
Languages
Elixir 90.2%
Nix 5%
Shell 4.1%
TypeScript 0.5%
CSS 0.2%