## API Reference

The `api` object is passed to `onActivate()`:

### api.commands

```javascript
// Register a command
await api.commands.register('plugin-id.command-name', {
  title: 'Command Title',       // Shown in Command Palette
  category: 'Category Name',    // Optional grouping
  keybinding: 'Cmd+Shift+P',    // Optional keyboard shortcut
  icon: 'terminal',             // Optional icon (Lucide name or emoji)
  handler: async (args) => {    // Executed when command runs
    // Your code here
  }
});

// Execute another command
await api.commands.execute('other-plugin.command', [arg1, arg2]);
```

**Available Icons:**

Use Lucide icon names (lowercase, kebab-case) or emoji:

| Icon Name | Description |
|-----------|-------------|
| `terminal` | Terminal icon |
| `git-branch` | Git branch |
| `folder` | Folder |
| `file-text` | Text file |
| `zap` | Lightning bolt |
| `search` | Search |
| `settings` | Settings gear |
| `play`, `pause`, `stop` | Media controls |
| `copy`, `clipboard` | Clipboard actions |
| `download`, `upload` | Transfer |

### api.terminal

Requires `terminal:write` and/or `terminal:read` capabilities.

```javascript
// Write to active terminal
await api.terminal.write('echo "Hello World"\n');

// Read full terminal content
const result = await api.terminal.read();
console.log(result.content); // Full buffer content

// Read with options
const result = await api.terminal.read({ scrollback: 100 }); // Last 100 lines

// Get current line (where cursor is)
const current = await api.terminal.getCurrentLine();
console.log(current.content);

// Get last N lines
const lines = await api.terminal.getLastLines(10);
console.log(lines.content); // Last 10 lines joined with \n
console.log(lines.lines);   // Array of 10 lines

// Subscribe to real-time terminal output (requires terminal:subscribe)
await api.terminal.subscribe({ terminalId: 'active' });

// Listen for terminal output events
api.on('terminal:output', (data) => {
  console.log(data); // { terminalId, data, timestamp }
});

// Unsubscribe
await api.terminal.unsubscribe({ terminalId: 'active' });
```

### api.notifications

Show toast notifications in the bottom-right corner.

```javascript
// Basic notification
api.notifications.show({
  type: 'success',  // 'success' | 'error' | 'info' | 'warning'
  message: 'File saved successfully'
});

// With title
api.notifications.show({
  type: 'error',
  title: 'Connection Failed',
  message: 'Unable to reach the server.'
});

// Custom duration (ms) - default is 4000ms
api.notifications.show({
  type: 'info',
  title: 'Tip',
  message: 'Use Cmd+K to open Command Palette',
  duration: 6000
});

// Persistent (duration: 0)
api.notifications.show({
  type: 'warning',
  title: 'Unsaved Changes',
  message: 'You have unsaved changes.',
  duration: 0
});
```

| Type | Icon | Use Case |
|------|------|----------|
| `success` | Green checkmark | Operation completed |
| `error` | Red circle | Something went wrong |
| `info` | Blue info | Tips, information |
| `warning` | Yellow triangle | Caution, attention needed |

### api.exec

Requires `exec` capability and `execPatterns` whitelist in manifest.

```javascript
const result = await api.exec.run('git status', '/path/to/repo');
// result: { stdout, stderr, exitCode }
```

**Manifest requirement:**
```json
{
  "capabilities": ["exec"],
  "execPatterns": ["git *", "npm *", "ls *"]
}
```

### api.filesystem

Requires `filesystem:read` and/or `filesystem:write` capabilities.

```javascript
// Read file
const { content, error } = await api.filesystem.readFile('/path/to/file');

// Write file
await api.filesystem.writeFile('/path/to/file', 'content');

// Read directory
const entries = await api.filesystem.readDir('/path/to/dir');
// entries: [{ name, is_dir, is_file, size, modified }]
```

### api.statusBar

Requires `statusbar` capability.

```javascript
// Add item to status bar
await api.statusBar.addItem({
  id: 'my-item',
  text: 'Status Text',
  icon: 'zap',
  tooltip: 'Hover text',
  position: 'right',       // 'left' or 'right'
  color: '#a78bfa',
  onClick: 'my-plugin.cmd' // Command ID to execute on click
});

// Update existing item
await api.statusBar.updateItem('my-item', { text: 'New Text', icon: 'check' });

// Remove item
await api.statusBar.removeItem('my-item');
```

