Build a project-environment provider

A project-environment provider lets Terminay create and manage one kind of environment in a project: an SSH host, a VM, a cloud workspace, or your own service. The provider describes its host-rendered forms and implements the lifecycle work.

What you build

This guide registers a minimal preview provider. It saves an endpoint in a profile, validates it, creates an available environment, and reports its status. Adapt the runtime methods to call your service.

Declare the contribution

The manifest makes the provider visible to Terminay before extension code starts. The contribution ID must correspond to the registered providerId.

JSON
{
  "manifestVersion": 1,
  "id": "acme.preview-environment",
  "displayName": "Preview environments",
  "api": "^1.2.0",
  "engines": { "terminay": "^1.2.0", "node": ">=20" },
  "entrypoint": "dist/index.js",
  "permissions": ["secrets:resolve"],
  "contributes": {
    "projectEnvironments": [{
      "id": "preview",
      "displayName": "Preview environment",
      "capabilities": ["terminal", "filesystem"],
      "profileSave": { "createEnvironment": true }
    }]
  }
}

Use only the environment capabilities you can actually provide. profileSave is opt-in: without it, saving a profile never creates an environment.

Register the definition and runtime

TypeScript
import {
  defineExtension,
  type ProviderRegistration,
} from '@terminay/extension-api';

const preview: ProviderRegistration = {
  definition: {
    providerId: 'preview',
    displayName: 'Preview environment',
    icon: 'cloud',
    capabilities: ['terminal', 'filesystem'],
    profileForm: {
      id: 'preview-account',
      title: 'Preview account',
      submitLabel: 'Save account',
      sections: [{
        id: 'connection', title: 'Connection', fields: [{
          id: 'endpoint', label: 'API endpoint', type: 'url', required: true,
        }] }],
    },
  },
  runtime: {
    async testProfile({ values }) {
      return typeof values.endpoint === 'string' ? [] : [{
        fieldId: 'endpoint', code: 'required', message: 'Enter an API endpoint.',
      }];
    },
    async resolveOptions() { return { options: [] }; },
    async createEnvironment(request) {
      return {
        state: 'ready',
        providerState: { endpoint: request.values.endpoint },
        status: {
          state: 'available',
          defaultRoot: '/workspace',
          revision: 1,
        },
      };
    },
    async resumeOperation() { throw new Error('No operation to resume.'); },
    async getStatus(request) {
      return { state: 'available', revision: 1 };
    },
    async invokeAction(request) {
      return {
        state: 'complete',
        providerState: request.providerState,
        status: { state: 'available', revision: 1 },
      };
    },
  },
};

export default defineExtension({
  activate(context) {
    context.registerProjectEnvironmentProvider(preview);
  },
});

profileForm and createForm are declarative. Terminay renders the fields, validation, progress, confirmations, actions, and status cards; extensions do not supply UI components or styles.

Implement the lifecycle

MethodUse it for
testProfileReturn field-level validation before a profile is saved.
resolveOptionsSupply async options for a declared form source.
createEnvironmentCreate the environment and return ready or pending.
resumeOperationContinue a pending provisioning operation.
getStatusReturn its current state, facts, actions, and revision.
invokeActionRun an action declared in the environment status card.
updateEnvironment, deleteEnvironmentOptional update and deletion flows.
invokeServiceOptional environment-bound capability operation; it is not a general command API.

Every callback receives a deadline, cancellation signal, and—for retried or concurrent mutations—an idempotency key and expected revision. Honour cancellation and use the revision to avoid overwriting a newer environment state.

Next steps

Add credentials or a dependent provider through scoped services. For the complete API surface, see the environment provider reference.