Skip to main content
Wildo.ai Coming soon

Share business modules

Package models, backend behaviour and frontend components for reuse across applications.

Shared models · backend code · frontend code · versioned modules

> Publish connected application code > Choose the version to adopt > Keep each application in control

A reusable module brings together the source files for a piece of an application: its shared definitions, backend behavior, interface and supporting declarations.

The module registry gives that piece a name and a version. Wildo helps you publish it, place it in another application’s source tree and track what was installed. Each application chooses how to integrate it and when to update.

A versioned module in the registry is adopted into the source layers of two separate applications.

Share the work that belongs together

Package across application layers

A business feature often spans several parts of the codebase. A module carries those files together, with a manifest describing their destination paths, so reuse can include the surrounding application structure.

Make adoption a deliberate choice

Choose a release for each application. Wildo verifies the artifact, checks its declared module, capability and framework requirements, and records the version and source files adopted.

Keep the receiving application yours

Installed code becomes part of the application’s source. Review its registrations, adapt its configuration and verify the resulting behavior. Updates happen when that application is ready to adopt them.

Example: Share a billing extension across internal tools

A team publishes the shared definitions, backend logic and interface for a billing extension. Two applications adopt the same release, each with its own configuration. When the extension changes, either application can review the new version before updating.

For engineers

Distinguish the artifact from the application

The platform registry stores module information, versions and artifacts. The CLI publishes and retrieves them. The receiving application’s own registries, service bindings and configuration determine how the installed source participates in its runtime.

BoundaryWhat belongs there
Published moduleNamed version, source files, manifest and declared placement boundaries
RegistryDiscovery, version resolution, access to artifacts and their integrity digest
Local installationExact resolved version, destination files and the installation record
Receiving applicationRegistrations, dependencies, settings, business behavior and release decisions

This separation lets a team share implementation without making every application follow one release schedule. A registry update changes local source; deploying that change is an application decision.

Publish a release under its owning organization

The publisher defines which module-owned folders travel together in wildo.module.json: shared definitions, backend behavior, interface code and any supporting specifications. The receiving application must support those relative paths. A published boundary describes source placement; it does not isolate the installed code from its host.

Publication targets an existing registry domain owned by the publisher’s organization. The registry checks that authority before accepting a release. New modules inherit the domain’s default visibility; visibility does not define the code’s license.

A release couples the manifest and source artifact with an exact version. Future changes receive a new version rather than replacing an existing release. The registry capability guide contains the manifest, commands and installation-record examples.

Turn an artifact into an application feature

Adoption selects a concrete release and checks its downloaded bytes against the registry’s digest. Before placing source or recording the installation, the CLI checks required module versions, enabled capabilities and installed framework versions. Missing prerequisites stop that adoption; npm dependencies are reported for the application to install.

The installation record identifies the exact version and paths that later updates manage. These checks establish declared compatibility, while the receiving application’s tests establish whether the integrated feature works.

The application then supplies its side of the integration: required dependencies and settings, shared and frontend registrations, backend discovery and service bindings. An artifact can be correctly downloaded while that integration is still unfinished. Provider synchronization refreshes its own outputs after installation; its result deserves attention separately from file placement.

The connected module example shows these registrations in the shipped skeleton and traces them into the existing companion loader. Apply that reasoning to the receiving application’s actual layout. Creating new structure through composition and adopting published source are distinct operations.

Review tracked changes and new files before running the result. Let development tooling compile the affected packages, inspect the resolved model through the companion and exercise the feature through its interface or API. Each check answers a different question about the adopted code.

Evolve the shared piece at each application’s pace

ChangeEffect on the receiving application
Publish a new releaseMakes another version available; installed copies do not change
Move a tagChanges selection for future requests, not an application’s recorded version
Withdraw a releasePrevents future resolution and downloads; existing copies remain in place
Adopt an updateReplaces module files; removes obsolete paths unless another installed module also records them
Repair recorded filesRe-fetches the recorded release and can overwrite local module edits; it does not select a newer release

Keep deliberate application edits in version control. Updates and repair are source replacement, not a merge of local changes. An update whose resolved version and digest already match is a no-op; explicitly requested repair serves a different purpose. Deployment remains the application’s release decision.

Use the development tools around adoption

The command-line area below follows what happens around a shared module: establishing an application, adding connected structure, refreshing configuration, running development and inspecting the result. Those same tools serve everyday application changes, whether their source was composed, adopted or written directly. Their capability guides explain each command’s contract without making publication responsible for the whole development lifecycle.

Share application code as versioned modules Tool

A reusable module packages a piece of an application with the source files that belong together. Shared definitions, backend behavior and interface code can travel in one named version, with a manifest describing where they belong.

Publish it to a registry, then choose the version each application adopts. Wildo verifies the downloaded artifact, places its files in the declared application paths and records that installation for later changes.

Example: Reuse an internal billing extension

A team packages its billing extension across shared, backend and frontend folders. Another application installs version 1.0.0, reviews the added source and connects the extension to its own configuration. A later release is an explicit update, so each application can adopt it at the right time.

A versioned registry artifact is verified and placed in the shared, backend and frontend layers of an application.
For engineers

Declare the files that travel together

Place wildo.module.json at the publishing application’s root, or select another manifest with --manifest. This illustrative manifest packages an existing billing extension. The paths are relative to that application root and must match real source directories:

{
  "id": "acme/billing",
  "version": "1.0.0",
  "description": "Internal billing extension",
  "boundaries": {
    "shared": ["shared-lib/src/modules/acme-billing"],
    "backend": ["backend-lib/src/modules/acme-billing"],
    "frontend": ["frontend-lib/src/modules/acme-billing"]
  }
}

version is an exact semantic version. boundaries can also include specifications, minions and workers. Publish collects files from these declared paths and packages them with the manifest; a manifest with no declared boundary directories is refused. Installation preserves the relative paths in the receiving application rather than moving code into an npm dependency directory.

Choose boundaries that belong to this module. Files outside them are rejected during placement, but a boundary is a placement contract supplied by the publisher, not a sandbox for the code after installation. Review the module as application source.