### api.panel

Requires `panel` capability.

```javascript
// Register a panel
await api.panel.register({
  id: 'my-panel',
  title: 'My Panel',
  icon: 'layout-dashboard',
  position: 'right'  // 'left' or 'right'
});

// Set panel HTML content
await api.panel.setContent('my-panel', '<div>Hello World</div>');

// Show/hide/toggle panel
await api.panel.show('my-panel');
await api.panel.hide('my-panel');
await api.panel.toggle('my-panel');
```

Panel content is rendered as HTML. Style with inline styles:

```javascript
const content = `
  <div style="color: #e4e4e7; padding: 12px;">
    <h3 style="color: #a78bfa;">Title</h3>
    <p>Content here</p>
  </div>
`;
await api.panel.setContent('my-panel', content);
```

### api.http

Requires `http` capability. Uses Electron's `net` module to bypass CORS.

```javascript
const response = await api.http.fetch('https://api.example.com/data', {
  method: 'GET',
  headers: { 'Authorization': 'Bearer token' }
});

// response: { ok, status, statusText, headers, data }
if (response.ok) {
  console.log(response.data);
}
```

**Manifest requirement:**
```json
{
  "capabilities": ["http"],
  "httpDomains": ["api.example.com"]
}
```

### api.storage

Requires `storage` capability. Persistent key-value storage, namespaced per plugin.

```javascript
await api.storage.set('myKey', { foo: 'bar' });
const value = await api.storage.get('myKey'); // { foo: 'bar' }
await api.storage.remove('myKey');
await api.storage.clear();
```

### api.contextMenu

Requires `contextmenu` capability.

```javascript
// Register a context menu item
await api.contextMenu.register('file-panel', {
  id: 'my-action',
  label: 'My Custom Action',
  icon: 'wrench'
});

// Available contexts:
// - 'file-panel'    - Right-click on file/folder
// - 'file-panel-bg' - Right-click on file panel background
// - 'terminal'      - Right-click on terminal
// - 'tab'           - Right-click on tab
// - 'global'        - Available in all contexts

// Update
await api.contextMenu.update('file-panel', {
  id: 'my-action',
  label: 'Updated Label',
  disabled: true
});

// Remove
await api.contextMenu.unregister('my-action');
```

### api.keybindings

Requires `keybindings` capability.

**Manifest-based registration (recommended):**

```json
{
  "contributes": {
    "keybindings": [
      {
        "command": "my-plugin.search",
        "key": "Cmd+Shift+S",
        "label": "Quick Search"
      },
      {
        "command": "my-plugin.run",
        "key": "Cmd+Alt+R",
        "when": "terminalFocus"
      }
    ]
  }
}
```

**Dynamic registration:**

```javascript
await api.keybindings.register({
  command: 'my-plugin.action',
  key: 'Cmd+Shift+X',
  label: 'My Action',
  when: 'always'  // 'always' | 'terminalFocus' | 'editorFocus'
});

await api.keybindings.unregister('my-plugin.action');
const binding = await api.keybindings.get('my-plugin.action');
```

**Key string format:**
- Modifiers: `Cmd`, `Ctrl`, `Alt`, `Shift`
- Combine with `+`: `Cmd+Shift+P`, `Ctrl+Alt+X`
- Single keys: `F1`, `Escape`, `Enter`, `A`

**Context conditions:**
- `always` (default): Works everywhere except when terminal is focused
- `terminalFocus`: Only when terminal is focused
- `editorFocus`: Only when editor is focused

Keybindings are automatically disabled when the terminal is focused (except `terminalFocus` bindings) to avoid conflicts with CLI tools like vim or Claude Code.

### api.themes

Requires `themes` capability.

**Manifest-based registration (recommended):**

