Contributing Guidelines for VSCode‑Logger

Overview

This repository contains a Visual Studio Code extension for streaming logs from embedded Linux devices over SSH. Users configure a list of devices in their settings and the extension lists them in a custom activity‑bar view and opens Webview panels to display live logs or run other actions. Key features include:

  • Device tree and side‑panel views – the activity bar lists devices defined under the embeddedLogger.devices setting. Selecting a device opens a log panel for that device. The side panel also lets users manage up to ten highlight keywords, run one‑off SSH commands and open interactive SSH terminals.

  • Real‑time log streaming – logs are streamed over SSH using a configurable command (defaults to tail -F /var/log/syslog). The extension parses log levels, filters messages, colourises them and supports exporting the visible lines to a file.

  • SSH command execution and terminal – device definitions can include a list of named commands. These commands are executed over SSH through the SshCommandRunner, and output is shown in an information message. Users can also open an interactive SSH terminal session via SshTerminalSession.

  • Configuration file – devices are configured in settings.json via embeddedLogger.devices. Each entry specifies an id, name, host, optional port, username, optional password (used only to migrate into secret storage), an optional privateKeyPath, an optional logCommand, and optional sshCommands. Additional top‑level settings such as embeddedLogger.defaultPort, embeddedLogger.defaultLogCommand, and embeddedLogger.maxLinesPerTab set sensible defaults when omitted.

  • Secure secret storage – legacy plain‑text passwords or passphrases are migrated into VS Code’s Secret Storage during activation. If no secret is stored, the user is prompted when connecting to the device. The PasswordManager handles storage, retrieval, reuse across workspaces and cleanup.

  • Running the extension – to test locally, install dependencies (npm install), compile TypeScript (npm run compile), then press F5 in VS Code to launch a development host with the Embedded Logger and Embedded Devices views.

This document provides guidelines with the intention of making informed, safe and high‑quality contributions to the repository. Follow these instructions to maintain coherence with the existing architecture and to avoid breaking functionality.

Repository structure

Path/Component

Purpose

src/extension.ts

Entry point of the extension. Activates the extension, migrates legacy passwords, registers the device tree and side‑panel views and the embeddedLogger.openDevice command. Handles refreshing when configuration changes. Do not add UI code here or perform heavy network operations at activation.

src/deviceTree.ts

Defines the EmbeddedDevice interface and implements the DeviceTreeDataProvider that populates the activity‑bar device list. Each device item triggers embeddedLogger.openDevice when clicked.

src/sidebarView.ts

Implements the SidebarViewProvider that renders the side‑panel Webview. This panel lists configured devices, lets users manage highlight keywords, run configured SSH commands and open an interactive SSH terminal. It posts messages to the extension host when actions occur and updates when configuration changes.

src/logPanel.ts

Hosts the Webview panel for a device and wires it to an SSH log session. Manages presets (save/delete), exports visible logs, and builds the HTML that loads media/loggerPanel.js and media/loggerPanel.css. Creates Webview messages to update the UI and cleans up sessions on disposal.

src/logSession.ts

Handles the SSH connection and streaming of logs from a device. Retrieves secrets via PasswordManager or prompts the user, connects via ssh2, validates host keys and forwards complete log lines to the Webview. Supports auto‑reconnect with host key validation.

src/sshCommandRunner.ts

Provides the SshCommandRunner class for executing one‑off SSH commands defined in the device configuration. Validates device configuration, sanitises commands to prevent injection, obtains authentication via PasswordManager and executes the command, returning stdout/stderr【847355808337162†L54-L77】.

src/sshTerminal.ts

Provides the SshTerminalSession pseudoterminal for interactive SSH shells. Handles input/output, window resize events and authentication via PasswordManager【596260497884061†L14-L19】.

src/passwordManager.ts

Provides helpers for storing and retrieving device passwords and passphrases using workspace‑aware keys. Supports migrating secrets from previous versions, reusing secrets across workspaces and cleaning up secrets【410299917197563†L50-L59】.

src/configuration.ts

Reads workspace settings and applies default values (e.g., default port, default log command, maximum lines per tab). Ensures that devices inherit sensible defaults and validates configuration.

media/loggerPanel.js