Publish, inspect, then install

The following illustrative workflow uses a registry already configured and authenticated for publication. The internal registry domain contains module acme/billing; these are separate parts of the add reference.

# In the application that owns the extension.
wildo registry publish --domain internal

# Inspect the published module before adopting it.
wildo registry search --domain internal --query billing
wildo registry info --domain internal --module acme/billing

# In the receiving workspace: note preexisting changes.
git status --short --untracked-files=all

# Adopt the release and inspect tracked changes and new files.
wildo registry add internal/acme/billing@1.0.0
git status --short --untracked-files=all
git diff
git diff --cached

Use --registry when selecting a registry other than the configured default. Public modules support anonymous reads; restricted access and publication use credentials for the selected registry. Authentication is managed per machine, separately from the module files.

The registry domain must already exist and belong to the organization making the publication request. internal identifies that publishing domain; acme/billing identifies the module inside it. Choosing a domain in the command does not create it or grant publishing rights. New modules inherit the domain’s default visibility. Visibility controls access to registry content; it does not define the module’s software license.

The add syntax is <domain>/<moduleId>@<version-or-range>. A range such as ^1.0.0 resolves to a concrete version at installation time. It is not a subscription that changes a running application whenever someone publishes.

Follow the installation record

StageWhat it establishes
ResolveThe registry selects an exact version and returns its artifact digest
DownloadThe client compares the downloaded bytes with that SHA-256 digest
ExtractVerified artifact files are unpacked into a staging directory and the manifest is parsed
Check requirementsBefore placing source, the CLI checks required module versions, authored capability activation and installed framework versions
Place sourceFiles are copied into application source paths allowed by the manifest
RecordThe lock entry keeps the registry, requested range, resolved version, digest and installed paths
Synchronize providersA follow-up sync refreshes provider artifacts; a warning here requires separate attention

The digest verifies that the received bytes match the artifact the registry resolved. Publisher trust and source review are separate decisions; the digest is not a publisher signature.

The lock entry is written after source placement. If that write fails, the command attempts to restore the files it replaced. Provider synchronization follows the recorded installation and can report a warning without undoing it. Check the command result and generated changes before using the module.

Read what this application adopted

The installation record lives at .wildo-saas/wildo-saas.lock.json, under sections.modules.installed. Example installation record, showing selected fields with illustrative values:

{
  "acme/billing": {
    "moduleId": "acme/billing",
    "domain": "internal",
    "version": "1.0.0",
    "requestedRange": "^1.0.0",
    "files": [
      "shared-lib/src/modules/acme-billing/index.ts"
    ],
    "source": "install"
  }
}

The full entry also records the registry binding, artifact digest and installation time. requestedRange records the choice the operator made; version records the exact release adopted. files identifies the application paths managed by the module lifecycle, rather than every file involved in integrating the feature.

Inspect that record from the application root, then run the read-only diagnostic:

node --input-type=module <<'JS'
import { readFileSync } from 'node:fs';
const lock = JSON.parse(readFileSync('.wildo-saas/wildo-saas.lock.json', 'utf8'));
console.log(JSON.stringify(lock.sections.modules.installed['acme/billing'], null, 2));
JS

# Inspect the lockfile shape and recorded file presence without repairing.
wildo registry repair-lockfile

A healthy report means those diagnostics found no inconsistency. It does not establish that local source still matches the published artifact or that the feature works in the application.

Integrate the module into the receiving application

A module’s source files and an application’s runtime bindings are different concerns. Review its shared and frontend registrations, backend discovery, service bindings and required settings. Use composition scenarios when creating new connected structure; do not assume copying a module also creates every host-specific registration.

The manifest can declare prerequisites for adoption. Add, update and repair check them after extracting the verified artifact, before replacing application source or updating its adoption record:

RequirementWhat the CLI checksWhat you still establish
Other modulesRecorded module versions satisfy the declared rangesThe adopted code is registered and works in the application
CapabilitiesKnown capabilities are explicitly enabled in application configurationProviders, credentials and application-specific configuration are ready
FrameworkInstalled framework versions satisfy the declared rangeThe complete application compiles and behaves as expected
npm packagesRuntime and peer requirements are printed as advisoriesAdd the dependencies to the packages that consume them and install them

Framework comparison covers every installed model package reached through the application’s workspace framework dependencies, including distinct versions in different packages. Desired version pins and the CLI’s own installation are not used as proof.

A missing or incompatible module, capability or framework prerequisite stops source adoption with a diagnostic. npm requirements remain advisory. It does not automatically install another module, enable a capability or edit package dependencies. Review and test the resulting application after adoption.

The connected module example follows a generated module through its shared, specification and frontend registrations, backend discovery and existing companion loader. It uses the skeleton layout; an adopted module must be integrated into the receiving application’s actual package paths and service keys. Registry adoption places source files, while composition creates a new connected structure.

Let the application’s development tooling compile the new source, then exercise the feature through its actual interface or API. Registry installation establishes file placement and the install record; application verification establishes that the adopted feature works in its new context.

Update deliberately and inspect source changes

These commands run inside the application that installed acme/billing. Updates use the recorded registry unless overridden:

# Record the workspace state before the update.
git status --short --untracked-files=all

# Adopt a selected later release.
wildo registry update acme/billing@1.1.0

# Inventory all changes, then inspect unstaged and staged differences.
git status --short --untracked-files=all
git diff
git diff --cached

# Remove the installed module when it is no longer needed.
wildo registry remove acme/billing

Compare the status listings before and after adoption. Open every new (??) file in your editor; Git’s diff commands omit untracked content. git diff shows unstaged tracked changes, while git diff --cached shows staged changes. Existing staged work remains visible, so distinguish it from the module’s changes rather than attributing the whole listing to the update. No blanket staging is needed to review the source.

Add and update replace files at the module’s destination paths. Update also removes paths belonging only to the previous version; removal uses the recorded installed paths. Files claimed by another installed module are protected from deletion, while overlapping writes produce warnings. This is not a three-way merge of application edits: preserve deliberate changes in version control and review them when adopting a new version.