```json
{
  "contributes": {
    "themes": [
      {
        "id": "ocean",
        "name": "Ocean Blue",
        "isDark": true,
        "colors": {
          "bgPrimary": "#0a192f",
          "bgSecondary": "#112240",
          "bgTertiary": "#1d3557",
          "bgHover": "#233554",
          "bgActive": "#303c55",
          "textPrimary": "#ccd6f6",
          "textSecondary": "#8892b0",
          "textMuted": "#495670",
          "textInverse": "#0a192f",
          "borderPrimary": "#233554",
          "borderSecondary": "#1d3557",
          "borderFocus": "#64ffda",
          "accent": "#64ffda",
          "accentHover": "#4fd1c5",
          "accentMuted": "#319795",
          "success": "#64ffda",
          "warning": "#ffd166",
          "error": "#ff6b6b",
          "info": "#4299e1",
          "terminal": "#020c1b",
          "selection": "rgba(100, 255, 218, 0.2)"
        }
      }
    ]
  }
}
```

**Dynamic registration:**

```javascript
await api.themes.register({
  id: 'my-theme',
  name: 'My Theme',
  isDark: true,
  colors: { /* all 22 color tokens */ }
});

await api.themes.activate('my-plugin.my-theme');
const themes = await api.themes.list();
const current = await api.themes.getCurrent();
```

**Required color tokens (22 total):**

| Category | Tokens |
|----------|--------|
| Backgrounds | `bgPrimary`, `bgSecondary`, `bgTertiary`, `bgHover`, `bgActive` |
| Text | `textPrimary`, `textSecondary`, `textMuted`, `textInverse` |
| Borders | `borderPrimary`, `borderSecondary`, `borderFocus` |
| Accent | `accent`, `accentHover`, `accentMuted` |
| Semantic | `success`, `warning`, `error`, `info` |
| Special | `terminal`, `selection` |

**Built-in themes:** `dark`, `midnight`, `dracula`, `light`

### api.dialog

Requires `dialog` capability.

```javascript
// Custom dialog with input fields
const result = await api.dialog.show({
  title: 'Enter Info',
  message: 'Please provide the following:',
  fields: [
    { id: 'name', label: 'Name', type: 'text', placeholder: 'Enter name...', required: true },
    { id: 'email', label: 'Email', type: 'text', placeholder: 'your@email.com' }
  ],
  buttons: [
    { id: 'cancel', label: 'Cancel', variant: 'secondary' },
    { id: 'confirm', label: 'OK', variant: 'primary' }
  ]
});
// result: { buttonId: 'confirm', fields: { name: '...', email: '...' } }

// Alert dialog
await api.dialog.alert({ title: 'Alert', message: 'Something happened!' });

// Confirm dialog
const result = await api.dialog.confirm({
  title: 'Confirm',
  message: 'Are you sure?'
});
// result: { buttonId: 'confirm' } or { buttonId: 'cancel' }
```

**Button variants:** `primary`, `secondary`, `danger`

### api.clipboard

Requires `clipboard` capability.

```javascript
await api.clipboard.write('Text to copy');
const { text } = await api.clipboard.read();
```

### api.appRail

Requires `appRail` capability. Add icons to the left navigation bar.

```javascript
await api.appRail.addItem({
  id: 'my-icon',
  icon: 'settings',       // Emoji or Lucide icon name
  tooltip: 'My Panel',
  priority: 50,           // Lower = higher in list
  panelId: 'my-panel'     // Optional: panel to toggle on click
});

await api.appRail.updateItem('my-icon', {
  icon: 'check',
  badge: '5',
  tooltip: 'Updated'
});

await api.appRail.removeItem('my-icon');
```

### api.env

Environment variables for plugin configuration, defined in manifest.

```javascript
const apiKey = await api.env.get('API_KEY');
const allEnv = await api.env.getAll();
// Returns: { API_KEY: '...', DEBUG_MODE: 'true', ... }
```

Users set values in Settings > Plugins > [Your Plugin] > Environment Variables.

### api.on / api.off

Event subscription for plugin-related events.

```javascript
api.on('terminal:output', (data) => {
  // { terminalId, data, timestamp }
});

api.on('panel:action', (data) => {
  // { panelId, actionId }
});

// Unsubscribe
api.off('terminal:output', handler);
```

| Event | Description | Data |
|-------|-------------|------|
| `terminal:output` | Real-time terminal data | `{ terminalId, data, timestamp }` |
| `panel:action` | Panel button clicks | `{ panelId, actionId }` |