Client‑side JavaScript loaded in the log panel Webview. Maintains state (entries, filters, presets, highlights, bookmarks), parses log levels, handles search, bookmark context menus, auto‑reconnect, auto‑save and more. Provides handlers for saving/deleting presets, exporting logs and updating UI. Consider refactoring into modules due to its size.

media/loggerPanel.css

Styles the log panel Webview content. Uses VS Code theme variables to match the host editor. Adjust styles here rather than inline in HTML. Defines classes for log levels, wrap styles, bookmarks, highlight markers and status indicators.

media/sidebarView.js

Client‑side JavaScript loaded in the side‑panel Webview. Renders device cards, highlight rows and command buttons. Enforces a maximum of ten highlight keywords, generates colour pairs, handles add/remove actions and posts messages back to the extension【540269785496255†L169-L174】.

media/sidebarView.css

Styles the side‑panel Webview. Defines layout for device cards, highlight rows and command buttons using VS Code theme variables.

package.json

Defines extension metadata, activation events, contributed settings, commands and views, and specifies build scripts. If you add new configuration options, update the contributes.configuration section accordingly so they appear in settings UI. The compiled output is emitted to out/ via npm run compile.

Setup and development

  1. Install dependencies: run npm install from the repository root. This installs typescript, ssh2 and VS Code type declarations.

  2. Compile: run npm run compile to transpile the TypeScript in src/ to JavaScript in out/. Do not commit compiled files; they are generated by the build.

  3. Launch the extension: open the repository in VS Code and press F5 to start a development host. The Embedded Logger and Embedded Devices views should appear in the activity bar.

  4. Configure devices: in VS Code settings (or via settings.json), add entries under embeddedLogger.devices as shown in the README. Each entry can include id, name, host, port, username, privateKeyPath, password (only for migrating to secret storage), logCommand and sshCommands (an array of {name, command}). Do not hard‑code devices in the source.

  5. Testing: manually verify that log panels open, logs stream correctly, filtering, search, bookmarks, highlights and presets behave as expected, commands run properly, terminals open and export works. When adding new features, test with multiple devices and both default and custom logCommand values.

  6. Required checks before submitting changes: run the build and lint commands to ensure contributions are stable and adhere to project standards:

    • Build: npm run compile

    • Lint: npm run lint

  7. Documentation: run TypeDoc (npm run docs:typedoc) from the repository root. The generated HTML lives at docs/typedoc/index.html. Keep README.md, this file and AGENTS.md up to date when introducing new behaviour.

Contribution guidelines

General principles

  • Follow the existing architecture: separate concerns between the extension host (backend) and Webview scripts (frontend). Extension code interacts with VS Code APIs and manages SSH connections; UI state and DOM manipulation belong in media/loggerPanel.js and media/sidebarView.js.

  • Use TypeScript: maintain strict typing and respect the compiler options defined in tsconfig.json. Avoid using any unless absolutely necessary. If adding new Webview scripts, consider using TypeScript or JSDoc for better maintainability.

  • Do not store secrets in code: always retrieve passwords and passphrases via PasswordManager【410299917197563†L50-L59】. When adding new sensitive data (e.g., API tokens), use context.secrets and workspace‑aware keys. Never commit secrets to the repository.

  • Be mindful of asynchronous operations: many VS Code APIs return promises. Ensure proper error handling with try / catch and propagate errors to the Webview via callbacks (see LogSessionCallbacks). Surfaces errors in the UI rather than silently logging them.

  • Preserve backward compatibility: when introducing new settings or behaviours, default to existing behaviour to avoid breaking users’ configurations. Update the contributes.configuration schema and provide sensible default values so new options appear in the settings UI.

  • Document your changes: update README.md, this file and AGENTS.md when adding features or altering workflows. Explain new configuration fields, UI elements and behaviours clearly.

  • Avoid side effects at activation: the activation function should be fast. Defer heavy operations until a device is selected or a Webview is shown. Do not perform network operations or prompt for secrets during activation.