Choose between a new release and a repair

ChangeWhat happens
Publish a new versionCreates a distinct release; republishing an existing module version is refused
Move a tagChanges which version the tag selects for a future request; installed copies stay at their recorded version
Withdraw a versionRefuses future resolution and download of that version; it does not remove copies already installed
Update an applicationSelects the requested release; matching version and digest produce a no-op without revalidating host requirements
Repair an installationReapplies the recorded exact version for fixable findings, rather than selecting a newer release

Use wildo registry repair-lockfile --fix only after preserving local edits and reviewing the diagnostic. For a missing-file finding, repair re-fetches the recorded version, extracts its artifact and copies its module files back into the application. Existing files can be replaced too: this is not a missing-file-only restore, and it does not back up the application’s edits. Malformed records, including an invalid artifact digest, require manual correction from a trusted lockfile revision; --fix does not reconstruct them. Repair also reports overlapping writes when another installed module claims the same destination. That warning describes a file replacement, not a merge or protection from overwriting it.

Repair refreshes the recorded digest and file list while retaining the installation timestamp and source field. A withdrawn release cannot be re-fetched through this path. Reinspect the resulting source and verify the application afterward.

The module registry coordinates sharing and version selection. Your application retains responsibility for its own integrations, tests and release timing.

Build, run and inspect from one command line

The command line turns a development intention into a concrete project action: create a workspace, add a connected module, regenerate configuration or supervise local processes.

Each command works within its own scope. You can review a composition plan before writing files, choose which configuration outputs to refresh, and inspect the resulting application from the same terminal.

Starting, configuring and inspecting remain connected to the same application.

Know what each command changes

Review before adding source

Composition shows the files and registrations a scenario will add or edit. Review that plan before applying it to your application.

Choose the environment and outputs

Configuration commands select the environment and generated artifacts. Local lifecycle commands prepare and supervise development processes.

Read the result in context

Inspection commands name the companion, service and model being queried. Use that information to interpret the result before investigating the source.

Example: Change a module, then check the application

A team adds a module through composition or adopts one from the reusable module registry. After reviewing its source and registrations, it refreshes the affected configuration, runs development and inspects the resolved model. It then checks the new behavior through the application itself.

For engineers

Establish the application context

Run application commands inside the intended workspace. The CLI resolves that project’s configuration and environment; the companion serves its live development context. Registry discovery can happen before an application exists, but installing a module needs an application source tree to receive it.

The following is an illustrative inspection sequence after an integration change, using a local Docker Compose environment. The module’s files and required registrations have already been reviewed:

# Refresh derived files and check the configuration.
wildo config sync --env local
wildo config validate --env local

# Prepare infrastructure and start supervised development.
wildo local dev

# In another terminal, inspect the serving companion.
wildo context health
wildo context list
wildo context info resources-registry

The normal local sync selects configuration and environment-file generation. Choose additional output domains when needed. local dev prepares its supporting infrastructure, then supervises development processes; a context query needs the companion to be available. Use the live query menu for the behaviors supported by that application.

Choose creation, adoption or inspection deliberately

TaskToolResult to review
Create a new applicationwildo initWorkspace, declarations and delivered development knowledge
Add connected source structurewildo composePlanned new files and edits to existing registrations
Adopt published sourcewildo registry addInstalled module files, exact version and installation record
Refresh generated configurationwildo config syncSelected environment outputs
Run local developmentwildo local devInfrastructure readiness and supervised application processes
Inspect the applicationwildo context infoA selected behavior and service, with the companion’s reported provenance

Composition works from a scenario’s templates and edits. Registry adoption works from a published artifact and its declared paths. They support different reuse needs and do not replace one another.

Follow the changed inputs to their consumers

After adding source, verify its registrations and let the development tooling compile it. After changing configuration, regenerate the relevant outputs. After starting development, query the companion and exercise the affected behavior through its actual interface or API.

The companion reads compiled application exports for introspection and can reuse a held answer. Journey and coherence also use working-tree inputs. Check the query’s source line and let affected packages compile before treating an answer as evidence of your latest change.

These steps establish different facts. A generated configuration is not an applied release, and a listed resource is not a completed business flow. The capability guides below explain the command contracts and the evidence to inspect at each stage.

Create and extend the application

Start with a connected application workspace Tool

A new application needs more than empty folders. Its shared definitions, backend, interface and specifications must agree on how they fit together.

Wildo creates that starting structure with local environment configuration and development knowledge. You begin with the framework connected; your business objects, workflows and experience remain yours to build.

Example: Start a service-management application

Create a workspace for a service team, then add modules for customers and requests. The first command establishes the application’s shared structure; composition adds each business area as its purpose becomes clear.

A new application workspace connects configuration with shared, backend and frontend source.
For engineers

From the empty directory that will become your application, this illustrative command sequence uses the shipped CLI flags. The administrator details are requested interactively; no credentials belong in the example or committed configuration.

wildo init --check
wildo init --name service-desk \
  --runtime docker-compose \
  --database postgresql

wildo align-deps --write
wildo assets sync
wildo config sync
wildo dev start

init --check verifies development tools without scaffolding. The ordinary init path renders files, installs dependencies and performs initial compilation unless --skip-install is selected. Follow the command’s reported next steps if installation or initial compilation needs attention. --config-only has a different purpose: it writes the application configuration rather than the complete skeleton.

Know which decisions the scaffold connects
Created elementIts role in the application
SpecificationsThe business and interface descriptions that guide implementation
Shared libraryResource definitions, relationships and shared contracts
Backend and frontendThe processes that consume those contracts
Infrastructure declarationsEnvironment and service choices used to derive process configuration
Workspace configurationPackage membership, TypeScript settings and dependency versions
Delivered framework knowledgeTemplates, references, skills and rules available to development tools

The generator derives dependency pins from framework metadata and development package lists from the workspace it actually creates. Framework-developer mode links to a checkout; application-creator mode uses published packages. The selected delivery mode changes dependency resolution, not the business role of each package.

Give each local application its own space

