Skip to content

Commit 4c6f3bb

Browse files
feat(moss-vscode): isolate Moss in a worker and persist indexes
Run the native Moss runtime in a forked Node worker so crashes cannot take down VS Code, save/load indexes from disk across sessions, and refresh sidebar branding with Moss wordmarks and avatar. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 01e1097 commit 4c6f3bb

22 files changed

Lines changed: 743 additions & 70 deletions

apps/moss-vscode/README.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
1+
<p align="center">
2+
<img src="media/moss_avatar_core.png" alt="Moss" width="96" />
3+
</p>
4+
15
# Moss Code Search (VS Code)
26

37
Semantic search over your open workspace, powered by [Moss](https://moss.dev) — local-first, sub-10ms retrieval via `SessionIndex`.
48

59
## Features
610

7-
- **Manual indexing** — click **Create Index** in the sidebar (no auto-index on open)
11+
- **Manual indexing** — click **Create Index** in the sidebar the first time
12+
- **Persisted indexes** — reopening the same folder restores the saved index (no full rebuild)
813
- Sidebar with live (debounced) semantic search after indexing
914
- Click a result to jump to file + line
10-
- Incremental re-index on save / create / delete / rename
15+
- Incremental re-index on save / create / delete / rename (also saved to disk)
1116
- Credentials via `.env`, VS Code settings, or Secret Storage
1217

1318
## Setup
@@ -35,6 +40,7 @@ Or from the Command Palette after installing a `.vsix`:
3540
| `Moss: Create Index` | Index the open workspace (required before search) |
3641
| `Moss: Rebuild Index` | Re-scan and re-index the workspace |
3742
| `Moss: Configure Credentials` | Store project ID / key in Secret Storage |
43+
| `Moss: Show Logs` | Open the Moss Code Search output channel |
3844

3945
## Settings
4046

@@ -45,6 +51,8 @@ Or from the Command Palette after installing a `.vsix`:
4551

4652
## Architecture
4753

48-
Extension host owns a Moss `SessionIndex` named `vscode-{workspaceHash}`. Files are chunked into `DocumentInfo` records (`{path}#chunk-{n}`) with metadata for navigation. Queries run in-process against the local session.
54+
Extension host owns UI and file scanning. Moss native runtime runs in a separate Node worker (`dist/mossWorker.js`) so a native crash cannot take down VS Code. Sessions are named `vscode-{workspaceHash}`. Files are chunked into `DocumentInfo` records (`{path}#chunk-{n}`) with metadata for navigation.
55+
56+
After **Create Index**, the session is written with Moss `saveToDisk` under the extension global storage (`indexes/{workspaceHash}/`), plus a `meta.json` map of file → chunk counts. Reopening that folder loads the cache with `loadFromDisk` so search works immediately. Use **Moss: Rebuild Index** to force a full reindex.
4957

50-
Native modules (`@moss-dev/moss`, `@moss-dev/moss-core`) are left external by esbuild and loaded from `node_modules` at runtime.
58+
Native modules (`@moss-dev/moss`, `@moss-dev/moss-core`) are left external by esbuild and loaded from `node_modules` at runtime in the worker.

apps/moss-vscode/esbuild.mjs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@ const watch = process.argv.includes("--watch");
44

55
/** @type {import('esbuild').BuildOptions} */
66
const options = {
7-
entryPoints: ["src/extension.ts"],
7+
entryPoints: {
8+
extension: "src/extension.ts",
9+
mossWorker: "src/worker/mossWorker.ts",
10+
},
811
bundle: true,
9-
outfile: "dist/extension.js",
12+
outdir: "dist",
1013
external: [
1114
"vscode",
1215
"@moss-dev/moss",

apps/moss-vscode/media/icon.svg

Lines changed: 51 additions & 4 deletions
Loading
3.13 KB
Loading
4.37 KB
Loading
4.54 KB
Loading

apps/moss-vscode/media/sidebar.css

Lines changed: 88 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
:root {
22
color-scheme: light dark;
3-
--moss-gap: 8px;
4-
--moss-radius: 4px;
3+
--moss-gap: 10px;
4+
--moss-radius: 6px;
5+
--moss-ink: #141915;
6+
--moss-paper: #f2f2f2;
7+
--moss-accent: var(--vscode-button-background, #141915);
8+
--moss-accent-fg: var(--vscode-button-foreground, #f2f2f2);
9+
--moss-border: var(--vscode-panel-border, rgba(128, 128, 128, 0.35));
510
}
611

712
* {
@@ -26,9 +31,49 @@ body {
2631
height: 100vh;
2732
}
2833

34+
.brand-header {
35+
display: flex;
36+
align-items: center;
37+
gap: 10px;
38+
padding-bottom: 4px;
39+
}
40+
41+
.brand-wordmark {
42+
display: block;
43+
height: 28px;
44+
width: auto;
45+
max-width: 140px;
46+
object-fit: contain;
47+
}
48+
49+
.brand-wordmark-light {
50+
display: none;
51+
}
52+
53+
.brand-wordmark-dark {
54+
display: block;
55+
}
56+
57+
body.vscode-dark .brand-wordmark-light,
58+
body.vscode-high-contrast .brand-wordmark-light {
59+
display: block;
60+
}
61+
62+
body.vscode-dark .brand-wordmark-dark,
63+
body.vscode-high-contrast .brand-wordmark-dark {
64+
display: none;
65+
}
66+
67+
.brand-tagline {
68+
margin: 0;
69+
font-size: 11px;
70+
opacity: 0.72;
71+
letter-spacing: 0.01em;
72+
}
73+
2974
.index-panel {
30-
padding: 10px;
31-
border: 1px solid var(--vscode-panel-border, rgba(128, 128, 128, 0.35));
75+
padding: 12px;
76+
border: 1px solid var(--moss-border);
3277
border-radius: var(--moss-radius);
3378
background: var(--vscode-editor-background);
3479
}
@@ -42,17 +87,24 @@ body {
4287

4388
.primary-btn {
4489
width: 100%;
45-
padding: 8px 12px;
46-
border: none;
90+
padding: 9px 12px;
91+
border: 1px solid transparent;
4792
border-radius: var(--moss-radius);
48-
background: var(--vscode-button-background);
49-
color: var(--vscode-button-foreground);
93+
background: var(--moss-accent);
94+
color: var(--moss-accent-fg);
5095
cursor: pointer;
5196
font: inherit;
97+
font-weight: 600;
98+
letter-spacing: 0.01em;
5299
}
53100

54101
.primary-btn:hover:not(:disabled) {
55-
background: var(--vscode-button-hoverBackground);
102+
background: var(--vscode-button-hoverBackground, #2a2f2b);
103+
}
104+
105+
.primary-btn:focus-visible {
106+
outline: 2px solid var(--vscode-focusBorder, #141915);
107+
outline-offset: 2px;
56108
}
57109

58110
.primary-btn:disabled {
@@ -72,7 +124,7 @@ body {
72124

73125
#query {
74126
flex: 1;
75-
padding: 6px 8px;
127+
padding: 8px 10px;
76128
border: 1px solid var(--vscode-input-border, transparent);
77129
border-radius: var(--moss-radius);
78130
background: var(--vscode-input-background);
@@ -82,12 +134,33 @@ body {
82134

83135
#query:focus {
84136
border-color: var(--vscode-focusBorder);
137+
box-shadow: 0 0 0 1px var(--vscode-focusBorder);
138+
}
139+
140+
.status-row {
141+
display: flex;
142+
align-items: center;
143+
gap: 8px;
144+
min-height: 1.2em;
145+
}
146+
147+
.status-avatar {
148+
width: 14px;
149+
height: 14px;
150+
border-radius: 3px;
151+
object-fit: cover;
152+
flex-shrink: 0;
153+
opacity: 0;
154+
transition: opacity 0.15s ease;
155+
}
156+
157+
.status-avatar.visible {
158+
opacity: 1;
85159
}
86160

87161
#status {
88162
font-size: 11px;
89163
opacity: 0.8;
90-
min-height: 1.2em;
91164
}
92165

93166
#results {
@@ -102,9 +175,9 @@ body {
102175
display: block;
103176
width: 100%;
104177
text-align: left;
105-
padding: 8px;
178+
padding: 8px 10px;
106179
margin-bottom: 6px;
107-
border: none;
180+
border: 1px solid transparent;
108181
border-radius: var(--moss-radius);
109182
background: var(--vscode-list-inactiveSelectionBackground, transparent);
110183
color: inherit;
@@ -113,6 +186,7 @@ body {
113186

114187
.result:hover {
115188
background: var(--vscode-list-hoverBackground);
189+
border-color: var(--moss-border);
116190
}
117191

118192
.result-header {
@@ -131,6 +205,7 @@ body {
131205
flex-shrink: 0;
132206
font-size: 11px;
133207
opacity: 0.75;
208+
font-variant-numeric: tabular-nums;
134209
}
135210

136211
.preview {

apps/moss-vscode/package.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"version": "0.1.0",
66
"publisher": "moss-dev",
77
"license": "BSD-2-Clause",
8+
"icon": "media/moss_avatar_core.png",
89
"engines": {
910
"vscode": "^1.85.0",
1011
"node": ">=20"
@@ -13,9 +14,6 @@
1314
"Other",
1415
"Machine Learning"
1516
],
16-
"activationEvents": [
17-
"onStartupFinished"
18-
],
1917
"main": "./dist/extension.js",
2018
"contributes": {
2119
"viewsContainers": {
@@ -52,6 +50,10 @@
5250
{
5351
"command": "moss.credentials.configure",
5452
"title": "Moss: Configure Credentials"
53+
},
54+
{
55+
"command": "moss.logs.show",
56+
"title": "Moss: Show Logs"
5557
}
5658
],
5759
"configuration": {

0 commit comments

Comments
 (0)