Adding new features

  • Extending the device model: if you need extra fields (e.g., log format, environment variables), extend the EmbeddedDevice interface in src/deviceTree.ts and update the configuration schema in package.json. Provide reasonable defaults and migrate any legacy fields similarly to how passwords are migrated.

  • Side‑panel enhancements: to add new actions (e.g., custom device commands, terminal options) or modify highlight behaviour, update src/sidebarView.ts and media/sidebarView.js. Keep highlight limit logic consistent on both ends and ensure commands are sanitised before execution. Use postMessage events to communicate actions to the extension.

  • Custom log parsing: the Webview parses log levels using a regex and maps aliases to canonical names. If you introduce new levels or formats, update levelAliases and levelOrder in media/loggerPanel.js and adjust the parsing logic accordingly. Ensure CSS classes exist for new levels in media/loggerPanel.css.

  • Presets, highlights, search and bookmarks: presets and highlight keywords are stored per device in workspace state. When altering how presets or highlights are saved or loaded, update both backend (logPanel.ts) and frontend (loggerPanel.js, sidebarView.js) to stay in sync. Use postMessage events to inform the Webview of changes. For search and bookmarks, ensure new behaviours are mirrored in the UI and state management.

  • Exporting logs: exports write only the visible (filtered) lines. If you add new data (e.g., timestamps) to entries, update the export to include or exclude them intentionally. Avoid exporting secrets or sensitive device details.

  • SSH commands and terminals: to support additional command types or terminal features, extend src/sshCommandRunner.ts and src/sshTerminal.ts. Sanitize commands to prevent injection【847355808337162†L54-L77】, validate device configuration and handle authentication via PasswordManager. Provide clear status messages using window.showInformationMessage or Webview events.

  • Bastion hosts: devices can specify a bastion jump host with its own host, username, port, fingerprint and authentication. Ensure new SSH features continue to respect bastion tunnelling for log streaming, terminals, SFTP and ad-hoc commands, and store bastion fingerprints separately from device fingerprints.

  • Internationalization and accessibility: avoid hard‑coding user‑visible text in JavaScript. Use VS Code’s localization functions (nls) when adding non‑trivial UI elements. Ensure controls are keyboard accessible, have descriptive ARIA labels and consider colour contrast for highlights and bookmarks.

Working with SSH connections

  • The ssh2 client is instantiated per session in LogSession or SshTerminalSession. When adding features such as key‑based authentication, port forwarding or custom terminal settings, configure the Client accordingly without blocking the UI thread. Always call client.end() and close streams in dispose() to release resources.

  • Do not hard‑code commands or credentials. Respect the logCommand and sshCommands specified by the user and fall back to the default when missing. Validate user‑provided commands to avoid injection and verify host keys on connection.

  • Provide informative status messages by calling callbacks.onStatus at significant points (connecting, streaming, reconnecting, disconnecting). Display errors via onError to the Webview and window.showErrorMessage so users understand what failed.

Webview guidelines

  • Security: Webviews use a Content‑Security‑Policy that disables remote code execution and restricts resources. When adding scripts or styles, update the CSP string and set appropriate nonce values to allow them to load. Do not fetch remote resources directly from the Webview.

  • State management: keep state in the state object in loggerPanel.js or sidebarView.js. When adding new state variables, initialize them from initialData if they originate from the extension host. Avoid global variables outside the state object.

  • Event handling: register event listeners once at initialization. Use postMessage to request actions from the extension host (save presets, delete presets, export logs, run commands, open terminals) and handle incoming messages in the message event listener. Avoid long‑running work in the Webview; offload heavy processing to the extension host if needed.

  • Performance: the log panel retains up to 10 000 log lines in memory. If you change this limit, ensure memory usage remains acceptable. Append elements efficiently using DocumentFragments and avoid unnecessary DOM reflows. For the side panel, avoid frequent re‑rendering; instead update only affected elements (e.g., highlight rows). Consider using a virtual list for extremely large logs.

Versioning and publishing

  • Increment the version in package.json following semantic versioning: bump the patch version for bug fixes, minor for backward‑compatible feature additions and major for breaking changes.

  • Update the changelog or release notes (if present) whenever you release a new version. Summarize notable changes and migration steps.

  • Before publishing to the VS Code Marketplace, run npm run compile and ensure the extension packages successfully (e.g., using vsce package). Test that all contributed settings and commands appear in the VS Code UI and that secrets are handled correctly.

Conclusion

This document should equip any contributor with the knowledge needed to navigate, maintain and extend the VSCode‑Logger extension. Always align changes with the existing design, respect user configurations and security practices, and accompany code changes with clear documentation. By adhering to these guidelines, any contributor should produce high‑quality contributions that improve the extension without disrupting the experience for existing users.