### Lookup Function Examples Source: https://docs.sidekick.binary.ninja/reference/bnql.html Examples demonstrating the usage of BNQL lookup functions. ```APIDOC ``` function("main") # function named "main" f(0x401000) # function at address datavar("g_config") # global named g_config tag("Reviewed") # all Reviewed tags address(0x1000)/^function # function containing address 0x1000 address-range(0x500000, 512) # 512-byte region starting at 0x500000 bv("libc.so.6")/function # functions in a specific binary ``` ``` -------------------------------- ### Lookup Functions Examples Source: https://docs.sidekick.binary.ninja/reference/bnql.html Examples demonstrating the usage of various lookup functions to retrieve specific objects like functions, symbols, data variables, types, tags, addresses, address ranges, sections, and binary views. ```python function("main") # function named "main" f(0x401000) # function at address datavar("g_config") # global named g_config tag("Reviewed") # all Reviewed tags address(0x1000)/^function # function containing address 0x1000 address-range(0x500000, 512) # 512-byte region starting at 0x500000 bv("libc.so.6")/function # functions in a specific binary ``` -------------------------------- ### Library Python Automation Recipe Source: https://docs.sidekick.binary.ninja/guide/sidekick_api.html A recipe demonstrating how to use `sidekick.api` for library automations, including getting or creating an index and adding objects to it. ```APIDOC ## Library Python Automation Recipe ### Description This is the recommended pattern for Library automations: keep the logic in Python, use the pre-bound `bv`, and access Sidekick resources through `sidekick.api`. This example shows how to reuse or create a workspace index and add objects to it. ### Code Example ```python import sidekick.api as api from binaryninja import MediumLevelILOperation TAILCALL_OPS = { MediumLevelILOperation.MLIL_TAILCALL, MediumLevelILOperation.MLIL_TAILCALL_UNTYPED, MediumLevelILOperation.MLIL_TAILCALL_SSA, MediumLevelILOperation.MLIL_TAILCALL_UNTYPED_SSA, } # Reuse the current workspace index or create it on first run. api.get_index(bv, "tailcalls", create_if_missing=True) # Collect Binary Ninja objects of any indexable kind. add_index_objects # accepts the objects directly and derives canonical object IDs for them. tailcalls = [ insn for func in bv.functions if func.mlil is not None for insn in func.mlil.instructions if insn.operation in TAILCALL_OPS ] entries = api.add_index_objects( bv, "tailcalls", objects=tailcalls, prevent_duplicates=True, ) print({"index": "tailcalls", "added": len(entries)}) ``` ``` -------------------------------- ### Multiple MCP Servers Configuration Source: https://docs.sidekick.binary.ninja/guide/mcp_tools.html Configure multiple MCP servers, each with specific tags and commands. This example shows a filesystem server and a git server, demonstrating how to set environment variables and aliases for tools. ```json { "version": "1.0", "servers": [ { "name": "filesystem", "tags": ["mcp.filesystem"], "server_config": { "command": ["uvx", "mcp-server-filesystem", "/home/user/allowed"] }, "tools": [ { "name": "read_file" }, { "name": "list_directory", "alias": "list_dir" } ] }, { "name": "git", "tags": ["mcp.git"], "server_config": { "command": ["uvx", "mcp-server-git", "--repository", "/path/to/repo"], "env": { "GIT_CONFIG_GLOBAL": "/dev/null" } }, "tools": [ { "name": "git_log" }, { "name": "git_diff" } ] } ] } ``` -------------------------------- ### Get the First Function Source: https://docs.sidekick.binary.ninja/reference/bnql.html Selects the first function from the set of all functions. This is a shorthand for retrieving the initial element. ```BNQL /function[0] ``` -------------------------------- ### Call a Prompt with Structured Output Source: https://docs.sidekick.binary.ninja/guide/sidekick_api.html Load the 'extract-summary' prompt and use it to get a structured summary and confidence score from a function's code. ```python extract = load_prompt("extract-summary") result = extract(CODE=render_object(func, verbosity="contents")) print(result["summary"], result["confidence"]) ``` -------------------------------- ### Minimal Python MCP Server Example Source: https://docs.sidekick.binary.ninja/guide/mcp_tools.html A basic Python script that implements an MCP server, exposing 'echo' and 'get_time' tools via JSON-RPC over stdin/stdout. It handles initialization, tool listing, and tool calls. ```python #!/usr/bin/env python3 """Minimal MCP tool server.""" import json import sys from datetime import datetime, timezone TOOLS = [ { "name": "echo", "description": "Returns the text you send it.", "inputSchema": { "type": "object", "properties": { "text": {"type": "string", "description": "Text to echo back"} }, "required": ["text"] } }, { "name": "get_time", "description": "Returns the current UTC time.", "inputSchema": {"type": "object", "properties": {}} }, ] def handle(msg): method = msg.get("method") rid = msg.get("id") # Notifications (no id) are silently ignored if rid is None: return if method == "initialize": respond(rid, { "protocolVersion": "2024-11-05", "capabilities": {"tools": {}}, "serverInfo": {"name": "my-server", "version": "1.0.0"} }) elif method == "tools/list": respond(rid, {"tools": TOOLS}) elif method == "tools/call": name = msg["params"]["name"] args = msg["params"].get("arguments", {}) if name == "echo": respond(rid, {"content": [{"type": "text", "text": args.get("text", "")}]}) elif name == "get_time": now = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S UTC") respond(rid, {"content": [{"type": "text", "text": now}]}) else: error(rid, -32601, f"Unknown tool: {name}") else: error(rid, -32601, f"Unknown method: {method}") def respond(rid, result): sys.stdout.write(json.dumps({"jsonrpc": "2.0", "id": rid, "result": result}) + "\n") sys.stdout.flush() def error(rid, code, message): sys.stdout.write(json.dumps({"jsonrpc": "2.0", "id": rid, "error": {"code": code, "message": message}}) + "\n") sys.stdout.flush() while True: line = sys.stdin.readline() if not line: break line = line.strip() if line: handle(json.loads(line)) ``` -------------------------------- ### Initialize Runtime Source: https://docs.sidekick.binary.ninja/guide/sidekick_api.html Recommended entry point to open or borrow a SessionContext. It handles bootstrapping a headless Sidekick application if a BinjaSession does not already exist. ```python from sidekick.context import init_runtime runtime = init_runtime(target="/path/to/binary") ``` -------------------------------- ### Initialize Sidekick Context (Headless) Source: https://docs.sidekick.binary.ninja/guide/sidekick_api.html Create a SidekickContext for headless use. The app_dir is preserved by default or can be cleaned up on exit for scratch runs. scripts_root sets the default agent/prompt lookup directory. ```python from sidekick.context import sidekick context = sidekick(app_dir="/path/to/app", semantic_index=True, cleanup_app_dir=True, scripts_root="/path/to/scripts") ``` -------------------------------- ### get_default_root Source: https://docs.sidekick.binary.ninja/guide/sidekick_api.html Gets the current default scripts root directory. ```APIDOC ## get_default_root() ### Description Retrieves the currently configured default scripts root directory. ### Method Not applicable (Python function) ### Endpoint Not applicable (Python function) ### Response #### Success Response - **root** (str) - The path to the default scripts root directory. ``` -------------------------------- ### Initialize Runtime and Run Agent Source: https://docs.sidekick.binary.ninja/guide/sidekick_api.html Initialize a Sidekick runtime session with a BinaryView, load the 'rename-vars' agent, and execute it on functions with more than 100 basic blocks. ```python from sidekick.api import init_runtime, execute_bnql with init_runtime(bv) as sess: renamer = sess.load_agent("rename-vars") large_funcs = execute_bnql(bv, "/view/function[count(basic_blocks) > 100]") for func in large_funcs: print(f"Analyzing {func.name}...") renamer(TARGET_FUNCTION=func) ``` -------------------------------- ### BNQL Query: Functions with Many Calls Source: https://docs.sidekick.binary.ninja/guide/indexes.html This BNQL query identifies functions that have a high number of outgoing calls, greater than 50 in this example. ```BNQL /function[count(calls::*) > 50] ``` -------------------------------- ### Executing Headless Scripts Outside Binary Ninja Source: https://docs.sidekick.binary.ninja/guide/sidekick_api.html Demonstrates how to use the `sidekick()` context manager to initialize a headless Sidekick application instance and open a session for a file. ```APIDOC ## Executing Headless Scripts Outside Binary Ninja ### Description Use the `sidekick()` context manager to initialize a headless application instance outside the Binary Ninja GUI. You can then open a session for a file or project to interact with Sidekick. ### Method `api.sidekick(app_dir, cleanup_app_dir=False)` ### Parameters #### Path Parameters - **app_dir**: Path to the directory to store workspace databases and index data. - **cleanup_app_dir** (optional): If True, removes temporary state on exit. ### Request Example ```python import sidekick.api as api from pathlib import Path app_dir = Path("~/.sidekick-headless").expanduser() with api.sidekick(app_dir) as sk: with sk.session("/path/to/target.bndb") as sess: funcs = api.execute_bnql(sess.bv, "/view/function", limit=10) print([f.name for f in funcs]) ``` ### Response #### Success Response (200) The `sk.session(target)` context manager yields a `SessionContext` object with a `bv` property for the active `BinaryView`. ``` -------------------------------- ### Create, List, Retrieve, Update, and Delete Indexes Source: https://docs.sidekick.binary.ninja/guide/sidekick_api.html Demonstrates the full lifecycle of managing indexes using the Sidekick API. This includes creating new indexes, listing existing ones, retrieving specific indexes, updating their metadata, and deleting them. ```python from sidekick.api import ( create_index, get_index, list_indexes, update_index, delete_index, add_index_objects, update_index_entries, remove_index_entries, ) # Create idx = create_index(bv, "interesting-functions", metadata={"owner": "user"}) # List and retrieve print([r.resource_id for r in list_indexes(bv)]) same_idx = get_index(bv, "interesting-functions") # Add Binary Ninja objects as entries. The API derives a canonical object_id # from each object and attributes the entry to bv. entries = add_index_objects(bv, "interesting-functions", objects=[func_a, func_b]) # Update entry metadata by entry_id update_index_entries(bv, "interesting-functions", [entries[0].entry_id], {"priority": 10}) # Remove entries remove_index_entries(bv, "interesting-functions", [entries[1].entry_id]) # Rename or update the index itself update_index(bv, "interesting-functions", name="priority-functions", index_type="manual") # Delete delete_index(bv, "priority-functions") ``` -------------------------------- ### BNMF Dependency Ordering Example Source: https://docs.sidekick.binary.ninja/reference/bnmf.html Use `id` and `depends_on` to enforce modification order, such as defining a type before using it in a variable. Modifications are sorted topologically. ```json { "modifications": [ { "id": "def_type", "uri": "bv:type/Buffer", "state": {"definition": "struct Buffer { char* data; size_t len; }"} }, { "uri": "bv:function/0x401000/variable/arg1", "state": {"type": "struct Buffer*"}, "depends_on": ["def_type"] } ] } ``` -------------------------------- ### Python API: Create and Populate Index from BNQL Source: https://docs.sidekick.binary.ninja/guide/indexes.html This Python snippet demonstrates how to create an index if it doesn't exist, execute a BNQL query, and add the results to the index, preventing duplicate entries. ```Python import sidekick.api as api # Create the index on first run, or reuse it if it already exists. api.get_index(bv, "interesting-functions", create_if_missing=True) # Find all callers of recv and add them, skipping duplicates on later runs. callers = api.execute_bnql(bv, 'callers("recv")') entries = api.add_index_objects( bv, "interesting-functions", objects=callers, prevent_duplicates=True, ) print({"index": "interesting-functions", "added": len(entries)}) ``` -------------------------------- ### Guard Rename with Precondition Source: https://docs.sidekick.binary.ninja/reference/bnmf.html This example shows how to rename a function only if a specific precondition is met, such as the function still having its original auto-generated name. This prevents unintended renames. ```json { "description": "Rename only if still auto-named", "binary_view_changes": [{ "modifications": [ { "uri": "bv:function/0x401000", "expect": {"name": "sub_401000"}, "state": {"name": "init_config"} } ] }] } ``` -------------------------------- ### BNQL Semantic Search in a Predicate Source: https://docs.sidekick.binary.ninja/guide/semantic_indexing.html Filters a structural result set using a semantic condition. This example returns functions that are semantically related to 'TLS handshake'. ```BNQL /function[concept("TLS handshake") in .] ``` -------------------------------- ### Find Functions Reachable Within a Depth Source: https://docs.sidekick.binary.ninja/reference/bnql.html Determines functions that are reachable from a starting function within a specified number of call hops. Useful for analyzing call chains. ```BNQL reachable-from(f("main"), depth=3) ``` -------------------------------- ### Manage Notebook Entries and Tasks Source: https://docs.sidekick.binary.ninja/guide/sidekick_api.html Demonstrates the full lifecycle of a notebook entry, including creation, retrieval, context updates, task management, and outcome recording. Prefer omitting entry_id as Sidekick generates a stable ID automatically. Use relevant_domains for filtering and analysis_context for structured intermediate state. ```python from sidekick.api import ( list_notebook_entries, get_notebook_entry, get_notebook_entry_context, create_notebook_entry, update_notebook_entry, delete_notebook_entry, update_notebook_entry_context, add_notebook_task, update_notebook_task, complete_notebook_task, delete_notebook_task, add_notebook_outcome, list_notebook_outcomes, get_notebook_outcome, update_notebook_outcome, delete_notebook_outcome, ) # Create an entry entry = create_notebook_entry( bv, "Investigate custom crypto routine", entry_type="research", relevant_domains=["crypto"], ) # Inspect entries entries = list_notebook_entries(bv) same_entry = get_notebook_entry(bv, entry.id) print(same_entry.analysis_context) # Record structured intermediate analysis state update_notebook_entry_context( bv, entry.id, set={"scope": {"strategy": "small-exhaustive", "functions": ["sub_4011a0"]}}, ) print(get_notebook_entry_context(bv, entry.id)) # Add and complete a task task = add_notebook_task(bv, entry.id, "Trace key schedule") update_notebook_task(bv, entry.id, task.id, status="in_progress") complete_notebook_task(bv, entry.id, task.id) # Record a finding outcome = add_notebook_outcome( bv, entry.id, kind="finding", title="Round key update located at sub_4011a0", confidence=0.85, ) print(get_notebook_outcome(bv, entry.id, outcome.id)) print(list_notebook_outcomes(bv, entry.id)) delete_notebook_entry(bv, entry.id) ``` -------------------------------- ### Executing BNQL Queries (Inside Binary Ninja) Source: https://docs.sidekick.binary.ninja/guide/sidekick_api.html Shows how to execute BNQL queries within the Binary Ninja environment using the `execute_bnql` function. ```APIDOC ## Executing BNQL Queries (Inside Binary Ninja) ### Description When Sidekick is active and a file is open in Binary Ninja, you can directly pass the `bv` object to API functions like `execute_bnql` to run BNQL queries against the current binary view. ### Method `execute_bnql` ### Parameters #### Path Parameters None #### Query Parameters - **bv**: The BinaryView object. - **query**: The BNQL query string. - **limit** (optional): The maximum number of results to return. ### Request Example ```python # Works in the BN scripting console or a script run from the Library panel from sidekick.api import execute_bnql funcs = execute_bnql(bv, "/view/function") print([f.name for f in funcs]) ``` ### Response #### Success Response (200) Returns a list of results based on the BNQL query. ``` -------------------------------- ### Define Struct and Apply to Variable Source: https://docs.sidekick.binary.ninja/reference/bnmf.html This example demonstrates defining a new struct type and then applying it to a function variable. It uses `depends_on` to ensure the type definition is processed first. ```json { "description": "Define connection struct", "binary_view_changes": [{ "modifications": [ { "id": "def_conn", "uri": "bv:type/Connection", "state": {"definition": "struct Connection { int fd; char* hostname; uint16_t port; }"} }, { "uri": "bv:function/0x401000/variable/arg1", "state": {"type": "struct Connection*"}, "depends_on": ["def_conn"] } ] }] } ``` -------------------------------- ### BNQL Predicate Examples Source: https://docs.sidekick.binary.ninja/reference/bnql.html Predicates filter objects after a step. The context item is represented by '.'. Path expressions within predicates evaluate to true if they return a non-empty set. ```plaintext /function[@name == "main"] /datavar[entropy(.) > 7.0] /function[calls::function[@name == "malloc"]] ``` -------------------------------- ### Call a Prompt from Python Source: https://docs.sidekick.binary.ninja/guide/sidekick_api.html Load the 'summarize-function' prompt and use it to summarize a function's code text obtained from a BinaryView object. ```python from sidekick.api import load_prompt, render_object summarize = load_prompt("summarize-function") code_text = render_object(bv.get_function_at(0x401000), verbosity="contents") result = summarize(CODE=code_text) print(result) ``` -------------------------------- ### Attribute Access in BNQL Predicates Source: https://docs.sidekick.binary.ninja/reference/bnql.html Access object properties using '@attribute_name' within predicates. Special attributes like '@name', '@address', and '@start' are available on addressable objects. ```plaintext /function[@name == "main"] /section[@name ~= r"\.text"] /view/tag[@scope == "instruction"] /view/function[@stack_size >= 256] ``` -------------------------------- ### Execute BNQL Query for All Functions Source: https://docs.sidekick.binary.ninja/guide/sidekick_api.html Retrieves all functions from a binary view using a basic BNQL query. ```python from sidekick.api import execute_bnql # All functions funcs = execute_bnql(bv, "/view/function") ``` -------------------------------- ### Component — `bv:component/{component_id}` Source: https://docs.sidekick.binary.ninja/reference/bnmf.html Manipulate components within the Binary Ninja project. A component can be identified by its GUID or name, and the lookup searches recursively through all nested components. ```APIDOC ## `bv:component/{component_id}` ### Description Manipulate components within the Binary Ninja project. `component_id` can be a GUID or a component name. The lookup searches recursively through all nested components. ### Properties - **name** (String): Component display name. - **functions** (Array[String]): Function addresses (hex strings); setting this replaces the entire list. - **datavars** (Array[String]): Data variable addresses (hex strings); setting this replaces the entire list. ### Notes - `state: null` calls `remove_component`. - Use `$add`/`$remove` collection operators to add or remove individual entries without replacing the full list. ``` -------------------------------- ### Loading and using the Sidekick service agent Source: https://docs.sidekick.binary.ninja/guide/sidekick_api.html Demonstrates how to load the built-in service-backed Sidekick chat agent using `load_sidekick_agent()` and interact with it by sending messages. The agent's responses can be retrieved directly or via `last_result` for more details. ```APIDOC ## `load_sidekick_agent()` ### Description Loads the built-in service-backed Sidekick chat agent, which powers the Sidekick GUI. This agent is suitable for direct chat interactions within the workspace. ### Method `sess.load_sidekick_agent(name: str, tool_policy: str = "autonomous") -> LoadedSidekickAgent` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters for `load_sidekick_agent` * **name** (string) - A display label for the chat, appearing in the workspace's chat list and GUI. This is not a spec-file lookup. * **tool_policy** (string, optional) - Defaults to "autonomous". Specifies the tool policy for the agent. ### Usage Example ```python from sidekick.api import init_runtime with init_runtime("/path/to/target.bndb", update_analysis=False) as sess: sidekick = sess.load_sidekick_agent(name="headless-analysis") print(sidekick("Analyze this binary and summarize the likely purpose.")) print(sidekick("Now identify any cryptographic routines.")) # Accessing last result details sidekick("Continue the analysis.") status = sidekick.last_result["status"] pending = sidekick.last_result["pending_approval_count"] # Stable chat IDs for resuming conversations chat_id = sidekick.chat_id thread_id = sidekick.thread_id # To resume: sess.call_agent("message", chat_id=saved_id, create_if_missing=False) ``` ### Response Returns a callable `LoadedSidekickAgent` object. Each call to this object sends a user message, waits for the agent to settle, and returns the assistant's response text. Context carries across successive calls. #### Success Response The callable returns the assistant's response text (string). #### Response Example ``` "Analysis complete. The binary appears to be a network utility." ``` ### Error Handling On failure (timeout, error state, no assistant reply), the callable raises `RuntimeError` with the underlying detail. The most recent response envelope is stored on `agent.last_result`. ``` -------------------------------- ### Importing the Sidekick API Source: https://docs.sidekick.binary.ninja/guide/sidekick_api.html Demonstrates how to import the sidekick.api package and specific public symbols for use in Binary Ninja scripts and Library Python entry points. ```APIDOC ## Importing the Sidekick API ### Description Use this import in Binary Ninja scripts and Library Python entry points when you need Sidekick-managed resources such as indexes, code maps, notebooks, prompts, or agents. All public symbols are also importable directly from `sidekick.api`. ### Code Examples ```python import sidekick.api as api ``` ```python from sidekick.api import execute_bnql, render_object, concept, load_prompt, init_runtime ``` ``` -------------------------------- ### BNQL Combined Semantic and Structural Query Source: https://docs.sidekick.binary.ninja/guide/semantic_indexing.html Combines semantic search with structural query conditions. This example finds functions related to 'network communication' that also call the 'send' function. ```BNQL /function[concept("network communication") in . and calls::function[@name == "send"]] ``` -------------------------------- ### BNQL Semantic Search with Exclusion Source: https://docs.sidekick.binary.ninja/guide/semantic_indexing.html Performs a semantic search and excludes results based on a structural condition. This example finds results related to 'credential' but excludes functions containing 'log' in their name. ```BNQL concept("credential") except /function[@name ~= r".*log.*"] ``` -------------------------------- ### Initialize Headless Sidekick Context Source: https://docs.sidekick.binary.ninja/guide/sidekick_api.html Initialize a headless Sidekick application instance using the sidekick() context manager. This is used for running scripts outside the Binary Ninja GUI. The app_dir stores workspace databases and index data. ```python import sidekick.api as api from pathlib import Path app_dir = Path("~/.sidekick-headless").expanduser() with api.sidekick(app_dir) as sk: with sk.session("/path/to/target.bndb") as sess: funcs = api.execute_bnql(sess.bv, "/view/function", limit=10) print([f.name for f in funcs]) ``` -------------------------------- ### Writing BNDB Metadata Source: https://docs.sidekick.binary.ninja/reference/data_storage.html Illustrates how to write metadata into a Binary Ninja database file using the `store_metadata` API. ```python from binaryninja import Settings # Store a new metadata key-value pair database.store_metadata("sidekick_view_uuid", "some-persistent-uuid") # Store a JSON manifest manifest_data = {"snapshots": ["snapshot_id_1", "snapshot_id_2"]} database.store_metadata("sidekick:portability.manifest", json.dumps(manifest_data)) ``` -------------------------------- ### BNQL Semantic Search for Specific Object Type Source: https://docs.sidekick.binary.ninja/guide/semantic_indexing.html Restricts a semantic search to a specific object type by combining `concept()` with a traversal step. This example searches for functions semantically related to 'file encryption'. ```BNQL concept("file encryption")/^function ``` -------------------------------- ### Search Byte Patterns and References Source: https://docs.sidekick.binary.ninja/reference/bnql.html Use `pattern` to find byte patterns, `xref` for cross-references, `syscall` for specific system calls, and `concept` for semantic searches. These can be combined with `/^function` to find containing functions. ```bnql pattern("48 89 5c 24")/^function # functions containing byte pattern ``` ```bnql xref(0x401000)/^function # functions that reference address ``` ```bnql syscall(1)/^function # functions making syscall 1 (write on Linux) ``` ```bnql concept("string decryption")/function # functions semantically related to string decryption ``` -------------------------------- ### Open Project File in Session Source: https://docs.sidekick.binary.ninja/guide/sidekick_api.html Opens a specific file within a project-backed session. Accepts various identifiers for the file. ```python with api.sidekick(app_dir) as sk: with sk.session(project) as sess: bv = sess.open_project_file("libfoo.so.bndb") results = api.execute_bnql(sess.binary_view_set, "/view/function") ``` -------------------------------- ### Retrieve IL Representations Source: https://docs.sidekick.binary.ninja/reference/bnql.html Use `hlil`, `mlil`, and `llil` to get High-Level, Medium-Level, and Low-Level Intermediate Language representations, respectively. These functions accept various inputs like function names, addresses, or instructions. ```bnql hlil("main") # HLIL function for main ``` ```bnql mlil(/view/function) # MLIL for all functions ``` ```bnql /view/string/used-by::instruction/hlil(.) # HLIL instructions using strings ``` -------------------------------- ### List All Functions in Binary Source: https://docs.sidekick.binary.ninja/reference/bnql.html Retrieves all function objects within the currently open binary view. This is a fundamental query for function analysis. ```BNQL /function ``` -------------------------------- ### create_notebook_entry Source: https://docs.sidekick.binary.ninja/guide/sidekick_api.html Creates a new notebook entry with a description and optional parameters like entry type and relevant domains. ```APIDOC ## create_notebook_entry(bv, description, *, entry_type="operational", relevant_domains=None, entry_id=None) ### Description Creates a new notebook entry. If `entry_id` is not provided, Sidekick will generate one. ### Method Not applicable (Python function) ### Endpoint Not applicable (Python function) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **bv** (object) - Required - The binary view object. - **description** (str) - Required - A description for the new notebook entry. - **entry_type** (str) - Optional - The type of the entry (e.g., "operational"). Defaults to "operational". - **relevant_domains** (list) - Optional - Domains relevant to this entry. - **entry_id** (str) - Optional - A specific ID for the entry. If omitted, one is generated. ``` -------------------------------- ### Library Python Automation Recipe for Tailcalls Source: https://docs.sidekick.binary.ninja/guide/sidekick_api.html A recommended pattern for Library automations using sidekick.api to collect and index tail call instructions within a binary. It reuses or creates an index and safely adds objects, preventing duplicates. ```python import sidekick.api as api from binaryninja import MediumLevelILOperation TAILCALL_OPS = { MediumLevelILOperation.MLIL_TAILCALL, MediumLevelILOperation.MLIL_TAILCALL_UNTYPED, MediumLevelILOperation.MLIL_TAILCALL_SSA, MediumLevelILOperation.MLIL_TAILCALL_UNTYPED_SSA, } # Reuse the current workspace index or create it on first run. api.get_index(bv, "tailcalls", create_if_missing=True) # Collect Binary Ninja objects of any indexable kind. add_index_objects # accepts the objects directly and derives canonical object IDs for them. tailcalls = [ insn for func in bv.functions if func.mlil is not None for insn in func.mlil.instructions if insn.operation in TAILCALL_OPS ] entries = api.add_index_objects( bv, "tailcalls", objects=tailcalls, prevent_duplicates=True, ) print({"index": "tailcalls", "added": len(entries)}) ``` -------------------------------- ### Loading a custom agent with structured output Source: https://docs.sidekick.binary.ninja/guide/sidekick_api.html Shows how to load a custom agent defined in a YAML file and configure it to return structured JSON output by specifying an `output_schema` and ensuring the system prompt requests JSON matching that schema. ```APIDOC ## `sess.load_agent(name: str, output_schema: dict = None, tool_policy: str = "autonomous")` ### Description Loads a custom agent defined in a YAML file. Can be configured to return structured output by providing an `output_schema`. ### Parameters * **name** (string) - The name of the agent to load (resolves from script roots). * **output_schema** (dict, optional) - A dictionary defining the expected JSON schema for the agent's output. The system prompt should explicitly require JSON matching this schema. * **tool_policy** (string, optional) - Defaults to "autonomous". Specifies the tool policy for the agent. ### Usage Example (with `output_schema`) ```yaml # agent.triage.yaml version: 1 protocol_id: triage completion_pool_id: smart output_schema: type: object properties: verdict: { type: string } rationale: { type: string } required: [verdict, rationale] uses_tags: - database prompt_template: messages: - role: system content: "Analyze the target and respond with JSON matching the output schema." - role: user content: "Triage this function:\n\n{{TARGET_FUNCTION}}" variables: TARGET_FUNCTION: name: TARGET_FUNCTION required: true ``` ```python # Assuming TARGET_FUNCTION is a variable representing a function # and 'func' is a variable holding the function object with init_runtime(bv) as sess: triage = sess.load_agent("triage") result = triage(TARGET_FUNCTION=func) print(result["verdict"], result["rationale"]) ``` ### Response Returns a callable agent object. When `output_schema` is provided and the prompt is correctly formatted, the callable returns a parsed dictionary matching the schema. ``` -------------------------------- ### Enable Semantic Search in Headless Session Source: https://docs.sidekick.binary.ninja/guide/sidekick_api.html Initializes a headless session with semantic search enabled and waits for the index to be ready. Use this when performing concept searches in scripts. ```python with api.sidekick(app_dir, semantic_index=True) as sk: with sk.session("/path/to/target.bndb") as sess: sess.wait_for_semantic_index_ready(timeout_secs=120.0) matches = api.concept(sess.bv, "credential handling") ``` -------------------------------- ### Render BNQL Results to Summaries Source: https://docs.sidekick.binary.ninja/guide/sidekick_api.html Executes a BNQL query and then renders the resulting objects into human-readable summaries. ```python from sidekick.api import execute_bnql, render_object funcs = execute_bnql(bv, "/view/function", limit=5) summaries = [render_object(f, verbosity="summary") for f in funcs] ``` -------------------------------- ### Import Sidekick API Source: https://docs.sidekick.binary.ninja/guide/sidekick_api.html Import the main sidekick.api package for use in Binary Ninja scripts and Library Python entry points. ```python import sidekick.api as api ``` -------------------------------- ### Minimal MCP Tools Configuration Source: https://docs.sidekick.binary.ninja/guide/mcp_tools.html This is a basic configuration for an MCP server, specifying the command to run and the tools to expose. Ensure the command path is correct for your environment. ```json { "version": "1.0", "servers": [ { "name": "my_tools", "server_config": { "command": ["python3", "/path/to/my_mcp_server.py"], "timeout": 30 }, "tools": [ { "name": "tool_a", "enabled": true }, { "name": "tool_b", "enabled": true } ], "enabled": true } ] } ``` -------------------------------- ### Rewrite query_binary to sidekick.api.execute_bnql Source: https://docs.sidekick.binary.ninja/migrating-from-5x.html During script import, `query_binary(...)` calls are automatically rewritten to `sidekick.api.execute_bnql(...)` to adapt to the new API surface in version 26. ```python query_binary(...) is rewritten to sidekick.api.execute_bnql(...). ``` -------------------------------- ### Load and Use Agent with Structured Output Source: https://docs.sidekick.binary.ninja/guide/sidekick_api.html Loads an agent defined with a structured output schema and calls it with a function argument, then accesses the parsed dictionary result. This demonstrates how to consume structured agent output. ```python with init_runtime(bv) as sess: triage = sess.load_agent("triage") result = triage(TARGET_FUNCTION=func) print(result["verdict"], result["rationale"]) ``` -------------------------------- ### Headless Sidekick with Temporary Directory Source: https://docs.sidekick.binary.ninja/guide/sidekick_api.html Run headless Sidekick scripts using a temporary directory for workspace data. The cleanup_app_dir=True option ensures the temporary state is removed upon exiting the context manager. ```python from tempfile import TemporaryDirectory with TemporaryDirectory(prefix="sidekick-headless-") as tmp: with api.sidekick(tmp, cleanup_app_dir=True) as sk: with sk.session("/path/to/target.bndb") as sess: funcs = api.execute_bnql(sess.bv, "/view/function", limit=10) ``` -------------------------------- ### load_prompt Source: https://docs.sidekick.binary.ninja/guide/sidekick_api.html Loads a prompt and returns a callable `LoadedPrompt`. ```APIDOC ## load_prompt(name, *, root=None, completion_pool=None) ### Description Loads a prompt and returns a callable `LoadedPrompt`. ### Method Not applicable (Python function) ### Endpoint Not applicable (Python function) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```python # Example usage: loaded_prompt = load_prompt("my_prompt") ``` ### Response #### Success Response - **LoadedPrompt** (callable) - A callable prompt object. ``` -------------------------------- ### Enable and Use Semantic Indexing in Headless Mode Source: https://docs.sidekick.binary.ninja/guide/semantic_indexing.html Explicitly enable semantic indexing for headless sessions. Ensure the index is ready before querying. ```python with api.sidekick("/tmp/sidekick-headless", semantic_index=True, cleanup_app_dir=True) as sk: with sk.session("/tmp/sample.bndb") as sess: sess.wait_for_semantic_index_ready(timeout_secs=120.0) results = api.concept(sess.bv, "credential handling", object_type="function") for func, score, _ in results: print(func.name, score) ``` -------------------------------- ### Register Sidekick MCP Server with Claude Code CLI Source: https://docs.sidekick.binary.ninja/guide/mcp_server.html Use this command to register the Sidekick MCP server with the Claude Code CLI. Ensure you replace placeholders with your actual paths. ```bash claude mcp add sidekick \ -e BN_USER_DIRECTORY=/path/to/binja/user/dir \ -- /path/to/binja/python \ /path/to/Vector35_Sidekick/sidekick/mcp_server/launch.py ``` -------------------------------- ### Register Sidekick MCP Server with Generic stdio JSON Source: https://docs.sidekick.binary.ninja/guide/mcp_server.html Configure the Sidekick MCP server for MCP clients that accept a JSON configuration. This specifies the command, arguments, and environment variables for the server launcher. ```json { "mcpServers": { "sidekick": { "command": "/path/to/binja/python", "args": [ "/path/to/Vector35_Sidekick/sidekick/mcp_server/launch.py" ], "env": { "BN_USER_DIRECTORY": "/path/to/binja/user/dir" } } } } ``` -------------------------------- ### Configure Smart Pool with Failover Source: https://docs.sidekick.binary.ninja/guide/sidekick_api.html Define a 'smart' completion pool using a local Ollama endpoint as primary and the 'sidekick' endpoint as a failover. Set temperature parameters for each. ```yaml group_id: smart completers: - endpoint_id: ollama parameters: temperature: 0.2 - endpoint_id: sidekick parameters: temperature: 0.2 ``` -------------------------------- ### Configure Python MCP Server in Sidekick Source: https://docs.sidekick.binary.ninja/guide/mcp_tools.html Reference a custom Python MCP server in your Sidekick configuration. This allows the agent to discover and use the tools exposed by the server. ```json { "version": "1.0", "servers": [ { "name": "my_tools", "server_config": { "command": ["python3", "/path/to/my_mcp_server.py"] }, "tools": [ { "name": "echo" }, { "name": "get_time" } ] } ] } ``` -------------------------------- ### Accessing BNDB Metadata Source: https://docs.sidekick.binary.ninja/reference/data_storage.html Demonstrates how to query metadata stored within a Binary Ninja database file using the `query_metadata` API. ```python from binaryninja import Settings # Query a specific metadata key view_uuid = database.query_metadata("sidekick_view_uuid") # Query all metadata keys starting with a prefix portability_keys = database.query_metadata("sidekick:portability.", True) ``` -------------------------------- ### Sidekick Directory Layout Source: https://docs.sidekick.binary.ninja/reference/data_storage.html This illustrates the hierarchical structure of the Sidekick data directory, including subdirectories for configuration, kernel state, databases, cache, and filestore. ```shell $BN_USER_DIRECTORY/sidekick/ ├── config/ │ ├── completion_routing/ │ ├── mcp_tools_config.json │ └── .meta.*.yaml ├── kernel/ │ └── .meta.*.yaml ├── data/ │ ├── workspaces.db │ └── semantics.db ├── cache/ │ ├── models/ │ ├── embedding.lock │ └── reranking.lock └── filestore/ ├── workspaces/ │ └── / │ └── processes/ │ └── / │ └── repos/ │ └── / └── app/ └── processes/ └── __global__/ └── repos/ └── / ``` -------------------------------- ### Execute BNQL Query Source: https://docs.sidekick.binary.ninja/guide/sidekick_api.html Run a BNQL query against the target and retrieve results as a list of objects. A time limit can be specified for the query execution. ```python results = sidekick.execute_bnql(target=runtime.bv, query="SELECT * FROM functions") ``` -------------------------------- ### Execute BNQL Query with Limit and Sorting Source: https://docs.sidekick.binary.ninja/guide/sidekick_api.html Retrieves a limited number of functions, sorted by name, using BNQL. ```python from sidekick.api import execute_bnql # First 20 functions sorted by name funcs = execute_bnql(bv, "/view/function", limit=20) ```