Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
a040ee1
generate protobuf types
brendan-kellam Nov 14, 2025
cca3d30
stream poc over SSE
brendan-kellam Nov 14, 2025
9cd3236
wip: make stream search api follow existing schema. Modify UI to supp…
brendan-kellam Nov 15, 2025
9f66c45
fix scrolling issue
brendan-kellam Nov 15, 2025
4f39451
Dockerfile
brendan-kellam Nov 15, 2025
cfdadf2
wip on lezer parser grammar for query language
brendan-kellam Nov 15, 2025
8dce2aa
add lezer tree -> grpc transformer
brendan-kellam Nov 16, 2025
46c8d60
remove spammy log message
brendan-kellam Nov 17, 2025
ac9d05a
fix syntax highlighting by adding a module resolution for @lezer/common
brendan-kellam Nov 17, 2025
b966b63
further wip on query language
brendan-kellam Nov 17, 2025
69e0a1a
Add case sensitivity and regexp toggles
brendan-kellam Nov 17, 2025
e6859cb
Improved type safety / cleanup for query lang
brendan-kellam Nov 18, 2025
307e17e
support search contexts
brendan-kellam Nov 18, 2025
09581f3
update Dockerfile with query langauge package
brendan-kellam Nov 18, 2025
b09def9
fix filter
brendan-kellam Nov 18, 2025
74376c0
Add skeletons to filter panel when search is streaming
brendan-kellam Nov 18, 2025
c7ba32f
add client side caching
brendan-kellam Nov 18, 2025
5ab585c
improved cancelation handling
brendan-kellam Nov 19, 2025
9c9b6b9
add isSearchExausted flag for flagging when a search captured all res…
brendan-kellam Nov 19, 2025
d55dd13
Add back posthog search_finished event
brendan-kellam Nov 19, 2025
afcc30d
remove zoekt tenant enforcement
brendan-kellam Nov 19, 2025
898c909
migrate blocking search over to grpc. Centralize everything in searchApi
brendan-kellam Nov 19, 2025
696d06b
branch handling
brendan-kellam Nov 20, 2025
aad3507
plumb file weburl
brendan-kellam Nov 20, 2025
3fd5f49
add repo_sets filter for repositories a user has access to
brendan-kellam Nov 20, 2025
bddbb76
refactor a bunch of stuff + add support for passing in Query IR to se…
brendan-kellam Nov 20, 2025
ceee66e
refactor
brendan-kellam Nov 21, 2025
1d1205f
dev README
brendan-kellam Nov 21, 2025
5c624cd
wip on better error handling
brendan-kellam Nov 21, 2025
55a3e9e
error handling for stream path
brendan-kellam Nov 21, 2025
93a3f89
update mcp
brendan-kellam Nov 21, 2025
a6e4092
changelog wip
brendan-kellam Nov 21, 2025
f52dfc7
type fix
brendan-kellam Nov 21, 2025
c477d76
style
brendan-kellam Nov 21, 2025
2f6fc04
Support rev:* wildcard
brendan-kellam Nov 21, 2025
5c80c53
changelog
brendan-kellam Nov 21, 2025
7c964d9
changelog nit
brendan-kellam Nov 21, 2025
ac19251
feedback
brendan-kellam Nov 21, 2025
d9ff676
fix build
brendan-kellam Nov 22, 2025
aac88a6
update docs and remove uneeded test file
brendan-kellam Nov 22, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .env.development
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ DATABASE_URL="postgresql://postgres:postgres@localhost:5432/postgres"
ZOEKT_WEBSERVER_URL="http://localhost:6070"
# The command to use for generating ctags.
CTAGS_COMMAND=ctags
# logging, strict
SRC_TENANT_ENFORCEMENT_MODE=strict

# Auth.JS
# You can generate a new secret with:
Expand Down
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

<!-- Bump @sourcebot/mcp since there are breaking changes to the api in this release -->