Initialization registers the local environment, provisions its secret material and allocates a port block by inspecting authored sibling application configurations under the framework checkout’s examples/ directory. --port-base supplies an explicit starting port when the workspace needs a deliberate allocation. It is still the operator’s responsibility to resolve unrelated processes already listening on a chosen port.

Administrator identity belongs to local initialization, not a reusable module. Optional --admin-email, --admin-first-name and --admin-last-name flags must be supplied together to bypass identity prompts. Keep passwords in the supported local secret flow; omit --admin-password to let initialization generate one.

Distinguish repair from regeneration

Re-running wildo init inside the application it created uses a repair path: it reuses administrator identity from usable saved secrets and backfills missing secret material without rotating existing credentials. If usable secrets are absent, it resolves the administrator identity again from supplied flags or interactive input. It does not overwrite your application with a fresh skeleton. Initial scaffolding refuses an unrelated non-empty target directory.

After a framework upgrade, dependency alignment and wildo assets sync refresh the delivered inputs. Configuration synchronization derives environment artifacts from your current declarations. A working platform registration is required for the deployment-related synchronization phase; it is separate from creating the local application structure.

Add a feature with its connections Mechanism

A module is useful when the application can discover and run it. Creating its files is only part of the work; its shared definitions, specifications and interface also need their registrations.

Composition scenarios describe these changes together. Preview the planned files and edits, apply them, then develop the new piece as application-owned code.

Example: Add a customer-support module

A support module starts with connected places for its shared definitions, business specifications, backend implementation and interface. The scenario registers that structure; you then add the request resources and the behavior your team needs.

A feature addition connects source code, module wiring and specifications.
For engineers

Run wildo compose inside an application to discover its available scenarios. The following is an illustrative add-module invocation using every required variable from the shipped manifest. Replace @service-desk/shared-lib with the actual shared-library package name.

wildo compose
wildo compose add-module \
  --var moduleId=customer-support \
  --var moduleCamel=customerSupport \
  --var modulePascal=CustomerSupport \
  --var 'purpose=Organize customer requests and their resolution' \
  --var 'businessCapability=Resolve customer requests' \
  --var businessDomain=customer-service \
  --var sharedLibPackage=@service-desk/shared-lib \
  --dry-run

The preview lists file writes, declared edits, already-present elements and conflicting files. It includes required engine peer declarations and applicable provider overrides, showing dependency names and values alongside the affected paths. Review that plan, then repeat the same invocation without --dry-run to apply it. Required variables and naming patterns are validated before planning the file changes.

Follow one module through the application

Example: the customer-support module produced by the command above, using the shipped skeleton layout with backend-api, frontend, shared-lib and specifications packages. The scenario creates a connected starting point. It does not implement a support feature: the initial resource, operation and view registries are empty.

You supply the module identity and business purpose. The scenario renders its descriptors and edits the host registrations below. The framework then consumes those registrations; your application code supplies the resources and behavior you add afterward.

Give the shared model one module identity

In shared-lib/src/modules/customer-support/index.ts, the generated descriptor connects the module’s field identifiers, resource configurations and relationships. The imports point to registries created alongside it:

import type { SharedSaaSModule } from '@wildo-ai/saas-models';

import { CustomerSupport_ResourceFieldIdentifier } from './resources/customer-support.resources-types';
import { moduleResourcesConfigurationsFactoryMap } from './resources/customer-support.resource-configs';
import { moduleResourcesRelationships } from './resources/customer-support.relationships';

const customerSupportModule: SharedSaaSModule = {
  moduleId: 'customer-support',
  kind: 'domain',
  resourceConfigurations: moduleResourcesConfigurationsFactoryMap,
  resourceFieldIdentifiers: CustomerSupport_ResourceFieldIdentifier,
  resourceRelationships: moduleResourcesRelationships,
};

export * from './resources';
export default customerSupportModule;

The identity is customer-support in every layer. Adding a resource later fills these registries; naming a module alone does not create an API or a form.

Keep the business meaning alongside the model

The specification declaration in specifications/src/modules/customer-support/index.ts explains the purpose behind the module. This selected declaration uses the variables supplied to the scenario:

import {
  type ModuleBusinessSemantics,
} from '@wildo-ai/saas-specifications';

export const customerSupportModuleBusinessSemantics: ModuleBusinessSemantics = {
  relatedModuleId: 'customer-support',
  purpose: 'Organize customer requests and their resolution',
  businessCapability: 'Resolve customer requests',
  businessDomain: 'customer-service',
  primaryActors: [
    'organization member',
    'organization admin',
  ],
  mainResources: [],
  supportingResources: [],
  integrationSurfaces: [],
};

The empty resource lists are intentional at this stage. As resources are added, the specifications explain which are central to the module and how they support its purpose.

Connect interface contributions and backend behavior

In frontend/src/modules/customer-support/index.ts, the generated frontend descriptor collects resource UI behavior, composite views and shell contributions:

import type { FrontendModule } from '@wildo-ai/saas-frontend-lib';

import moduleResourcesUIBehavior from './resources/index.js';
import moduleAppLevelViewsCompositeViews from './app-level-views/index.js';
import moduleAppShellModuleConfig from './app-shell.module.frontend.js';

const customerSupportFrontendModule: FrontendModule = {
  moduleId: 'customer-support',
  resourceUIBehavior: moduleResourcesUIBehavior,
  compositeViews: moduleAppLevelViewsCompositeViews,
  ...moduleAppShellModuleConfig,
};

export default customerSupportFrontendModule;

The shell contribution starts with an empty navigation group. Creating this descriptor does not add a customer-support screen; actual resources and view contributions provide the visible experience.

The backend has a different owner. backend-api/src/modules/customer-support/index.ts supplies the descriptor discovered by the existing backend directory scan:

import type { BackendOwnedModule } from '../../backend-owned-module.js';
import moduleResources from './resources/index.js';

const customerSupportBackendModule: BackendOwnedModule = {
  moduleId: 'customer-support',
  kind: 'domain',
  backendModule: moduleResources,
};

export default customerSupportBackendModule;

