Building and Using Indexes¶
Indexes are named collections of binary locations — functions, data variables, strings, or any other addressable object — that you want to track as a group. They give you a persistent, filterable, and navigable list of points of interest that you can build by querying the binary, curating manually, or letting Sidekick populate automatically during analysis.
Use indexes to:
- Track candidate functions for deeper review (e.g., all callers of
malloc). - Collect functions that Sidekick should analyze in a batch.
- Record the results of an automated analysis run with per-entry metadata.
- Build a curated list of interesting locations across multiple binaries in a project.
The Indexes Sidebar¶
Open the Indexes sidebar by clicking the Sidekick Indexes icon in the Binary Ninja sidebar. The sidebar has two main areas:
- Browse list — shows all indexes for the current workspace, sorted by most recently updated (pinned indexes appear first).
- Detail view — shows the entries of the selected index in a sortable, filterable table.
At the top of the sidebar there is a Query Editor text box. Its behavior changes depending on context:
- When no index is selected, typing a BNQL query and pressing Enter creates a new index and populates it with the results.
- When a BNQL index is selected, the query editor shows the current query. Editing it and pressing Enter re-runs the query and refreshes the index.
- When a manual index is selected, submitting a query adds the query results to the existing entries without replacing them.
Index Types¶
Every index has a type that controls how it is populated and whether entries can be refreshed.
| Type | How it is populated | Refreshable | User curation |
|---|---|---|---|
| BNQL | A single BNQL query | Yes — re-runs the query | No |
| Script | A script execution | Yes — re-runs the script | No |
| Manual | Any combination of queries and manual additions | No | Yes |
Sidekick-driven analysis creates manual indexes by default. When you submit a query from the Query Editor, Sidekick creates a BNQL index.
You can convert a BNQL or Script index to a Manual index at any time (see Converting an index to manual).
Note
Script indexes cannot be created from the UI. They are created programmatically — either via the Sidekick Python API in a Library script, or by Sidekick agents that run scripts as part of automated analysis. A Script index behaves like a BNQL index in all other respects: it is refreshable and does not allow manual entry curation.
Creating an Index¶
From the Query Editor¶
- Open the Indexes sidebar.
- Type a BNQL query in the Query Editor at the top (e.g.,
callers("malloc")). - Press Enter.
Sidekick executes the query in the background and creates a new index populated with the results. The index is automatically given a name derived from the query; you can rename it at any time.
From the New button¶
To create an empty manual index:
- Open the Indexes sidebar.
- Click the + (New Index) button in the toolbar.
An empty index opens in the detail view. You can rename it immediately and add entries later.
Managing Indexes¶
Renaming an index¶
Double-click the index name in the browse list to edit it inline, then press Enter to confirm.
Deleting an index¶
Right-click the index in the browse list and select Delete Index. Confirm the prompt. Deletion is permanent.
Viewing index properties¶
Right-click the index and select View Properties to see its type, creation and update timestamps, source query (if applicable), entry counts, and whether user curation is allowed.
Pinning an index to the list¶
Right-click an index and select Pin to keep it at the top of the browse list. Select Unpin to remove the pin. Pinned indexes are shown with a pin icon in the list.
To show only pinned indexes, open the hamburger menu (the three-line menu button in the toolbar) and select Show Pinned Indexes Only. Select Show All Indexes to restore the full list.
Refreshing a BNQL index¶
For BNQL indexes, you can re-run the source query to update the entries:
- Open the hamburger menu and select Refresh Index, or
- Edit the query in the Query Editor and press Enter.
Refreshing replaces all entries with the new results.
Converting an index to manual¶
Converting changes a BNQL or Script index into a Manual index. This:
- Marks all existing entries as user-curated, so they are preserved.
- Allows entries from multiple queries to be accumulated.
- Removes the ability to refresh from the original source.
To convert, right-click the index in the browse list (or open the hamburger menu) and select Convert to Manual Index. The conversion cannot be undone.
Working with Index Entries¶
The detail view shows a table with one row per entry. The columns are:
- Address — the hexadecimal address of the entry in the binary.
- Entry — a disassembly-style rendering of the object at that address.
- Metadata columns — any metadata keys attached to entries appear as additional columns, added dynamically as entries with metadata are loaded.
Columns can be sorted by clicking the column header, resized by dragging the header borders, and reordered by dragging the header. Column layout is saved per-index.
Use the Filter entries text box above the table to narrow the displayed rows. Filtering is case-insensitive and searches across all columns (address, entry text, and metadata).
Navigating to an entry¶
Double-click a row to navigate to the entry's address in the binary. If the entry belongs to a different binary in a multi-binary project, the corresponding tab is activated automatically.
Right-click a row and select Navigate to Address for the same behavior from the context menu.
Copying entries¶
Select one or more rows, right-click, and select Copy. The selection is copied to the clipboard as tab-separated text.
Removing entries¶
Select one or more rows, right-click, and select Remove Selected Entries to delete them from the index.
Note
For BNQL and Script indexes, removed entries return the next time the index is refreshed. Convert the index to manual first if you want removals to be permanent.
Pinning an Index to a Pane¶
You can open any index in a dedicated pane that stays visible alongside the main Binary Ninja UI:
- Right-click the index in the browse list and select Pin Index to New Pane.
The pane opens in a horizontal split and contains the same filter-and-table view as the sidebar detail view. It updates live as the index changes. Close the pane to dismiss it.
Querying with BNQL¶
The Query Editor accepts any valid BNQL query. BNQL is a path-based language for selecting objects in a binary. For a complete syntax reference, see the BNQL Reference.
Some common patterns for building indexes:
All functions in the binary:
Functions that call a specific API:
Functions that call a large number of other functions:
High-entropy global variables (potential keys or constants):
Functions matching a semantic concept (requires semantic indexing):
Combining multiple result sets:
Result limit¶
The UI limits query results to 1000 entries per execution by default. You can change this limit in Edit > Preferences > Settings by searching for sidekick.ui.indexes.max_query_results. For queries that may produce more results than the configured limit, use the Python API to run the query without a limit.
Integration with Chat¶
The assistant can inspect existing indexes with query_indexes and modify them with update_index.
Use Chat when you want collaborative questions such as:
- "Which index already contains the TLS handlers?"
- "Do we already have an index for packet parsers?"
- "Update the crypto work queue index to include these new functions."
query_indexes supports three common patterns:
- No arguments — list the visible indexes.
ref=...— resolve one index by name or resource ID prefix.search=...— search across index names, summaries, and entry content.
Entry IDs are hidden in query_indexes results by default because they are mainly useful for follow-up mutations. Pass include_entry_ids=true when you need entry IDs for a later update_index removal.
Using Indexes via the Python API¶
The sidekick.api module provides full CRUD access to indexes from Binary Ninja scripts. The examples below cover the most common patterns. For the full API surface, see Scripting and Automation with the Sidekick API.
Creating an index and populating it from a BNQL query¶
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)})
Attaching metadata to entries¶
Each IndexEntry can carry an arbitrary dictionary of key/value metadata. Every unique key across all entries in an index becomes an additional column in the detail view table.
from sidekick.api import create_index, execute_bnql
from sidekick.binja.resources.index import make_index_entry
idx = create_index(bv, "scored-functions")
funcs = execute_bnql(bv, "/view/function")
entries_to_add = []
for func in funcs:
entry = make_index_entry(
obj=func,
metadata={"block_count": len(list(func.basic_blocks))}
)
if entry:
entries_to_add.append(entry)
idx.add_entries(entries_to_add, prevent_duplicates=True, notify=True)
The block_count key appears as a sortable column in the Indexes sidebar once the entries are loaded.
Searching Across Indexes¶
The search box in the Indexes sidebar toolbar searches across index names, summaries, and entry contents simultaneously. Results are ranked by hit count, which is shown as a subtitle on each matching list item.
Indexes and Automation¶
Sidekick agents can read from and write to indexes during automated analysis. When an agent completes its work, any index changes it made are applied directly — there is no separate review or accept step.
Agents that write to indexes typically create or update manual indexes, accumulating entries across multiple analysis passes without overwriting previous results.
Tip
To direct an agent's output to a specific index, create the index before starting the task and reference its name in your instructions to the agent.