Plugin API Reference

This document provides complete reference documentation for the TeamIDE Plugin API, available via window.__teamide.

Overview

The Plugin API is the official interface for plugins to interact with TeamIDE. It provides safe, controlled access to IDE functionality without exposing internal implementation details.

// Access the API
if (window.__teamide) {
  // API is available
  const projectId = window.__teamide.getProjectId();
}

Important: Always check if window.__teamide exists before using it. During development or in certain contexts, it may not be available.

API Methods

openFile

Opens a file in the Code module editor.

openFile(path: string, projectId?: string): Promise<void>

Parameters:

Name Type Required Description
path string Yes Path to the file (relative to repository root)
projectId string No Environment/project ID. Defaults to current project

Returns: Promise<void> - Resolves when the file is opened

Behavior: - Switches to the Code module automatically - Opens the file in the editor - If no project is selected, logs a warning and returns

Example:

// Open a file in the current project
await window.__teamide.openFile('/src/index.ts');

// Open a file in a specific project
await window.__teamide.openFile('/README.md', 'project-123');

// Handle case where no project is selected
const projectId = window.__teamide.getProjectId();
if (projectId) {
  await window.__teamide.openFile('/package.json');
} else {
  console.log('Please select a project first');
}

getProjectId

Gets the current environment/project ID.

getProjectId(): string | null

Parameters: None

Returns: string | null - The current project ID, or null if no project is selected

Example:

const projectId = window.__teamide.getProjectId();

if (projectId) {
  console.log('Current project:', projectId);
  // Proceed with project-specific operations
} else {
  console.log('No project selected');
  // Show a message or disable functionality
}

Notes: - The project ID is also called “environment ID” internally - It identifies the current working context (cloned repository) - Returns null when viewing “Local” or “All Owners” without a specific repo


switchModule

Switches to a different module tab.

switchModule(moduleId: string): void

Parameters:

Name Type Required Description
moduleId string Yes The ID of the module to switch to

Returns: void

Built-in Module IDs:

Module ID Description
code Code editor and file explorer
terminal Terminal overlay
browser Embedded web browser

Example:

// Switch to the terminal
window.__teamide.switchModule('terminal');

// Switch to the code editor
window.__teamide.switchModule('code');

// Switch to another plugin (if installed)
window.__teamide.switchModule('my-other-plugin');

Notes: - For overlay modules (like Terminal), this toggles the overlay visibility - Switching to a non-existent module ID has no effect - Plugins can switch to other plugins using their plugin ID


getGitHubToken

Gets the GitHub access token for the current owner.

getGitHubToken(): string | null

Parameters: None

Returns: string | null - The GitHub access token, or null if not available

Example:

const token = window.__teamide.getGitHubToken();

if (token) {
  // Make authenticated GitHub API calls
  const response = await fetch('https://api.github.com/user', {
    headers: {
      'Authorization': `Bearer ${token}`
    }
  });
  const user = await response.json();
  console.log('Logged in as:', user.login);
} else {
  console.log('No GitHub account connected');
}

Notes: - Returns null if no owner is selected in the top bar - Returns null if the owner doesn’t have a GitHub token - Tokens are managed through Settings > Accounts - Use responsibly - don’t expose tokens in logs or UI


getGitHubUsername

Gets the GitHub username of the current owner.

getGitHubUsername(): string | null

Parameters: None

Returns: string | null - The GitHub username, or null if not available

Example:

const username = window.__teamide.getGitHubUsername();

if (username) {
  console.log('Current GitHub user:', username);
} else {
  console.log('No GitHub account selected');
}

Notes: - Returns null if no owner is selected - This is the login/username, not the display name


getPluginSettings

Retrieves persisted settings for a plugin.

getPluginSettings(pluginId: string): Promise<Record<string, unknown> | null>

Parameters:

Name Type Required Description
pluginId string Yes The plugin ID to get settings for

Returns: Promise<Record<string, unknown> | null> - The settings object, or null if none exist

Example:

// Load settings when plugin activates
async function loadSettings() {
  const settings = await window.__teamide.getPluginSettings('my-plugin');

  if (settings) {
    console.log('Loaded settings:', settings);
    applyTheme(settings.theme as string);
    setRefreshInterval(settings.refreshInterval as number);
  } else {
    console.log('No saved settings, using defaults');
    applyTheme('light');
    setRefreshInterval(60);
  }
}

Notes: - Settings are stored persistently on the local machine - Returns null if no settings have been saved - Settings are specific to each plugin ID - The return type is generic - cast values as needed


savePluginSettings

Saves settings for a plugin.

savePluginSettings(pluginId: string, settings: Record<string, unknown>): Promise<void>

Parameters:

Name Type Required Description
pluginId string Yes The plugin ID to save settings for
settings Record<string, unknown> Yes The settings object to save

Returns: Promise<void> - Resolves when saved, rejects on error

Example:

// Save settings when user changes preferences
async function saveSettings(theme: string, refreshInterval: number) {
  try {
    await window.__teamide.savePluginSettings('my-plugin', {
      theme,
      refreshInterval,
      lastUpdated: Date.now()
    });
    console.log('Settings saved');
  } catch (error) {
    console.error('Failed to save settings:', error);
  }
}

// Usage
await saveSettings('dark', 30);

Notes: - Settings are saved persistently - Overwrites any existing settings for the plugin - Keep settings small - avoid storing large data - Use serializable values (no functions, circular references)