backendModule starts with the module’s empty resource-operation collection. Later additions supply implementations here; the module directory is the discovery boundary.

Register the module in the host that will use it

These are selected resulting declarations from separate files, not one file to paste over the application’s existing registries. The scenario adds the corresponding imports and preserves existing entries.

// shared-lib/src/modules-registry.shared.ts
export const applicationSharedModules: SharedSaaSModule[] = [
  customerSupportModule,
];

// specifications/src/module-registry.specification.ts
export const applicationModuleBusinessSemantics: ModuleBusinessSemantics[] = [
  customerSupportModuleBusinessSemantics,
];

// frontend/src/modules/index.ts
export const applicationFrontendModules: FrontendModule[] = [
  customerSupportFrontendModule,
];

// wildo.saas.config.ts — the service keys in this skeleton
export const applicationModules = {
  'customer-support': { services: ['backendApi', 'app'] },
};

The shared registry includes the module in the model, the specification registry includes its business meaning, and the frontend registry includes its interface contributions. The service binding declares which configured services use the module. Source registration and service selection answer different questions; both matter.

Backend discovery already exists in backend-api/src/modules/index.ts. This selected existing code scans child module exports and assembles their backend contributions; the scenario does not append a separate backend array entry:

const applicationBackendOwners = await scanSubdirDefaultExports<BackendOwnedModule>({
  importMetaUrl: import.meta.url,
});

const applicationBackendDomainModules: BackendDomainModule[] = applicationBackendOwners.flatMap((ownedModule) =>
  ownedModule.backendModule ? [ownedModule.backendModule] : []
);

const backendModules = mergeBackendDomainModules(...applicationBackendDomainModules);
Carry the registration into the companion’s observed model

The shared package’s existing companion-exports.ts already loads the assembled sharedModules. This loader stays unchanged when the scenario adds the module upstream:

async function loadSharedCompanionData() {
  return import('./modules-registry.shared.js');
}

export async function loadSharedModules(): Promise<SharedSaaSModule[]> {
  const { sharedModules } = await loadSharedCompanionData();
  return sharedModules;
}

The existing sharedCompanionExports object exposes loadSharedModules. The package’s ./companion entry points to the emitted companion surface. Let the application’s development watchers compile the changed packages, then synchronize changed configuration for the selected environment. The companion resolves the requested service and the targets required by that introspection behavior; it does not infer them from a newly created directory.

Use the running companion’s menu to choose a service key and an available behavior:

# Discover the actual serving surface and its supported queries.
wildo context health
wildo context list

# In this skeleton, backendApi is the backend service key.
wildo context info resources-registry --service backendApi
wildo context coherence

These are verification commands to run in your application, not captured output from a deployed support feature. A health response establishes availability. An empty new module contributes no resources to resources-registry, so the absence of a support resource is expected until one is declared. Once a resource and its behavior are added, check their presence in the resolved model and exercise the actual API or screen. A successful compilation or coherence report alone does not demonstrate that business flow.

Choose the right scenario boundary
InputWhat it controls
Scenario manifestRequired variables, generated file paths and edits to existing files
Template file treeInitial application-owned implementation files
Structured TypeScript editsImports, registrations, enum members and configuration entries
JSON and package editsWorkspace or dependency declarations needed by the new piece
Post-apply notesFollow-up steps, such as adding resources or allowing watchers to compile changes

Scenario selection is per reference: an application-delivered scenario takes precedence over the same reference in the framework checkout. References found only in the checkout remain available as a fallback. add-module supplies a connected empty shape; add-resource adds its business records afterwards.

Keep later edits under application ownership

Planning skips byte-identical generated files and edits whose required elements are already present. A generated target with different content becomes a collision, and apply refuses that plan before starting its writes. Reconcile deliberate application changes through version control rather than expecting a scenario to merge them.

This preflight protects against known conflicts; applying a plan performs filesystem writes sequentially. Keep the change reviewable in version control, including recovery from an interrupted write or a later post-apply failure. After a successful addition, let the development watchers compile the affected packages and synchronize configuration when runtime bindings change.

Configure and run development

One command line for application work Tool

Wildo brings application setup, configuration, local operation and inspection into one command line. Each command understands the workspace it operates on, so the application’s declared structure carries into everyday development work.

Developers and coding agents use the same commands. Built-in help exposes the available operations and their options; the application’s business code remains yours to write.

Example: Move from a configuration change to a running application

After changing an application’s configuration, a developer refreshes the generated files, checks the local environment and starts a development session. The same tool can then ask the running companion what the application exposes.

The wildo command line leads to creating, configuring and running an application.
For engineers

Start with the installed tool’s own help. The listing is derived from registered command metadata, including descriptions, arguments and flags.

# Discover commands and inspect a specific operation.
wildo help
wildo config sync --help

# Inspect the local and live-context command contracts.
wildo local dev --help
wildo local doctor --help
wildo context info --help

Command availability depends on workspace scope. Run application commands from that application’s workspace; framework-maintenance commands additionally require a framework checkout. A command unavailable in the current scope reports why instead of attempting to operate on an unrelated directory.

Keep the stages of application work distinct
WorkCommand familyWhat it operates on
Refresh derived configurationwildo configAuthored application and environment declarations
Run and inspect development infrastructurewildo localThe selected local environment and supervised application
Query application knowledgewildo contextCompanion-backed inspection, plus named local authority/configuration checks
Compose reusable partswildo composeApplication composition and its declarations
Work with reusable moduleswildo registryModule discovery, installation and publication

context health, list, info, coherence and journey query the companion. context jurisdictions and context assurance-basis inspect local configuration, specifications and installed authority definitions without it. Those local checks are separate commands, not fallbacks for a failed companion request.

These families share the CLI context, but their effects differ. A context query reads; configuration sync writes generated artifacts; a lifecycle command starts or stops processes. Consult the specific command’s help when automating it rather than assuming every family accepts the same flags.

Understand what the tool automates

Commands declare a phrase-shaped name such as config sync. The registry resolves the longest matching command name, which supports nested command families without a separate parser for each one. Discovery loads command files, and duplicate names fail instead of allowing one implementation to silently replace another.

