Basic project environment
This small JavaScript package adds an “Example server” environment type. It uses a host-rendered create form and returns a ready environment rooted at the user’s selected directory.
Package shape
terminay-example-provider/
├── package.json
└── extension.js
This is intentionally minimal: the package manifest lives in package.json, and
extension.js contains the provider definition and runtime.
Declare the contribution
{
"name": "terminay-example-provider",
"version": "1.0.0",
"type": "module",
"exports": { ".": "./extension.js" },
"terminay": {
"manifestVersion": 1,
"id": "dev.example.basic",
"displayName": "Example server",
"description": "Minimal project-environment provider.",
"api": "^1.1.0",
"engines": { "terminay": ">=1.0.0", "node": ">=22" },
"entrypoint": "extension.js",
"permissions": [],
"contributes": {
"projectEnvironments": [{
"id": "dev.example.basic/server",
"displayName": "Example server",
"capabilities": ["infrastructure"]
}]
}
}
}
The project-environment contribution declares the provider ID and infrastructure
capability. Its ID is repeated as providerId at registration time.
Register a definition and runtime
import { defineExtension } from "@terminay/extension-api";
const status = {
state: "available",
message: "Example is ready",
defaultRoot: "/workspace",
revision: 1,
};
export default defineExtension({
activate(context) {
context.registerProjectEnvironmentProvider({
definition: {
providerId: "dev.example.basic/server",
displayName: "Example server",
capabilities: ["infrastructure"],
createForm: {
id: "dev.example.basic/create",
title: "Create example environment",
sections: [{
id: "connection",
title: "Connection",
fields: [{ id: "root", type: "text", label: "Default root", required: true }],
}],
submitLabel: "Create",
},
},
runtime: {
async testProfile() { return []; },
async resolveOptions() { return { options: [] }; },
async createEnvironment(request) {
return {
state: "ready",
providerState: { root: request.values.root ?? "/workspace" },
status,
};
},
async resumeOperation(request) {
return { state: "ready", providerState: request.providerState, status };
},
async getStatus() { return status; },
async invokeAction(request) {
return { state: "complete", providerState: request.providerState, status };
},
},
});
},
});
Terminay renders createForm itself. The runtime validates profiles, resolves
options, creates or resumes the environment, reports status, and handles declared actions.
Package it
cd packages/extension-api/examples/basic-provider
npm pack
# Upload terminay-example-provider-1.0.0.tgz in Settings → ExtensionsGive a copied provider a new extension ID and provider ID before publishing it. For optional operations such as updates, deletion, profiles, secrets, and dependencies, see the project-environment API.