Available Global Libraries

Plugins have access to these libraries without bundling them:

Vue 3

import { ref, computed, defineComponent, h } from 'vue';

// All Vue 3 Composition API features are available
const count = ref(0);
const doubled = computed(() => count.value * 2);

Available exports: All of Vue 3’s public API including: - Reactivity: ref, reactive, computed, watch, watchEffect - Components: defineComponent, h, createApp - Lifecycle: onMounted, onUnmounted, onActivated - And more…

Pinia

import { defineStore } from 'pinia';

const useMyStore = defineStore('my-plugin', {
  state: () => ({ items: [] }),
  actions: {
    addItem(item) {
      this.items.push(item);
    }
  }
});

Available exports: Full Pinia API including: - defineStore - storeToRefs - mapState, mapActions (Options API helpers)

Quasar

import { useQuasar, QBtn, QCard } from 'quasar';

// Use Quasar utilities
const $q = useQuasar();
$q.notify('Hello!');

Available exports: Full Quasar component library including: - All components (QBtn, QCard, QInput, etc.) - Composables (useQuasar, useDialogPluginComponent) - Utilities (date, format, colors)


Module Definition Interface

When creating a plugin, export a ModuleDefinition object:

interface ModuleDefinition {
  // Required
  id: string;                           // Unique identifier
  name: string;                         // Display name
  icon: string;                         // Material icon name
  version: string;                      // Semantic version
  navigationComponent: Component;       // Left panel
  mainComponent: Component;             // Center panel

  // Optional
  contextComponent?: Component;         // Right panel
  order?: number;                       // Tab order (lower = first)
  renderMode?: 'default' | 'overlay';   // How to render
  requiresRepository?: boolean;         // Disable without repo
  dependencies?: string[];              // Required plugins/modules

  // Lifecycle hooks
  onRegister?: () => void | Promise<void>;
  onActivate?: () => void | Promise<void>;
  onDeactivate?: () => void | Promise<void>;
}

Properties

Property Type Required Description
id string Yes Unique identifier matching manifest
name string Yes Display name in UI
icon string Yes Material Design icon name
version string Yes Semantic version (e.g., “1.0.0”)
navigationComponent Component Yes Vue component for left panel
mainComponent Component Yes Vue component for center area
contextComponent Component No Vue component for right panel
order number No Tab sort order (default: 100)
renderMode string No ‘default’ or ‘overlay’
requiresRepository boolean No If true, tab disabled without repo
dependencies string[] No IDs of required modules

Lifecycle Hooks

Hook When Called Async Description
onRegister Plugin loads Yes One-time initialization
onActivate Tab becomes active Yes Setup when tab is shown
onDeactivate Tab becomes inactive Yes Cleanup when tab is hidden

Feature Toggle Integration

Check if features are enabled using the features system:

// In your plugin code
import { isFeatureEnabled } from '@teamide/features';

// Check feature state
if (isFeatureEnabled('my-plugin-dark-mode')) {
  applyDarkTheme();
}

Note: The features API is injected at runtime. Define features in features.json.


TypeScript Definitions

Add this to your plugin’s types.d.ts:

interface PluginAPI {
  openFile: (path: string, projectId?: string) => Promise<void>;
  getProjectId: () => string | null;
  switchModule: (moduleId: string) => void;
  getGitHubToken: () => string | null;
  getGitHubUsername: () => string | null;
  getPluginSettings: (pluginId: string) => Promise<Record<string, unknown> | null>;
  savePluginSettings: (pluginId: string, settings: Record<string, unknown>) => Promise<void>;
}

declare global {
  interface Window {
    __teamide?: PluginAPI;
  }
}

export {};

Error Handling

All API methods handle errors gracefully:

// getPluginSettings returns null on error
const settings = await window.__teamide.getPluginSettings('my-plugin');
// settings is null if there was an error

// savePluginSettings throws on error
try {
  await window.__teamide.savePluginSettings('my-plugin', data);
} catch (error) {
  console.error('Save failed:', error);
}

// Synchronous methods return null if unavailable
const token = window.__teamide.getGitHubToken(); // null if not available

Best Practices

Always Check API Availability

// Good
if (window.__teamide) {
  await window.__teamide.openFile(path);
}

// Better - with fallback
async function openFile(path: string) {
  if (window.__teamide) {
    await window.__teamide.openFile(path);
  } else {
    console.warn('TeamIDE API not available');
  }
}

Handle Null Returns

const projectId = window.__teamide?.getProjectId();
if (!projectId) {
  // Show user-friendly message
  showNotification('Please select a repository first');
  return;
}

Cache API References

// Cache the API reference for cleaner code
const api = window.__teamide;

if (api) {
  const projectId = api.getProjectId();
  const username = api.getGitHubUsername();
  await api.openFile('/README.md');
}

Type Your Settings

interface MyPluginSettings {
  theme: 'light' | 'dark';
  refreshInterval: number;
  showNotifications: boolean;
}

async function loadSettings(): Promise<MyPluginSettings> {
  const settings = await window.__teamide?.getPluginSettings('my-plugin');
  return {
    theme: (settings?.theme as MyPluginSettings['theme']) ?? 'light',
    refreshInterval: (settings?.refreshInterval as number) ?? 60,
    showNotifications: (settings?.showNotifications as boolean) ?? true
  };
}

Changelog

Date Change
2026-02-02 Initial documentation