The tool coordinates framework-owned operations. It does not turn artifact generation into a deployment: config sync produces deployment inputs. Generated workflows build images; the Kubernetes workflow also applies manifests, while Compose rollout requires your host-transfer and deployment steps. Application behavior, release review and the operating environment remain explicit decisions.

From a configuration change to an application query

Use one application workspace and its configured local Docker Compose environment. First inspect the command help, validate the declaration, synchronize derived files and read the diagnosis:

# Discover the flags supported by this installed command.
wildo config sync --help

# Check, regenerate, then diagnose the local environment.
wildo config validate --env local
wildo config sync --env local
wildo local doctor

Resolve reported failures before starting wildo local dev in that terminal. If a development session already owns the workspace, use it rather than creating a second owner. From a second terminal in the same application, run wildo context health, then wildo context journey to inspect eligibility and work in flight. Health establishes reachability; the specific query and compiled-output freshness establish what application information is available.

Keep delivered assets aligned with their source

wildo assets sync replaces the framework-owned template mirror under .wildo-saas/templates/; keep application customizations out of that replaceable mirror. Templates follow the CLI’s framework assets. Documentation, skills and rules instead come from the application’s installed @wildo-ai/framework-knowledge package.

If the command reports version skew, align the CLI installer with the application’s knowledge-package version using its reported --cli-version value, then run wildo assets sync again. Synchronizing assets does not upgrade the CLI. A missing knowledge package requires installation before its documentation and skills can be delivered.

Carry configuration changes into generated files Tool

One application definition feeds several working files: process settings, service connections, container manifests and deployment workflows. Wildo refreshes those outputs together, in the order their dependencies require.

Change the authored configuration, then synchronize it. This keeps generated files aligned without asking developers to repeat the same decision in each format.

Example: Change a service connection once

An application changes where a backing service runs. Synchronization reconciles the environment declaration, prepares required secret material and regenerates the affected connection settings and deployment artifacts.

Authored configuration feeds environment settings, service configuration and runtime files.
For engineers

Run these commands from an application workspace with its environment configured. The first command performs the normal sync for the local environment. The narrower command refreshes process environment files when that is the only output needed.

# Refresh the normal set of derived outputs.
wildo config sync --env local

# Or select a specific output domain.
wildo config sync --env local --domain env-files

# Check configuration and, for Kubernetes, rendered manifests.
wildo config validate --env local

The --env value is your configured environment name. Generated CI workflows build images. The Kubernetes workflow also applies manifests; the Compose workflow leaves host transfer and rollout to your deployment setup. Generating these files does not itself deploy the application.

Know which outputs are regenerated
Sync domainPurpose
env-filesPer-process environment files and their derived service connections
configEnvironment deployment artifacts, including runtime-specific configuration
manifestLocal Docker Compose or Kubernetes manifests; remote environments are skipped
cicdDeployment and configuration-validation workflows
secretsExplicit secret rotation, requiring separate authorization

The normal local selection is config and env-files. Select manifest or cicd explicitly when regenerating those outputs; CI adds workflow generation when an application root is available. Provider runtime artifacts are synchronized through the same application generation path.

Missing framework-managed material is provisioned additively before dependent generation; existing material is not rotated merely because new configuration needs another secret.

--force permits overwriting generated files without the normal confirmation. It does not authorize secret rotation: that requires --rotate-secrets. Changing the initialized platform’s database engine is also a separate decision, not a consequence silently authorized by --force.

Separate authored changes from regeneration

config sync projects declarations into generated outputs. config mutate changes supported existing values in the application declaration, with a dry-run option. These are the actual command forms for changing a service’s local port; use a service key present in your application:

# Preview a proposed declaration change.
wildo config mutate set-service-port --service main_backend_api --port 4302 --dry-run

# Apply that declaration change after reviewing it.
wildo config mutate set-service-port --service main_backend_api --port 4302

This is an illustrative port choice, not a required Wildo port. Mutations reject unknown paths and name the failing segment. Regenerate relevant outputs after changing the declaration. config reapply-declaration handles another job: refreshing declaration-managed application configuration stored on the platform, without recreating its credentials or data.

Read validation at the right level

Validation checks configuration coherence. For Kubernetes, the default manifest check renders infrastructure and platform manifests into a temporary sandbox and parses them. For other runtimes, it reports a successful skip; this is not a Docker Compose render/parse check.

For an environment configured to use Kubernetes, check the application’s deployment artifacts after generating them. The example uses an environment named local; choose the registered environment that owns your output:

# Inspect the application Kubernetes output already written by sync.
wildo config validate --env local --domain manifest --deployment-artifacts

This reads the generated application manifests and reports missing output rather than regenerating it. Neither validation mode applies anything to a cluster. Application deployment generation has its own platform and registration prerequisites; if sync reports that generation was skipped, a successful sandbox check does not establish that application workloads were produced.

In CI, --ci changes the credential source to the pipeline’s flat environment variables. It does not change the deployment output directory. Treat generated secret-bearing files as derived private output, not as a replacement for the authored configuration.

Keep local overrides outside generated files

The frontend’s .env and .env.example are both generated. Put deliberate frontend-only overrides in .env.local, which Vite reads with higher precedence and this generator leaves alone. Do not carry that filename rule over to unrelated backend or specialized outputs.

For the env-files domain, existing files require confirmation unless --force is given. Declining, or running non-interactively without force, can skip that environment successfully. Read the reported writes and skips; a successful exit does not mean every existing file was regenerated.

Recover from a failed synchronization

A synchronization can leave successful phase writes in place when another phase fails. Read the phase outcomes and the named error, fix its cause, then retry the needed domain. Exceptions or prerequisite failures may return before the final phase summary.

For example, after correcting an env-file problem, use wildo config sync --env local --domain env-files. This narrows the requested output, but can still perform prerequisite configuration reconciliation, missing-material provisioning and provider-runtime refresh. It is not a rollback or a promise to touch only one file. Inspect the result before restarting consumers.

