### Start Development Server Source: https://github.com/caido/doc-developer/blob/main/src/guides/documentation.md Renders the documentation website locally for previewing changes. This command requires Node.js and pnpm to be installed. ```bash pnpm dev ``` -------------------------------- ### Bootstrap Caido Instance with Multiple Plugins Source: https://github.com/caido/doc-developer/blob/main/src/guides/client/install_plugin.md This script demonstrates bootstrapping a Caido instance by installing multiple plugins from the store. It includes error handling for failed installations and skips already installed plugins. ```typescript import { Client } from "@caido/sdk-client"; async function main() { const client = new Client({ url: process.env["CAIDO_INSTANCE_URL"] ?? "http://localhost:8080", auth: { pat: process.env["CAIDO_PAT"]!, cache: { file: ".caido-token.json" }, }, }); await client.connect(); const manifestIds = ["scanner", "quickssrf", "autorize"]; for (const manifestId of manifestIds) { try { const pkg = await client.plugin.install({ manifestId }); console.log(`Installed ${pkg.manifestId} (${pkg.plugins.length} plugins)`); } catch (error) { console.error(`Failed to install ${manifestId}:`, error); } } } main().catch((error) => { console.error(error); process.exit(1); }); ``` -------------------------------- ### Register Command, Shortcut, and Command Palette Entry Source: https://github.com/caido/doc-developer/blob/main/src/guides/shortcuts.md This example demonstrates the full setup for a feature: registering a command, assigning it a keyboard shortcut, and making it discoverable in the command palette. Use the `when` property on commands to control shortcut activity. ```typescript import type { Caido } from "@caido/sdk-frontend"; export type CaidoSDK = Caido; export const init = (sdk: CaidoSDK) => { // Register command sdk.commands.register("toggle-feature", { name: "Toggle Feature", run: () => { // Toggle logic here sdk.log.info("Feature toggled"); }, }); // Register keyboard shortcut sdk.shortcuts.register("toggle-feature", ["Control", "T"]); // Also register to command palette sdk.commandPalette.register("toggle-feature"); }; ``` -------------------------------- ### Initialize Project and Install Dependencies Source: https://github.com/caido/doc-developer/blob/main/src/tutorials/client/scanner.md Sets up a new project directory, initializes npm, and installs the Caido Client SDK and Scanner spec package. ```bash mkdir caido-scanner-tutorial cd caido-scanner-tutorial pnpm init ``` ```bash pnpm add @caido/sdk-client @caido-community/scanner ``` -------------------------------- ### Install @urql/core Source: https://github.com/caido/doc-developer/blob/main/src/guides/client/graphql_direct.md Install the `@urql/core` package to use the `gql` template tag for defining GraphQL documents. ```bash pnpm add @urql/core ``` ```bash npm install @urql/core ``` ```bash yarn add @urql/core ``` -------------------------------- ### Page-Specific Initialization Source: https://github.com/caido/doc-developer/blob/main/src/guides/navigation_events.md Perform cleanup when leaving pages and initialization when entering new pages. This example tracks the current page and executes page-specific setup code for Replay and HTTP History pages. ```typescript import type { Caido } from "@caido/sdk-frontend"; export type CaidoSDK = Caido; export const init = (sdk: CaidoSDK) => { let currentPage: string | undefined; const handler = sdk.navigation.onPageChange((event) => { // Clean up previous page if (currentPage) { sdk.log.debug("Leaving page:", currentPage); // Perform cleanup } // Initialize new page currentPage = event.routeId; sdk.log.debug("Entering page:", currentPage); // Perform page-specific initialization if (event.routeId === "replay") { sdk.log.info("Replay page opened"); // Initialize replay-specific features } else if (event.routeId === "http-history") { sdk.log.info("HTTP History page opened"); // Initialize HTTP history features } }); // Store handler for cleanup if needed // handler.stop() can be called when plugin is unloaded }; ``` -------------------------------- ### Full Database Initialization Example Source: https://github.com/caido/doc-developer/blob/main/src/guides/sqlite.md A comprehensive example demonstrating database initialization, table creation, data insertion, and retrieval within a Caido plugin's backend. ```typescript import type { DefineAPI, SDK } from "caido:plugin"; async function initDatabase(sdk: SDK) { try { const db = await sdk.meta.db(); const dataPath = sdk.meta.path(); sdk.console.log(`Database will be stored in: ${dataPath}`); await db.exec(` CREATE TABLE IF NOT EXISTS test ( id INTEGER PRIMARY KEY, name TEXT NOT NULL ); `); const insertStatement = await db.prepare("INSERT INTO test (name) VALUES (?)"); const result = await insertStatement.run("foo"); sdk.console.log(`Inserted row with ID: ${result.lastInsertRowid}`); const selectStatement = await db.prepare("SELECT * FROM test"); const rows = await selectStatement.all(); sdk.console.log("Current records: " + JSON.stringify(rows)); const getByIdStatement = await db.prepare("SELECT * FROM test WHERE id = ?"); const row = await getByIdStatement.get(1); if (row) { sdk.console.log(`Found record: ${JSON.stringify(row)}`); } else { sdk.console.log("No record found with that ID"); } return db; } catch (error) { sdk.console.error(`Database initialization failed: ${error}`); throw error; } } export type API = DefineAPI<{ }>; export async function init(sdk: SDK) { await initDatabase(sdk); sdk.console.log("Database initialized."); } ``` -------------------------------- ### Install Plugin Project Dependencies Source: https://github.com/caido/doc-developer/blob/main/src/guides/index.md After creating a new plugin package, navigate into its directory and run this command to install all necessary project dependencies. ```bash pnpm install ``` -------------------------------- ### Install Plugin from Local Package File Source: https://github.com/caido/doc-developer/blob/main/src/guides/client/install_plugin.md Install a plugin from a local .zip archive. The archive must be a signed plugin package. Ensure the file path is correct. ```typescript import { readFileSync } from "node:fs"; import { Client } from "@caido/sdk-client"; async function main() { const client = new Client({ url: "http://localhost:8080", auth: { pat: process.env["CAIDO_PAT"]! }, }); await client.connect(); const buffer = readFileSync("./plugin_package.zip"); const file = new File([new Uint8Array(buffer)], "plugin_package.zip", { type: "application/zip", }); const pkg = await client.plugin.install({ file }); console.log("Installed:", pkg.manifestId); } main(); ``` -------------------------------- ### Install Dependencies Source: https://github.com/caido/doc-developer/blob/main/src/guides/documentation.md Installs project dependencies using pnpm. Ensure you have Node.js and pnpm installed. ```bash pnpm i ``` -------------------------------- ### Install AI SDK Package Source: https://github.com/caido/doc-developer/blob/main/src/guides/ai.md Installs the necessary 'ai' package for integrating AI functionalities into your plugin. ```bash npm install ai ``` -------------------------------- ### File Monitor Plugin Example Source: https://github.com/caido/doc-developer/blob/main/src/guides/files.md An example plugin that initializes listeners for file uploads, updates, and deletions, logging each event. ```typescript import type { Caido } from "@caido/sdk-frontend"; export type CaidoSDK = Caido; export const init = (sdk: CaidoSDK) => { // Monitor file uploads sdk.files.onUploadedHostedFile((file) => { sdk.log.info(`[File Monitor] Uploaded: ${file.name} (${file.path})`); }); // Monitor file updates sdk.files.onUpdatedHostedFile((file) => { sdk.log.info(`[File Monitor] Updated: ${file.name} (${file.path})`); }); // Monitor file deletions sdk.files.onDeletedHostedFile((fileId) => { sdk.log.info(`[File Monitor] Deleted: ${fileId}`); }); sdk.log.info("File monitor plugin initialized"); }; ``` -------------------------------- ### Example manifest.json for a Caido Plugin Source: https://github.com/caido/doc-developer/blob/main/src/concepts/package.md Defines the plugin package structure and metadata for the Caido installer. Includes plugin kind, IDs, names, entrypoints, and backend configurations. ```json { "id": "authmatrix", "name": "AuthMatrix", "version": "0.2.0", "description": "Grid-based authorization testing across multiple users and roles.", "author": { "name": "Caido Labs Inc.", "email": "dev@caido.io", "url": "https://github.com/caido-community/authmatrix" }, "plugins": [ { "kind": "frontend", "id": "authmatrix-frontend", "name": "Authmatrix Frontend", "entrypoint": "frontend/script.js", "style": "frontend/style.css", "backend": { "id": "authmatrix-backend" } }, { "kind": "backend", "id": "authmatrix-backend", "name": "Authmatrix Backend", "runtime": "javascript", "entrypoint": "backend/script.js" } ] } ``` -------------------------------- ### Complete Backend Script Example Source: https://github.com/caido/doc-developer/blob/main/src/guides/request.md A full example of the backend script, including imports, the `sendRequest` function, API definition, and initialization. This serves as a reference for implementing request functionality. ```typescript import { RequestSpec } from "caido:utils"; import { SDK, DefineAPI } from "caido:plugin"; async function sendRequest(sdk: SDK): Promise { const spec = new RequestSpec("https://example.com/"); spec.setMethod("GET"); spec.setHost("example.com"); spec.setPort(443); spec.setPath("/"); spec.setQuery("query=test") spec.setTls(true); let sentRequest = await sdk.requests.send(spec); if (sentRequest.response) { let domain = spec.getHost(); let port = spec.getPort(); let path = spec.getPath(); let query = spec.getQuery(); let id = sentRequest.response.getId(); let code = sentRequest.response.getCode(); sdk.console.log(`REQ ${id}: ${domain}:${port}${path}${query} received a status code of ${code}`); } } export type API = DefineAPI({ sendRequest: typeof sendRequest; }); export function init(sdk: SDK) { sdk.api.register("sendRequest", sendRequest); } ``` -------------------------------- ### Server.listen() Source: https://github.com/caido/doc-developer/blob/main/src/reference/modules/llrt/net.md Starts a server listening for connections. This can be a TCP or IPC server. The 'listening' event is emitted when the server starts listening. ```APIDOC ## listen(listeningListener?: () => void): void ### Description Start a server listening for connections. A `net.Server` can be a TCP or an `IPC` server depending on what it listens to. Possible signatures: * `server.listen(options[, callback])` * `server.listen(path[, backlog][, callback])` for `IPC` servers * `server.listen([port[, host[, backlog]]][, callback])` for TCP servers This function is asynchronous. When the server starts listening, the `'listening'` event will be emitted. The last parameter `callback` will be added as a listener for the `'listening'` event. All `listen()` methods can take a `backlog` parameter to specify the maximum length of the queue of pending connections. Currently this parameter is IGNORED, support will be added in the future. All [Socket](#socket) are set to `SO_REUSEADDR`. The `server.listen()` method can be called again if and only if there was an error during the first `server.listen()` call or `server.close()` has been called. Otherwise, an error will be thrown. ### Parameters #### Path Parameters - **listeningListener?** (() => `void`) - An optional callback function to be executed when the server starts listening. ### Returns `void` ``` -------------------------------- ### Add @caido/sdk-client Package Source: https://github.com/caido/doc-developer/blob/main/src/guides/client/install.md Install the SDK package using your preferred package manager. ```bash pnpm add @caido/sdk-client ``` ```bash npm install @caido/sdk-client ``` ```bash yarn add @caido/sdk-client ``` -------------------------------- ### Workflow Discovery and Synchronization Example Source: https://github.com/caido/doc-developer/blob/main/src/guides/workflows.md This example implements a workflow discovery system that logs all workflows on initialization and re-discovers them whenever workflows are created or deleted, keeping the plugin's workflow list synchronized. ```typescript import type { Caido } from "@caido/sdk-frontend"; export type CaidoSDK = Caido; export const init = (sdk: CaidoSDK) => { const discoverWorkflows = () => { const workflows = sdk.workflows.getWorkflows(); workflows.forEach((workflow) => { sdk.log.info(`Workflow: ${workflow.name} (ID: ${workflow.id})`); }); return workflows; }; // Discover workflows on initialization const workflows = discoverWorkflows(); // Re-discover when workflows change sdk.workflows.onCreatedWorkflow(() => { discoverWorkflows(); }); sdk.workflows.onDeletedWorkflow(() => { discoverWorkflows(); }); }; ``` -------------------------------- ### server.listen(port?, listeningListener?) Source: https://github.com/caido/doc-developer/blob/main/src/reference/modules/llrt/net.md Starts a TCP server listening on the specified port. An optional callback function can be provided to be executed once the server starts listening. ```APIDOC ## listen(port?, listeningListener?) ### Description Starts a server listening for connections on a specified port. ### Method `server.listen(port?: number, listeningListener?: () => void): void` ### Parameters * `port` (number) - Optional - The port number to listen on. * `listeningListener` (function) - Optional - A callback function to be executed when the server starts listening. ### Returns `void` ### Notes - This function is asynchronous. The 'listening' event is emitted when the server starts listening. - The `backlog` parameter is currently ignored but will be supported in the future. - All sockets are set to `SO_REUSEADDR`. - `server.listen()` can be called again only after an error or `server.close()`. ``` -------------------------------- ### Listen for Connections with Server Source: https://github.com/caido/doc-developer/blob/main/src/reference/modules/llrt/net.md Starts a server listening for incoming connections. The 'listening' event is emitted when the server starts listening. The callback function is added as a listener for this event. ```javascript server.listen(options[, callback]) server.listen(path[, backlog][, callback]) for IPC servers server.listen([port[, host[, backlog]]][, callback]) for TCP servers ``` -------------------------------- ### server.listen(path, listeningListener?) Source: https://github.com/caido/doc-developer/blob/main/src/reference/modules/llrt/net.md Starts an IPC server listening on the specified path with an optional callback. ```APIDOC ## listen(path, listeningListener?) ### Description Starts an IPC server listening on the specified path. ### Method `server.listen(path: string, listeningListener?: () => void): void` ### Parameters * `path` (string) - Required - The path for the IPC server. * `listeningListener` (function) - Optional - A callback function to be executed when the server starts listening. ### Returns `void` ### Notes - This function is asynchronous. The 'listening' event is emitted when the server starts listening. - All sockets are set to `SO_REUSEADDR`. - `server.listen()` can be called again only after an error or `server.close()`. ``` -------------------------------- ### Install Plugin from Caido Store Source: https://github.com/caido/doc-developer/blob/main/src/guides/client/install_plugin.md Use this method to install a plugin from the Caido community store by providing its manifest ID. Ensure the Caido PAT is set in the environment. ```typescript import { Client } from "@caido/sdk-client"; async function main() { const client = new Client({ url: "http://localhost:8080", auth: { pat: process.env["CAIDO_PAT"]! }, }); await client.connect(); const pkg = await client.plugin.install({ manifestId: "scanner" }); console.log("Installed:", pkg.manifestId); } main(); ``` -------------------------------- ### Example manifest.json Structure Source: https://github.com/caido/doc-developer/blob/main/src/reference/manifest.md This is a complete example of a manifest.json file for a plugin named AuthMatrix. It includes main fields, author details, links, and definitions for frontend, backend, and workflow plugins. ```json { "id": "authmatrix", "name": "AuthMatrix", "version": "0.2.0", "description": "Grid-based authorization testing across multiple users and roles.", "author": { "name": "Caido Labs Inc.", "email": "dev@caido.io", "url": "https://github.com/caido-community/authmatrix" }, "links": { "sponsor": "https://patreon.com/" }, "plugins": [ { "kind": "frontend", "id": "authmatrix-frontend", "name": "Authmatrix Frontend", "entrypoint": "frontend/script.js", "style": "frontend/style.css", "backend": { "id": "authmatrix-backend" }, "assets": "frontend/assets" }, { "kind": "backend", "id": "authmatrix-backend", "name": "Authmatrix Backend", "runtime": "javascript", "entrypoint": "backend/script.js", "assets": "frontend/assets" }, { "kind": "workflow", "id": "authmatrix-workflow", "name": "Authmatrix Workflow", "definition": "workflow/definition.json" } ] } ``` -------------------------------- ### Server Listen Method Source: https://github.com/caido/doc-developer/blob/main/src/reference/modules/llrt/net.md Starts a server listening for incoming connections. The server can be a TCP or IPC server. The 'listening' event is emitted when the server starts listening. A callback can be provided to be executed when the 'listening' event is emitted. ```APIDOC ## listen(options[, callback]) ### Description Starts a server listening for connections. A `net.Server` can be a TCP or an `IPC` server depending on what it listens to. ### Method `server.listen` ### Parameters #### Path Parameters - `options` (`ListenOptions`) - Required - Options for listening. - `callback` (`() => void`) - Optional - A callback function to be executed when the server starts listening. ### Possible Signatures * `server.listen(options[, callback])` * `server.listen(path[, backlog][, callback])` for `IPC` servers * `server.listen([port[, host[, backlog]]][, callback])` for TCP servers ### Notes - All `listen()` methods can take a `backlog` parameter to specify the maximum length of the queue of pending connections. Currently, this parameter is IGNORED. - All [Socket](#socket) are set to `SO_REUSEADDR`. - The `server.listen()` method can be called again if and only if there was an error during the first `server.listen()` call or `server.close()` has been called. Otherwise, an error will be thrown. ``` -------------------------------- ### UnderlyingSinkStartCallback Source: https://github.com/caido/doc-developer/blob/main/src/reference/modules/llrt/stream/web/stream/web.md Callback function invoked when the sink starts. ```APIDOC ## UnderlyingSinkStartCallback() > **UnderlyingSinkStartCallback**(`controller`: [`WritableStreamDefaultController`](#writablestreamdefaultcontroller)): `any` ### Parameters | Parameter | Type | | ------ | ------ | | `controller` | [`WritableStreamDefaultController`](#writablestreamdefaultcontroller) | ### Returns `any` ``` -------------------------------- ### Get Plugin Handle Source: https://github.com/caido/doc-developer/blob/main/src/guides/client/call_function.md Retrieve the package handle for an installed plugin using its manifest ID. Always check if the plugin is installed before proceeding. ```typescript const pkg = await client.plugin.pluginPackage("quickssrf"); if (pkg === undefined) { throw new Error("quickssrf is not installed"); } ``` -------------------------------- ### Example: Rule Status Indicators Source: https://github.com/caido/doc-developer/blob/main/src/guides/match_replace.md Adds visual indicators to rules based on their enabled status. An enabled rule gets a green checkmark, while a disabled rule gets a grey circle. Updates indicators when rule selection changes. ```typescript import type { Caido } from "@caido/sdk-frontend"; export type CaidoSDK = Caido; export const init = (sdk: CaidoSDK) => { const updateRuleIndicators = () => { const rules = sdk.matchReplace.getRules(); rules.forEach((rule) => { if (rule.isEnabled) { sdk.matchReplace.addRuleIndicator(rule.id, { icon: "fas fa-check-circle", description: "Rule is enabled", }); } else { sdk.matchReplace.addRuleIndicator(rule.id, { icon: "fas fa-circle", description: "Rule is disabled", }); } }); }; // Update indicators when rules change sdk.matchReplace.onCurrentRuleChange(() => { updateRuleIndicators(); }); // Initial update updateRuleIndicators(); }; ``` -------------------------------- ### Full Example: Provision, Configure, and Select Environment Source: https://github.com/caido/doc-developer/blob/main/src/guides/client/environments.md A complete script demonstrating the creation of a 'staging' environment, adding and updating variables, selecting it as active, and logging its final state. Includes client initialization and connection. ```typescript import { Client } from "@caido/sdk-client"; async function main() { const client = new Client({ url: process.env["CAIDO_INSTANCE_URL"] ?? "http://localhost:8080", auth: { pat: process.env["CAIDO_PAT"]!, cache: { file: ".caido-token.json" }, }, }); await client.connect(); const env = await client.environment.create({ name: "staging", variables: [ { name: "API_URL", value: "https://api.staging.example.com", kind: "PLAIN" }, { name: "API_KEY", value: "secret-123", kind: "SECRET" }, ], }); await env.addVariable({ name: "REGION", value: "us-east-1", kind: "PLAIN" }); await env.updateVariable("API_KEY", { value: "secret-rotated" }); await client.environment.select(env.id); console.log(`Active: ${env.name}`); for (const v of env.variables) { const display = v.kind === "SECRET" ? "***" : v.value; console.log(` ${v.name} = ${display} (${v.kind})`); } } main().catch((error) => { console.error(error); process.exit(1); }); ``` -------------------------------- ### Running the Caido SDK Client Example Source: https://github.com/caido/doc-developer/blob/main/src/guides/client/call_function.md These commands show how to set the necessary environment variables and execute the TypeScript script to interact with the Caido instance. ```bash export CAIDO_PAT=caido_xxxxx npx tsx ./index.ts ``` -------------------------------- ### Display Caido Version and Plugin Compatibility Source: https://github.com/caido/doc-developer/blob/main/src/guides/runtime.md This example displays the current Caido version and indicates plugin compatibility. It uses Vue's computed properties to reactively update the version string. For more details on creating pages and Vue components, refer to the page creation guide. ```vue ``` -------------------------------- ### Initialize Caido Client and Authenticate Source: https://github.com/caido/doc-developer/blob/main/src/guides/client/base_setup.md Sets up the Caido client with instance URL and PAT from environment variables. It connects to the instance and fetches viewer details. Ensure CAIDO_PAT is set. ```typescript import { Client } from "@caido/sdk-client"; async function main() { const instanceUrl = process.env["CAIDO_INSTANCE_URL"] ?? "http://localhost:8080"; const pat = process.env["CAIDO_PAT"]; if (!pat) { console.error("CAIDO_PAT environment variable is required"); process.exit(1); } const client = new Client({ url: instanceUrl, auth: { pat: pat, cache: { file: ".caido-token.json" }, }, }); await client.connect(); const viewer = await client.user.viewer(); console.log("Viewer:", JSON.stringify(viewer, null, 2)); } main().catch((error) => { console.error(error); process.exit(1); }); ``` -------------------------------- ### Manage Project-Specific Configuration with Events Source: https://github.com/caido/doc-developer/blob/main/src/guides/application_events.md This example demonstrates how to manage project-specific configuration by reacting to project change events. It cleans up resources from the previous project and loads configuration for the new one. ```ts import type { Caido } from "@caido/sdk-frontend"; export type CaidoSDK = Caido; export const init = (sdk: CaidoSDK) => { let currentProjectId: string | undefined; sdk.projects.onCurrentProjectChange((event) => { const previousProject = currentProjectId; currentProjectId = event.projectId; // Clean up previous project if (previousProject) { sdk.log.info(`Leaving project: ${previousProject}`); // Clean up project-specific resources } // Initialize new project if (currentProjectId) { sdk.log.info(`Entering project: ${currentProjectId}`); // Load project-specific configuration loadProjectConfig(currentProjectId); } }); const loadProjectConfig = (projectId: string) => { // Load configuration specific to this project sdk.log.info(`Loading config for project: ${projectId}`); }; }; ``` -------------------------------- ### Create and Listen on a TCP Server Source: https://github.com/caido/doc-developer/blob/main/src/reference/modules/llrt/net.md Demonstrates creating a basic TCP server that closes connections immediately and logs the server's address information once it starts listening. Handles potential errors during server operation. ```javascript const server = net.createServer((socket) => { socket.end('goodbye\n'); }).on('error', (err) => { // Handle errors here. throw err; }); // Grab an arbitrary unused port. server.listen(() => { console.log('opened server on', server.address()); }); ``` -------------------------------- ### Response Headers Example Source: https://github.com/caido/doc-developer/blob/main/src/reference/sdks/backend/requests.md An example of the structure for response headers, showing how multiple values for a single header are represented. ```json { "Date": ["Sun, 26 May 2024 10:59:21 GMT"], "Content-Type": ["text/html"] } ``` -------------------------------- ### Initialize Git Repository and Connect to GitHub Source: https://github.com/caido/doc-developer/blob/main/src/guides/repository.md Initialize a Git repository in your local project, stage all files, commit them, set the main branch name, and add your GitHub repository as a remote. Finally, push the initial commit to the remote repository. ```bash git init git add . git commit -m "init" git branch -M main git remote add origin git@github.com:YOUR_USERNAME/YOUR_REPO_NAME.git git push -u origin main ``` -------------------------------- ### YAML Frontmatter Example Source: https://github.com/caido/doc-developer/blob/main/AGENTS.md Pages may include YAML frontmatter for VitePress configuration. This example shows a basic title. ```yaml --- title: Page Title --- ``` -------------------------------- ### Initialize Vue App with SDK and PrimeVue Source: https://github.com/caido/doc-developer/blob/main/src/guides/rpc.md Create a Vue application instance, provide the SDK to all components via dependency injection, and configure PrimeVue with the Classic preset. ```javascript const app = createApp(App); app.provide("sdk", sdk); app.use(PrimeVue, { unstyled: true, pt: Classic }); ``` -------------------------------- ### Markdown Code Examples Source: https://github.com/caido/doc-developer/blob/main/AGENTS.md Use appropriate language tags for code examples in Markdown. Supported tags include ts, json, and bash. ```markdown ```ts // TypeScript example ``` ``` ```markdown ```json // JSON example ``` ``` ```markdown ```bash # Shell command ``` ``` -------------------------------- ### Get Last Inserted Row ID Source: https://github.com/caido/doc-developer/blob/main/src/guides/sqlite.md Access the `lastInsertRowid` property from the result of an `.run()` operation to get the ID of the most recently inserted row. ```typescript console.log(`Inserted row with ID: ${result.lastInsertRowid}`); ``` -------------------------------- ### server.listen(path, backlog?, listeningListener?) Source: https://github.com/caido/doc-developer/blob/main/src/reference/modules/llrt/net.md Starts an IPC server listening on the specified path. Optional backlog and callback parameters can be provided. ```APIDOC ## listen(path, backlog?, listeningListener?) ### Description Starts an IPC server listening on the specified path. ### Method `server.listen(path: string, backlog?: number, listeningListener?: () => void): void` ### Parameters * `path` (string) - Required - The path for the IPC server. * `backlog` (number) - Optional - The maximum length of the queue of pending connections (currently ignored). * `listeningListener` (function) - Optional - A callback function to be executed when the server starts listening. ### Returns `void` ### Notes - This function is asynchronous. The 'listening' event is emitted when the server starts listening. - The `backlog` parameter is currently ignored but will be supported in the future. - All sockets are set to `SO_REUSEADDR`. - `server.listen()` can be called again only after an error or `server.close()`. ``` -------------------------------- ### Navigate to Project Directory Source: https://github.com/caido/doc-developer/blob/main/src/guides/repository.md Change your current directory to the root of your newly created plugin project. ```bash cd my-plugin ``` -------------------------------- ### Plugin Package Handle Structure Source: https://github.com/caido/doc-developer/blob/main/src/guides/client/install_plugin.md The `PluginPackageHandle` returned by `install()` describes the installed package and its constituent plugins, including their kind, manifest ID, and enabled status. ```text { id: "068a80a3-c1ab-4116-8b89-e7ee64be4534", manifestId: "scanner", plugins: [ { kind: "PluginBackend", manifestId: "backend", enabled: true }, { kind: "PluginFrontend", manifestId: "frontend", enabled: true } ] } ``` -------------------------------- ### Full Frontend Script with Asset Access Source: https://github.com/caido/doc-developer/blob/main/src/guides/files.md An example of a complete frontend script that initializes the plugin, reads an asset file, and displays its content. It also sets up navigation and sidebar items. ```typescript import "./styles/index.css"; import type { FrontendSDK } from "./types"; // Note that the init function is async to account for fetching the files. export const init = async (sdk: FrontendSDK) => { const root = document.createElement("div"); Object.assign(root.style, { height: "100%", width: "100%", }); root.id = `plugin--frontend-vanilla`; const parent = document.createElement("div"); parent.classList.add("h-full", "flex", "justify-center", "items-center"); const container = document.createElement("div"); container.classList.add("flex", "flex-col", "gap-1", "p-4"); const file = await sdk.assets.get("myfile.txt"); // For large files or to process in chunks, use file.asReadableStream() instead. const content = await file.asString(); container.textContent = content; parent.appendChild(container); root.appendChild(parent); sdk.navigation.addPage("/view-file-plugin", { body: root, }); sdk.sidebar.registerItem("View File Plugin", "/view-file-plugin"); }; ``` -------------------------------- ### Successful Authentication and Viewer Output Source: https://github.com/caido/doc-developer/blob/main/src/guides/client/base_setup.md Example output demonstrating a successful authentication flow and the fetched viewer details. Subsequent runs may show cached token usage. ```text [caido] Attempting to load cached token [caido] Failed to load cached token from file [caido] Starting authentication flow [caido] Authentication flow completed [caido] Saving token to cache Viewer: { "kind": "CloudUser", "id": "", "profile": { "identity": { "email": "you@example.com", "name": "Your Name" }, "subscription": { "plan": { "name": "" }, "entitlements": [ { "name": "feature:..." } ] } } } ``` -------------------------------- ### Initialize Backups Page Source: https://github.com/caido/doc-developer/blob/main/src/guides/page.md Creates and mounts a Vue application for the Backups page, then adds it to the SDK navigation. ```typescript import { Classic } from "@caido/primevue"; import PrimeVue from "primevue/config"; import { createApp } from "vue"; import type { Caido } from "@caido/sdk-frontend"; import App from "./views/BackupsApp.vue"; export type CaidoSDK = Caido; export const init = (sdk: CaidoSDK) => { const app = createApp(App); app.use(PrimeVue, { unstyled: true, pt: Classic, }); const root = document.createElement("div"); Object.assign(root.style, { height: "100%", width: "100%", }); app.mount(root); sdk.navigation.addPage("/backup-analytics", { body: root, }); // Monitor Backups page changes sdk.window.onContextChange((context) => { if (context.page?.kind === "Backups") { sdk.log.info("Now on Backups page"); } }); }; ``` -------------------------------- ### Reactive Workflow Management Example Source: https://github.com/caido/doc-developer/blob/main/src/guides/workflows.md This example demonstrates reactive workflow management by subscribing to all workflow lifecycle events. It logs changes and provides placeholders for triggering custom actions. ```typescript import type { Caido } from "@caido/sdk-frontend"; export type CaidoSDK = Caido; export const init = (sdk: CaidoSDK) => { // Get all workflows on initialization const workflows = sdk.workflows.getWorkflows(); sdk.log.info(`Found ${workflows.length} workflows`); // React to workflow changes sdk.workflows.onCreatedWorkflow((workflow) => { sdk.log.info(`New workflow created: ${workflow.name}`); // Perform actions when a new workflow is created // e.g., send notification, update UI, etc. }); sdk.workflows.onUpdatedWorkflow((workflow) => { sdk.log.info(`Workflow updated: ${workflow.name}`); // React to workflow updates // e.g., refresh related data, update cache, etc. }); sdk.workflows.onDeletedWorkflow((workflowId) => { sdk.log.info(`Workflow deleted: ${workflowId}`); // Clean up resources related to the deleted workflow }); }; ``` -------------------------------- ### Initialize and Connect Golang Client Source: https://github.com/caido/doc-developer/blob/main/src/concepts/client/community_golang.md Initializes a new Caido client with specified options, including URL and authentication, and establishes a connection. Use PATAuth for Personal Access Tokens. ```go client, _ := caido.NewClient(caido.Options{ URL: "http://localhost:8080", Auth: caido.PATAuth("caido_xxxxx"), }) client.Connect(context.Background()) ``` -------------------------------- ### Initialize Assistant Page Source: https://github.com/caido/doc-developer/blob/main/src/guides/page.md Sets up a Vue application for the Assistant page and registers it with the SDK navigation. ```typescript import { Classic } from "@caido/primevue"; import PrimeVue from "primevue/config"; import { createApp } from "vue"; import type { Caido } from "@caido/sdk-frontend"; import App from "./views/AssistantApp.vue"; export type CaidoSDK = Caido; export const init = (sdk: CaidoSDK) => { const app = createApp(App); app.use(PrimeVue, { unstyled: true, pt: Classic, }); const root = document.createElement("div"); Object.assign(root.style, { height: "100%", width: "100%", }); app.mount(root); sdk.navigation.addPage("/ai-assistant-tools", { body: root, }); // React to Assistant page context sdk.window.onContextChange((context) => { if (context.page?.kind === "Assistant") { sdk.log.info("Assistant tools page is now relevant"); } }); }; ``` -------------------------------- ### Initialize Vue App and Register Page with Caido SDK Source: https://github.com/caido/doc-developer/blob/main/src/guides/page.md Sets up a Vue application, configures PrimeVue, mounts the app to a DOM element, and registers a new page with the Caido SDK. Also registers a sidebar item for navigation. ```typescript import { Classic } from "@caido/primevue"; import PrimeVue from "primevue/config"; import { createApp } from "vue"; import type { Caido } from "@caido/sdk-frontend"; import type { API } from "starterkit-plugin-backend"; import App from "./views/App.vue"; export type CaidoSDK = Caido; export const init = (sdk: CaidoSDK) => { const app = createApp(App); app.use(PrimeVue, { unstyled: true, pt: Classic, }); const root = document.createElement("div"); Object.assign(root.style, { height: "100%", width: "100%", }); app.mount(root); sdk.navigation.addPage("/my-plugin-page", { body: root, }); sdk.sidebar.registerItem("My Plugin", "/my-plugin-page", { icon: "fas fa-rocket", }); }; ``` -------------------------------- ### Install Plugin Spec Package Source: https://github.com/caido/doc-developer/blob/main/src/guides/client/spec_typing.md Install the plugin's spec package using your preferred package manager (pnpm, npm, or yarn). The convention for spec package names is `@caido-community/`. ```bash pnpm add @caido-community/quickssrf ``` ```bash npm install @caido-community/quickssrf ``` ```bash yarn add @caido-community/quickssrf ``` -------------------------------- ### Create and Use Filter Presets Source: https://github.com/caido/doc-developer/blob/main/src/guides/filters.md Demonstrates creating a filter with an alias and then using that filter as a preset in HTTPQL queries. Presets are referenced using the `preset:` prefix. ```typescript // Create a filter with an alias const filter = await sdk.filters.create({ name: "Successful GET Requests", alias: "success-get", query: "resp.code.eq:200 AND req.method.eq:\"GET\"", }); // Use the filter in a query sdk.httpHistory.setQuery("preset:success-get"); ``` -------------------------------- ### Get and Set URL Port Source: https://github.com/caido/doc-developer/blob/main/src/reference/modules/llrt/url/index.md Illustrates getting and setting the port number for a URL. Default ports are converted to an empty string. Invalid port strings are ignored, and leading numbers are parsed. ```javascript const myURL = new URL('https://example.org:8888'); console.log(myURL.port); // Prints 8888 // Default ports are automatically transformed to the empty string // (HTTPS protocol's default port is 443) myURL.port = '443'; console.log(myURL.port); // Prints the empty string console.log(myURL.href); // Prints https://example.org/ myURL.port = 1234; console.log(myURL.port); // Prints 1234 console.log(myURL.href); // Prints https://example.org:1234/ // Completely invalid port strings are ignored myURL.port = 'abcd'; console.log(myURL.port); // Prints 1234 // Leading numbers are treated as a port number myURL.port = '5678abcd'; console.log(myURL.port); // Prints 5678 // Non-integers are truncated myURL.port = 1234.5678; console.log(myURL.port); // Prints 1234 // Out-of-range numbers which are not represented in scientific notation // will be ignored. myURL.port = 1e10; // 10000000000, will be range-checked as described below console.log(myURL.port); // Prints 1234 ``` ```javascript myURL.port = 4.567e21; console.log(myURL.port); // Prints 4 (because it is the leading number in the string '4.567e21') ``` -------------------------------- ### Create a Hosted File Source: https://github.com/caido/doc-developer/blob/main/src/reference/sdks/backend/hostedfile.md Use this method to create a new hosted file. Provide a name for the file and its content. The content should be a string. ```javascript await sdk.hostedFile.create({ name: "My File", content: "Hello, world!" }); ``` -------------------------------- ### Connect to Caido and Install Scanner Plugin Source: https://github.com/caido/doc-developer/blob/main/src/tutorials/client/scanner.md Connects to a Caido instance using a PAT and installs the Scanner plugin if it's not already present. The ScannerSpec generic ensures type safety for subsequent calls. ```typescript import { Client } from "@caido/sdk-client"; import type { Spec as ScannerSpec } from "@caido-community/scanner"; async function main() { const client = new Client({ url: process.env["CAIDO_INSTANCE_URL"] ?? "http://localhost:8080", auth: { pat: process.env["CAIDO_PAT"]!, cache: { file: ".caido-token.json" }, }, }); await client.connect(); console.log("Connected to Caido"); // Look up the installed plugin, install if missing let pkg = await client.plugin.pluginPackage("scanner"); if (pkg === undefined) { console.log("Installing Scanner..."); pkg = await client.plugin.install({ manifestId: "scanner" }); } console.log("Scanner ready"); } main().catch((error) => { console.error(error); process.exit(1); }); ``` -------------------------------- ### Initialize WebSocket Analyzer Plugin Source: https://github.com/caido/doc-developer/blob/main/src/guides/page.md Set up a Vue application for a WebSocket analyzer and register it as a new page in Caido. This example demonstrates mounting a Vue app and adding a navigation entry. ```typescript import { Classic } from "@caido/primevue"; import PrimeVue from "primevue/config"; import { createApp } from "vue"; import type { Caido } from "@caido/sdk-frontend"; import App from "./views/WebSocketAnalyzerApp.vue"; export type CaidoSDK = Caido; export const init = (sdk: CaidoSDK) => { const app = createApp(App); app.use(PrimeVue, { unstyled: true, pt: Classic, }); const root = document.createElement("div"); Object.assign(root.style, { height: "100%", width: "100%", }); app.mount(root); sdk.navigation.addPage("/websocket-analyzer", { body: root, }); // React to WebSocket page context sdk.window.onContextChange((context) => { if (context.page?.kind === "Websocket") { sdk.log.info("WebSocket analyzer tools available"); } }); }; ``` -------------------------------- ### Get Collections Source: https://github.com/caido/doc-developer/blob/main/src/guides/replay.md Retrieves all collections. ```APIDOC ## Get Collections ### Description Retrieves all collections. ### Method `sdk.replay.getCollections()` ### Response #### Success Response (200) - **collections** (Array) - An array of collection objects. ### Response Example ```json { "collections": [ { "id": "collection-abc", "name": "My Collection" } ] } ``` ``` -------------------------------- ### Create Directory Recursively with fsPromises.mkdir Source: https://github.com/caido/doc-developer/blob/main/src/reference/modules/llrt/fs/promises.md Use fsPromises.mkdir to asynchronously create a directory. Set the 'recursive' option to true to create parent directories as needed. This example creates './test/project/123' and any necessary parent directories. ```javascript import { mkdir } from 'fs/promises'; try { const projectFolder = './test/project/123'; const createDir = await mkdir(projectFolder, { recursive: true }); console.log(`created ${createDir}`); } catch (err) { console.error(err.message); } ``` -------------------------------- ### Session Monitor Plugin Example Source: https://github.com/caido/doc-developer/blob/main/src/guides/automate.md An example plugin that monitors automate sessions and adds indicators to recently created entries. It checks entries every minute and adds a 'clock' indicator if created within the last hour. ```typescript import type { Caido } from "@caido/sdk-frontend"; export type CaidoSDK = Caido; export const init = (sdk: CaidoSDK) => { const checkEntries = () => { const sessions = sdk.automate.getSessions(); sessions.forEach((session) => { const entries = sdk.automate.getEntries(session.id); entries.forEach((entry) => { // Add indicator for entries created in the last hour const oneHourAgo = Date.now() - 60 * 60 * 1000; if (entry.createdAt.getTime() > oneHourAgo) { sdk.automate.addEntryIndicator(entry.id, { icon: "fas fa-clock", description: "Recently created", }); } }); }); }; // Check entries periodically setInterval(checkEntries, 60000); // Every minute // Initial check checkEntries(); }; ``` -------------------------------- ### Build Request Query Source: https://github.com/caido/doc-developer/blob/main/src/reference/sdks/backend/requests.md Demonstrates building a query to fetch requests. This includes filtering, ordering, and pagination. ```javascript const query = sdk.requests.query() .filter("method eq POST") .descending("req", "time") .first(10); const connection = await query.execute(); ``` -------------------------------- ### SitemapSDK.getScopeId Source: https://github.com/caido/doc-developer/blob/main/src/reference/sdks/frontend/sitemap.md Get the current scope ID. ```APIDOC ## getScopeId() ### Description Get the current scope ID. ### Returns - [`ID`](utils.md#id) | `undefined` - The current scope ID. ``` -------------------------------- ### QueuingStrategyInit Source: https://github.com/caido/doc-developer/blob/main/src/reference/modules/llrt/stream/web/stream/web.md Initialization options for a QueuingStrategy. ```APIDOC ## QueuingStrategyInit ### Properties - **highWaterMark** (number) ``` -------------------------------- ### Registering a Command Source: https://github.com/caido/doc-developer/blob/main/src/reference/sdks/frontend/commands.md Demonstrates how to register a new command using the `commands.register` method. This includes specifying the command's ID, name, and the function to execute when the command is run. It also shows how to optionally define a group and a condition for when the command should be available. ```APIDOC ## commands.register() ### Description Register a command. ### Method `register(id: CommandID, options: object) => void` ### Parameters #### Parameters - **id** (`CommandID`) - Required - The id of the command. - **options** (`object`) - Required - Options for the command. - **group?** (`string`) - Optional - The group this command belongs to. - **name** (`string`) - Required - The name of the command. - **run** (`(context: CommandContext) => Promise | void`) - Required - The function to run when the command is executed. - **when?** (`(context: CommandContext) => Promise | boolean`) - Optional - A function to determine if the command is available. ### Returns `void` ### Example ```ts sdk.commands.register("hello", { name: "Print to console.", run: () => console.log("Hello world!"), group: "Custom Commands", }); ``` ``` -------------------------------- ### RuntimeSDK.version Source: https://github.com/caido/doc-developer/blob/main/src/reference/sdks/frontend/runtime.md Get the current version of Caido. ```APIDOC ## RuntimeSDK.version ### Description Get the current version of Caido. ### Signature `get version(): string` ### Returns `string` - The current version of Caido. ``` -------------------------------- ### FiltersSDK.getCurrentFilter() Source: https://github.com/caido/doc-developer/blob/main/src/reference/sdks/frontend/filters.md Gets the currently selected filter. ```APIDOC ## FiltersSDK.getCurrentFilter() ### Description Get the currently selected filter. ### Method `getCurrentFilter() => Filter | undefined` ### Returns `Filter | undefined` - The currently selected filter, or undefined if no filter is selected. ```