### Added
- Added support for streaming code search results. [#623](https://github.com/sourcebot-dev/sourcebot/pull/623)
- Added buttons to toggle case sensitivity and regex patterns. [#623](https://github.com/sourcebot-dev/sourcebot/pull/623)
- Added counts to members, requets, and invites tabs in the members settings. [#621](https://github.com/sourcebot-dev/sourcebot/pull/621)

### Changed
- Changed the default search behaviour to match patterns as substrings and **not** regular expressions. Regular expressions can be used by toggling the regex button in search bar. [#623](https://github.com/sourcebot-dev/sourcebot/pull/623)
- Renamed `public` query prefix to `visibility`. Allowed values for `visibility` are `public`, `private`, and `any`. [#623](https://github.com/sourcebot-dev/sourcebot/pull/623)
- Changed `archived` query prefix to accept values `yes`, `no`, and `only`. [#623](https://github.com/sourcebot-dev/sourcebot/pull/623)

### Removed
- Removed `case` query prefix. [#623](https://github.com/sourcebot-dev/sourcebot/pull/623)
- Removed `branch` and `b` query prefixes. Please use `rev:` instead. [#623](https://github.com/sourcebot-dev/sourcebot/pull/623)
- Removed `regex` query prefix. [#623](https://github.com/sourcebot-dev/sourcebot/pull/623)

### Fixed
- Fixed spurious infinite loads with explore panel, file tree, and file search command. [#617](https://github.com/sourcebot-dev/sourcebot/pull/617)
- Wipe search context on init if entitlement no longer exists [#618](https://github.com/sourcebot-dev/sourcebot/pull/618)
Expand Down
9 changes: 8 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,12 @@ COPY .yarn ./.yarn
COPY ./packages/db ./packages/db
COPY ./packages/schemas ./packages/schemas
COPY ./packages/shared ./packages/shared
COPY ./packages/queryLanguage ./packages/queryLanguage

RUN yarn workspace @sourcebot/db install
RUN yarn workspace @sourcebot/schemas install
RUN yarn workspace @sourcebot/shared install
RUN yarn workspace @sourcebot/query-language install
# ------------------------------------

# ------ Build Web ------
Expand Down Expand Up @@ -92,6 +94,7 @@ COPY --from=shared-libs-builder /app/node_modules ./node_modules
COPY --from=shared-libs-builder /app/packages/db ./packages/db
COPY --from=shared-libs-builder /app/packages/schemas ./packages/schemas
COPY --from=shared-libs-builder /app/packages/shared ./packages/shared
COPY --from=shared-libs-builder /app/packages/queryLanguage ./packages/queryLanguage

# Fixes arm64 timeouts
RUN yarn workspace @sourcebot/web install
Expand Down Expand Up @@ -130,6 +133,7 @@ COPY --from=shared-libs-builder /app/node_modules ./node_modules
COPY --from=shared-libs-builder /app/packages/db ./packages/db
COPY --from=shared-libs-builder /app/packages/schemas ./packages/schemas
COPY --from=shared-libs-builder /app/packages/shared ./packages/shared
COPY --from=shared-libs-builder /app/packages/queryLanguage ./packages/queryLanguage
RUN yarn workspace @sourcebot/backend install
RUN yarn workspace @sourcebot/backend build

Expand Down Expand Up @@ -173,7 +177,6 @@ ENV DATA_DIR=/data
ENV DATA_CACHE_DIR=$DATA_DIR/.sourcebot
ENV DATABASE_DATA_DIR=$DATA_CACHE_DIR/db
ENV REDIS_DATA_DIR=$DATA_CACHE_DIR/redis
ENV SRC_TENANT_ENFORCEMENT_MODE=strict
ENV SOURCEBOT_PUBLIC_KEY_PATH=/app/public.pem

# Valid values are: debug, info, warn, error
Expand Down Expand Up @@ -217,6 +220,9 @@ COPY --from=zoekt-builder \
/cmd/zoekt-index \
/usr/local/bin/

# Copy zoekt proto files (needed for gRPC client at runtime)
COPY vendor/zoekt/grpc/protos /app/vendor/zoekt/grpc/protos

# Copy all of the things
COPY --from=web-builder /app/packages/web/public ./packages/web/public
COPY --from=web-builder /app/packages/web/.next/standalone ./
Expand All @@ -229,6 +235,7 @@ COPY --from=shared-libs-builder /app/node_modules ./node_modules
COPY --from=shared-libs-builder /app/packages/db ./packages/db
COPY --from=shared-libs-builder /app/packages/schemas ./packages/schemas
COPY --from=shared-libs-builder /app/packages/shared ./packages/shared
COPY --from=shared-libs-builder /app/packages/queryLanguage ./packages/queryLanguage

# Fixes git "dubious ownership" issues when the volume is mounted with different permissions to the container.
RUN git config --global safe.directory "*"
Expand Down
43 changes: 31 additions & 12 deletions docs/docs/features/search/syntax-reference.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,51 @@ title: Writing search queries

Sourcebot uses a powerful regex-based query language that enabled precise code search within large codebases.


## Syntax reference guide

Queries consist of space-separated regular expressions. Wrapping expressions in `""` combines them. By default, a file must have at least one match for each expression to be included.
Queries consist of space-separated search patterns that are matched against file contents. A file must have at least one match for each expression to be included. Queries can optionally contain search filters to further refine the search results.

## Keyword search (default)

Keyword search matches search patterns exactly in file contents. Wrapping search patterns in `""` combines them as a single expression.

| Example | Explanation |
| :--- | :--- |
| `foo` | Match files with regex `/foo/` |
| `foo bar` | Match files with regex `/foo/` **and** `/bar/` |
| `"foo bar"` | Match files with regex `/foo bar/` |
| `foo` | Match files containing the keyword `foo` |
| `foo bar` | Match files containing both `foo` **and** `bar` |
| `"foo bar"` | Match files containing the phrase `foo bar` |
| `"foo \"bar\""` | Match files containing `foo "bar"` exactly (escaped quotes) |

## Regex search

Multiple expressions can be or'd together with `or`, negated with `-`, or grouped with `()`.
Toggle the regex button (`.*`) in the search bar to interpret search patterns as regular expressions.

| Example | Explanation |
| :--- | :--- |
| `foo or bar` | Match files with regex `/foo/` **or** `/bar/` |
| `foo -bar` | Match files with regex `/foo/` but **not** `/bar/` |
| `foo (bar or baz)` | Match files with regex `/foo/` **and** either `/bar/` **or** `/baz/` |
| `foo` | Match files with regex `/foo/` |
| `foo.*bar` | Match files with regex `/foo.*bar/` (foo followed by any characters, then bar) |
| `^function\s+\w+` | Match files with regex `/^function\s+\w+/` (function at start of line, followed by whitespace and word characters) |
| `"foo bar"` | Match files with regex `/foo bar/`. Quotes are not matched. |

Expressions can be prefixed with certain keywords to modify search behavior. Some keywords can be negated using the `-` prefix.
## Search filters

Search queries (keyword or regex) can include multiple search filters to further refine the search results. Some filters can be negated using the `-` prefix.

| Prefix | Description | Example |
| :--- | :--- | :--- |
| `file:` | Filter results from filepaths that match the regex. By default all files are searched. | `file:README` - Filter results to filepaths that match regex `/README/`<br/>`file:"my file"` - Filter results to filepaths that match regex `/my file/`<br/>`-file:test\.ts$` - Ignore results from filepaths match regex `/test\.ts$/` |
| `repo:` | Filter results from repos that match the regex. By default all repos are searched. | `repo:linux` - Filter results to repos that match regex `/linux/`<br/>`-repo:^web/.*` - Ignore results from repos that match regex `/^web\/.*` |
| `repo:` | Filter results from repos that match the regex. By default all repos are searched. | `repo:linux` - Filter results to repos that match regex `/linux/`<br/>`-repo:^web/.*` - Ignore results from repos that match regex `/^web\/.*/` |
| `rev:` | Filter results from a specific branch or tag. By default **only** the default branch is searched. | `rev:beta` - Filter results to branches that match regex `/beta/` |
| `lang:` | Filter results by language (as defined by [linguist](https://github.com/github-linguist/linguist/blob/main/lib/linguist/languages.yml)). By default all languages are searched. | `lang:TypeScript` - Filter results to TypeScript files<br/>`-lang:YAML` - Ignore results from YAML files |
| `sym:` | Match symbol definitions created by [universal ctags](https://ctags.io/) at index time. | `sym:\bmain\b` - Filter results to symbols that match regex `/\bmain\b/` |
| `context:` | Filter results to a predefined [search context](/docs/features/search/search-contexts). | `context:web` - Filter results to the web context<br/>`-context:pipelines` - Ignore results from the pipelines context |
| `context:` | Filter results to a predefined [search context](/docs/features/search/search-contexts). | `context:web` - Filter results to the web context<br/>`-context:pipelines` - Ignore results from the pipelines context |

## Boolean operators & grouping

By default, space-separated expressions are and'd together. Using the `or` keyword as well as parentheses `()` can be used to create more complex boolean logic. Parentheses can be negated using the `-` prefix.

| Example | Explanation |
| :--- | :--- |
| `foo or bar` | Match files containing `foo` **or** `bar` |
| `foo (bar or baz)` | Match files containing `foo` **and** either `bar` **or** `baz`. |
| `-(foo) bar` | Match files containing `bar` **and not** `foo`. |
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"dev:prisma:studio": "yarn with-env yarn workspace @sourcebot/db prisma:studio",
"dev:prisma:migrate:reset": "yarn with-env yarn workspace @sourcebot/db prisma:migrate:reset",
"dev:prisma:db:push": "yarn with-env yarn workspace @sourcebot/db prisma:db:push",
"build:deps": "yarn workspaces foreach --recursive --topological --from '{@sourcebot/schemas,@sourcebot/db,@sourcebot/shared}' run build"
"build:deps": "yarn workspaces foreach --recursive --topological --from '{@sourcebot/schemas,@sourcebot/db,@sourcebot/shared,@sourcebot/query-language}' run build"
},
"devDependencies": {
"concurrently": "^9.2.1",
Expand All @@ -27,6 +27,7 @@
},
"packageManager": "yarn@4.7.0",
"resolutions": {
"prettier": "3.5.3"
"prettier": "3.5.3",
"@lezer/common": "1.3.0"
}
}
1 change: 0 additions & 1 deletion packages/backend/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ const listenToShutdownSignals = () => {
const cleanup = async (signal: string) => {
try {
if (receivedSignal) {
logger.debug(`Recieved repeat signal ${signal}, ignoring.`);
return;
}
receivedSignal = true;
Expand Down
2 changes: 2 additions & 0 deletions packages/db/src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
import type { User, Account } from ".prisma/client";
export type UserWithAccounts = User & { accounts: Account[] };
export * from ".prisma/client";
3 changes: 3 additions & 0 deletions packages/mcp/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Changed
- Updated API client to match the latest Sourcebot release. [#555](https://github.com/sourcebot-dev/sourcebot/pull/555)

## [1.0.9] - 2025-11-17

### Added
Expand Down
8 changes: 2 additions & 6 deletions packages/mcp/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,12 @@ server.tool(
query += ` ( lang:${languages.join(' or lang:')} )`;
}

if (caseSensitive) {
query += ` case:yes`;
} else {
query += ` case:no`;
}

const response = await search({
query,
matches: env.DEFAULT_MATCHES,
contextLines: env.DEFAULT_CONTEXT_LINES,
isRegexEnabled: true,
isCaseSensitivityEnabled: caseSensitive,
});

if (isServiceError(response)) {
Expand Down
21 changes: 11 additions & 10 deletions packages/mcp/src/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,17 @@ export const symbolSchema = z.object({
kind: z.string(),
});

export const searchOptionsSchema = z.object({
matches: z.number(), // The number of matches to return.
contextLines: z.number().optional(), // The number of context lines to return.
whole: z.boolean().optional(), // Whether to return the whole file as part of the response.
isRegexEnabled: z.boolean().optional(), // Whether to enable regular expression search.
isCaseSensitivityEnabled: z.boolean().optional(), // Whether to enable case sensitivity.
});

export const searchRequestSchema = z.object({
// The zoekt query to execute.
query: z.string(),
// The number of matches to return.
matches: z.number(),
// The number of context lines to return.
contextLines: z.number().optional(),
// Whether to return the whole file as part of the response.
whole: z.boolean().optional(),
query: z.string(), // The zoekt query to execute.
...searchOptionsSchema.shape,
});

export const repositoryInfoSchema = z.object({
Expand Down Expand Up @@ -109,7 +111,7 @@ export const searchStatsSchema = z.object({
regexpsConsidered: z.number(),

// FlushReason explains why results were flushed.
flushReason: z.number(),
flushReason: z.string(),
});

export const searchResponseSchema = z.object({
Expand Down Expand Up @@ -139,7 +141,6 @@ export const searchResponseSchema = z.object({
content: z.string().optional(),
})),
repositoryInfo: z.array(repositoryInfoSchema),
isBranchFilteringEnabled: z.boolean(),
isSearchExhaustive: z.boolean(),
});

Expand Down
2 changes: 2 additions & 0 deletions packages/queryLanguage/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/node_modules/
/dist
20 changes: 20 additions & 0 deletions packages/queryLanguage/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "@sourcebot/query-language",
"private": true,
"main": "dist/index.js",
"scripts": {
"build": "lezer-generator src/query.grammar -o src/parser --typeScript --names && tsc",
"test": "vitest",
"postinstall": "yarn build"
},
"devDependencies": {
"@lezer/generator": "^1.8.0",
"tsx": "^4.19.1",
"typescript": "^5.7.3",
"vitest": "^2.1.9"
},
"dependencies": {
"@lezer/common": "^1.3.0",
"@lezer/lr": "^1.4.3"
}
}
7 changes: 7 additions & 0 deletions packages/queryLanguage/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { parser } from "./parser";

type Tree = ReturnType<typeof parser.parse>;
type SyntaxNode = Tree['topNode'];
export type { Tree, SyntaxNode };
export * from "./parser";
export * from "./parser.terms";
21 changes: 21 additions & 0 deletions packages/queryLanguage/src/parser.terms.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// This file was generated by lezer-generator. You probably shouldn't edit it.
export const
negate = 22,
Program = 1,
OrExpr = 2,
AndExpr = 3,
NegateExpr = 4,
PrefixExpr = 5,
ArchivedExpr = 6,
RevisionExpr = 7,
ContentExpr = 8,
ContextExpr = 9,
FileExpr = 10,
ForkExpr = 11,
VisibilityExpr = 12,
RepoExpr = 13,
LangExpr = 14,
SymExpr = 15,
RepoSetExpr = 16,
ParenExpr = 17,
Term = 18
Loading
Loading