Run and recover your local workspace Tool

Wildo coordinates the supporting services and application processes needed for local development. Startup checks the environment and waits for dependencies before launching the work that relies on them.

When something is wrong, inspection, repair and reset are separate actions. You can diagnose the workspace or repair its setup while keeping local data, and choose a fresh start deliberately.

Example: Resume work after an interrupted session

A developer checks the workspace after a machine restart, reads the diagnostic result and starts a new supervised session. If setup needs repairing, initialization restores the local environment without deleting backing-service data.

A local stack groups database, queue and storage services with start, status and stop controls.
For engineers

From the application workspace, use this supervised sequence with a local Docker Compose environment. The inspection commands are independent reads; run them in another terminal while the session remains active.

# Own the development session in this terminal.
wildo local dev

# In another terminal, inspect what is running.
wildo local status
wildo local doctor

local dev claims ownership before replacing stale root-scoped processes, checks startup prerequisites, prepares infrastructure and waits for readiness. Application runtimes start after their prerequisites. The supervised session is more than a command that launches several processes simultaneously.

local dev-status adds build, runtime-gate, supervisor and endpoint detail when a framework checkout and its diagnostic collector (local-dev-status.mjs) are available for the targeted application. It is not a prerequisite for ordinary status and doctor inspection. local status addresses infrastructure status. local doctor combines shared startup preconditions with runtime diagnostics, so a health problem can be located at the appropriate layer.

Choose the effect on processes and data
CommandIntended resultEffect on local data
wildo local upBring supporting infrastructure upRetains existing backing data
wildo local downStop local infrastructure and platform servicesRetains backing data
wildo local initInitialize or repair setup and registrationPreserves backing-service data
wildo local reinitRecreate the local setup in framework-developer modeWipes local data before rebuilding; unavailable in application-creator mode
wildo local resetStop and clear the local environmentWipes local data; leaves startup as the next step

Reset and reinitialization require destructive confirmation. They are not backup or restore operations. The shared data-wipe path is used for both supported local runtime lanes so removing containers or volume handles is not mistaken for removing their underlying host files.

Diagnose before changing the workspace
# Read the diagnosis, including structured output when needed.
wildo local doctor
wildo local doctor --json

# Read infrastructure logs; optionally name a service.
wildo local logs

The doctor reports findings; it does not kill orphaned watchers or repair stale files. Its checks distinguish prerequisites from observations that require a running stack. A stopped daemon can therefore be reported alongside another actionable environment problem.

If the intent is to stop the whole development stack, wildo dev stop-all combines development-process cleanup with infrastructure shutdown. wildo dev force-stop targets development processes, including orphaned root-scoped watchers. These are explicit mutation commands, separate from the diagnostic reads.

The lifecycle commands operate on local development. Remote environment deployment has its own generated artifacts and pipeline; a healthy local session is not evidence that a remote release has been applied.

Initialize without interrupting another owner

local up brings infrastructure up. local init also converges setup, application registration and generated runtime environment files, then checks the registered application’s managed configuration. Runtime targets are derived from the same prepared registration snapshot. This postcondition is narrower than proving every application process or business workflow healthy.

Full initialization can stop processes and refuses while a live development session owns the shared platform. Stop that owner first when full convergence is needed. If the platform is already running and only this application needs registration, use wildo local init --register-only; it reconciles the application without rebuilding the shared infrastructure. Preserving backing data does not mean preserving running processes.

Inspect the application you are changing

Keep development tools connected to your application Tool

Development involves many short actions: inspect a resource, refresh derived content, run assisted work or review its result. Each needs to know which application it belongs to.

The companion provides that application-aware service alongside the development environment. Commands and the workbench can use its context and services while the business application keeps its own runtime.

Example: Return to a project after an interrupted coding run

A developer restarts local development and checks the companion and workbench status. If a previous coding task was interrupted, the companion reconciles its recorded state for review rather than silently undoing its edits. The developer inspects the changes before deciding how to continue.

The companion stays alongside a local workspace and its development tools.
For engineers
Check the application and its development surface separately

Run these commands inside the intended application. Keep the foreground development process in its own terminal:

For this supervised startup sequence, select a local Docker Compose environment.

# Terminal 1: prepare and supervise local application development.
wildo local dev

# Terminal 2: inspect the companion serving that application.
wildo context health
wildo context list

# Separate companion readiness from frontend availability.
wildo workbench status

# Open the local workbench destination after startup.
wildo workbench open

dev start is the narrower delegation to the application’s development script. local dev owns broader local preparation and supervision. Follow the workspace’s existing process ownership rather than launching competing supervisors to repair a missing response.

Keep its responsibilities explicit
ResponsibilityWhat the companion supplies
IntrospectionDerived views of compiled application models and their freshness handling
Authoring and generationApplication-aware services for supported derived content and creation work
Workbench supportExplicitly exposed resources, identity/frontend support and development operations
DiagnosticsReachability, state and recorded execution information

The observed application registry does not mean that every business resource API is exposed on the companion. Startup uses explicit controller/resource exposure. Inspect those contracts when integrating a new development surface.

Recover interrupted work without hiding the changes

This selected startup excerpt from start-companion-application.service.ts shows reconciliation before the HTTP server starts. Logging is retained; surrounding startup stages are omitted:

try {
  const { reconciledTaskIds } =
    await this.codingAgentDispatchService.reconcileInterruptedApplicationCodingTasks();
  this.logDebug('Startup coding-task reconciliation completed', { interrupted: reconciledTaskIds.length });
  if (reconciledTaskIds.length > 0) {
    this.logger.warn(
      'Startup reconciliation terminalized interrupted application-coding task(s) as '
        + 'INTERRUPTED_REQUIRES_REVIEW — a previous companion process left them PROCESSING. '
        + 'Review their captured change sets before retrying.',
      { reconciledTaskIds },
    );
  }
} catch (error) {
  this.logger.warn('Startup coding-task reconciliation failed; continuing (non-fatal by design).', {
    error: describeCaughtError(error),
  });
}
await this.initializePlatformHttpServer(config.customControllers);

Reconciliation makes the interrupted task reviewable and captures the worktree state. It does not revert the files or assert that the unfinished work succeeded. It is best effort so a reconciliation problem does not prevent the companion from starting and making diagnosis possible.

Keep locality and identity separate

The companion refuses a non-loopback HTTP host. Its protected custom routes use a machine-local token stored under the application state directory with restrictive permissions. Reading that token is not the same as a person’s approval or an application role.

The workbench’s platform-operator identity and resource authorization are separate again. The same email address in the business application’s user store does not make the two identities equivalent.

Check compiled publication when the model looks old

The companion observes compiled application surfaces. Let an edited declaration reach those surfaces before expecting inspection to reflect it. Health checks establish reachability, not that the latest source was successfully compiled or the feature was verified.

The model-refresh mechanism explains that boundary; the development interfaces explain how commands and the browser reach the companion.

Inspect what the running application exposes Tool

Ask Wildo about the application’s resources, specifications and relationships from the terminal. The development companion answers from the application it serves, giving developers and coding agents a shared way to inspect its structure.

The available questions come from the running companion itself. Answers identify the companion they came from and report reused results when that information is available. Introspection reflects built application packages; recent source edits need to be compiled before they can appear.

Example: Check what a newly composed module exposes

After adding a resource, a developer queries the service expected to expose it. If the declaration is missing from the returned registry, they check the selected service, registration and compilation before debugging the resource’s business behavior.

The result narrows the investigation: a missing declaration and a declared operation that fails at runtime are different problems.

A terminal query reaches application resources, operations and relationships through the companion and returns an answer.
For engineers

Run from an application workspace whose development companion is running. These are actual command forms, not a simulated response:

# Check the companion and read its current query menu.
wildo context health
wildo context list

# Ask about the application's resolved resources and specifications.
wildo context info resources-registry
wildo context info specification-artifacts

# Inspect cross-family coherence.
wildo context coherence

context list fetches behavior identifiers, supported service kinds and service keys from the companion. It does not keep a second catalogue in the CLI. This matters when the installed command line and companion were built at different times.

Target a service and supply the behavior’s input

context info accepts --service to select a service key published by the menu. Without it, the CLI uses the companion’s reported default backend. If no backend is reported, the command asks for an explicit service instead of guessing.

For a parameterized behavior, --input supplies JSON. Select the behavior and its expected input from the live menu and the corresponding contract. Invalid JSON is rejected before the introspection request.

The client’s request is a selected excerpt from ContextInfoCommand, with its response type annotation omitted; input parsing and service selection happen before it:

const result = await CompanionClient.post(
  '/api/companion/_meta/introspect',
  { serviceKey, behavior, ...(input !== undefined ? { input } : {}) },
  options,
);

This POST asks for a derivation. The context family is read-only: it does not apply a configuration change or repair a reported inconsistency.

Read a concrete output without overstating it

This illustrative source line follows the CLI’s formatter. The address and service key are examples, not a captured run. The application-specific payload follows it:

source: dev-companion http://localhost:4302 · introspection resources-registry on backend · freshness: compiled application packages; companion reused a held derivation
Part of the answerWhat it tells the developerNext check
Companion addressWhich local process answeredConfirm it belongs to the intended application
resources-registry on backendWhich model and service were selectedCompare with the service that should expose the resource
Held derivationThis answer reused a successful derivationCheck compilation and reported freshness after an edit
Resource declaration in the payloadThat declaration is exposed in this modelExercise the operation with its real inputs and permissions

An absent resource calls for a service, registration and compilation check. A present resource shifts the investigation toward its configuration and actual behavior. Neither result is a substitute for running the feature.

Interpret the answer and its provenance

The CLI prints a source line identifying the companion address and queried surface, followed by plain text or pretty-printed JSON. Introspection materializes application packages through their compiled ./companion exports. A source edit must reach those emitted surfaces before an answer can reflect it; the terminal’s source label is not proof that an unbuilt change is already available.

For the connected module example, the new shared descriptor reaches the companion through the existing shared-registry loader. Its initial resource registry is empty: a resource query cannot prove or disprove that empty module’s registration merely by looking for a support resource. After adding a resource, check its resolved declaration and service context, then verify the behavior through the application.

The companion can reuse a successful held derivation or join an identical derivation already in flight. Its watcher observes emitted application files and injected framework bytes, triggering refresh when those inputs change. Without an active watcher, per-read observation provides the fallback. A query therefore need not spawn another subprocess to answer the same question. Journey and coherence reads combine specification exports with working-tree file and Git state. Their provenance therefore differs from a resource introspection result; neither header establishes that every source edit has compiled.

Introspection provenanceHow to read it
Reuse reportedThe companion explicitly marked the answer as a held derivation
Reuse not reportedThe response did not establish whether a held answer or a new derivation supplied it
Unverified after failureNo successful answer is available to use as application evidence

Use the reported service and behavior to identify what was inspected. A successful answer establishes that result, not the freshness of unrelated packages or the success of the business feature.

QuestionCommandInterpretation
Is the companion available?context healthCompanion health response
What can this companion answer?context listThe serving behavior catalogue
What does this application expose?context infoThe requested introspection result
Do related definitions remain coherent?context coherenceThe report, printed without condensing away findings
Where does the creation journey stand?context journeyEligibility counts and reasons, running work and interrupted count

The output includes provenance text as well as structured payloads; a consumer should not treat the entire stdout stream as a bare JSON document. Catalogue and journey reads have a bounded read timeout, while subprocess-based introspection has a longer one.

A companion failure is reported with a direction to context health; there is no fallback to a CLI-authored approximation of the application. Coherence reporting explains problems but does not itself block a release or mutate the definitions.

Share the implementation. Keep the application deliberate.

A reusable module gives useful work a home beyond the first application that needed it.

Wildo connects publication, version selection and source placement. Each application keeps ownership of the decisions that turn the shared piece into its own working feature.

Building a B2B product or an internal tool?

Wildo is not self-service yet. Tell us what you have in mind and we will say plainly whether it fits, and what happens next.