{"_id":"@dong-victor/dsh-better-sidebar-jupyter","_rev":"6-a2024ae9e093c943ec9bc28c2bb0be2b","name":"@dong-victor/dsh-better-sidebar-jupyter","dist-tags":{"latest":"0.2.4"},"versions":{"0.1.0":{"name":"@dong-victor/dsh-better-sidebar-jupyter","version":"0.1.0","keywords":["dsh","deepseek-harness","plugin","dsh-better-sidebar","jupyter","ipynb","notebook"],"license":"MIT","_id":"@dong-victor/dsh-better-sidebar-jupyter@0.1.0","maintainers":[{"name":"dong-victor","email":"dougzforever@gmail.com"}],"dsh":{"bundle":{"patch":"./cordis.patch.yml"},"client":{"inject":["@deepseek-ai/dsh-client-runtime"],"platform":"web"}},"dist":{"shasum":"aa4b46992fbb970392e915b1ae0f541657b98495","tarball":"https://registry.npmjs.org/@dong-victor/dsh-better-sidebar-jupyter/-/dsh-better-sidebar-jupyter-0.1.0.tgz","fileCount":8,"integrity":"sha512-1hynPfH5LElz4kjzSay92ZaJTLguGZl8imSxp0fDWYITw9c/LzJWv+b6BRqrlbj3NbTck+nDE06jWrXTq79B6A==","signatures":[{"sig":"MEYCIQD/ceOxjnDjo/Ai1E7P6Vk2sNjLe2AJt1X+dYY//O+45gIhAKrcp76fqWfwFkeMOnfXtHLaLLGbhevktliIukunjq3I","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":283097},"main":"lib/index.js","type":"module","engines":{"node":"^22.19.0 || >=24.0.0"},"exports":{".":"./lib/index.js","./client":{"default":"./lib/client.js"},"./package.json":"./package.json","./python/bridge.py":"./python/bridge.py"},"gitHead":"62eb4e6c166788de95bb175c2946d6ac4c2eccfe","scripts":{"test":"vitest run","build":"tsc --noEmit && tsdown","typecheck":"tsc --noEmit"},"_npmUser":{"name":"dong-victor","email":"dougzforever@gmail.com"},"_npmVersion":"11.12.1","description":"Jupyter notebook support for the dsh-better-sidebar editor: .ipynb opens inline as a runnable notebook viewer with Python syntax highlighting, a lazy-start Python kernel (jupyter_client + ipykernel via python/bridge.py), streaming outputs and save-back. R","directories":{},"_nodeVersion":"24.15.0","dependencies":{"ws":"^8.18.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"react":"^18.2.0","tsdown":"^0.22.2","vitest":"^4.1.8","@types/ws":"^8.5.10","react-dom":"^18.2.0","typescript":"^5.6.0","@types/node":"^24.0.0","@types/react":"~18.3.1","@types/react-dom":"~18.3.1","dsh-better-sidebar":"workspace:*","@deepseek-ai/cordis":"^4.0.1","@deepseek-ai/dsh-session":"^0.1.0-rc.6","@deepseek-ai/dsh-host-webserver":"^0.1.0-rc.6"},"peerDependencies":{"react":"^18.2.0","cordis":"^4.0.0-rc.7","react-dom":"^18.2.0","dsh-better-sidebar":"^0.13.0","@deepseek-ai/dsh-session":"^0.1.0-rc.6","@deepseek-ai/dsh-host-webserver":"^0.1.0-rc.6"},"peerDependenciesMeta":{"dsh-better-sidebar":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/dsh-better-sidebar-jupyter_0.1.0_1786860735577_0.01698827843817763","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@dong-victor/dsh-better-sidebar-jupyter","version":"0.2.0","keywords":["dsh","deepseek-harness","plugin","dsh-better-sidebar","jupyter","ipynb","notebook"],"license":"MIT","_id":"@dong-victor/dsh-better-sidebar-jupyter@0.2.0","maintainers":[{"name":"dong-victor","email":"dougzforever@gmail.com"}],"dsh":{"bundle":{"patch":"./cordis.patch.yml"},"client":{"inject":["@deepseek-ai/dsh-client-runtime"],"platform":"web"}},"dist":{"shasum":"299a4f9e186a29a03ab4c4b6910d82459a04e04c","tarball":"https://registry.npmjs.org/@dong-victor/dsh-better-sidebar-jupyter/-/dsh-better-sidebar-jupyter-0.2.0.tgz","fileCount":8,"integrity":"sha512-C1DkSNz8TvsvabrOxxNamCMqqr3Kjieox2aYwFXMUgYnwuKg6P5TSkXU14oh1GJ6zkCTpHpLJ2EnAfOiB6yH8w==","signatures":[{"sig":"MEYCIQC5+7OPM7VuwAN+my6aVtZWf2PG7ZmgqqeOJuM7hCQ5hAIhAK/4LLR3Z7XoKXkX+icQQUTClrUeHcUU7UFwpSiIVnDD","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":369607},"main":"lib/index.js","type":"module","engines":{"node":"^22.19.0 || >=24.0.0"},"exports":{".":"./lib/index.js","./client":{"default":"./lib/client.js"},"./package.json":"./package.json","./python/bridge.py":"./python/bridge.py"},"gitHead":"62eb4e6c166788de95bb175c2946d6ac4c2eccfe","scripts":{"test":"vitest run","build":"tsc --noEmit && tsdown","typecheck":"tsc --noEmit"},"_npmUser":{"name":"dong-victor","email":"dougzforever@gmail.com"},"_npmVersion":"11.12.1","description":"Jupyter notebook support for the dsh-better-sidebar editor: .ipynb opens inline as a runnable notebook viewer with IDEA/PyCharm-style run mode (Ctrl+Enter / Shift+Enter / run-all shortcuts, IDEA toolbar, gutter run icons, In/Out labels, execution duration","directories":{},"_nodeVersion":"24.15.0","dependencies":{"ws":"^8.18.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"react":"^18.2.0","tsdown":"^0.22.2","vitest":"^4.1.8","@types/ws":"^8.5.10","react-dom":"^18.2.0","typescript":"^5.6.0","@types/node":"^24.0.0","@types/react":"~18.3.1","@types/react-dom":"~18.3.1","dsh-better-sidebar":"workspace:*","@deepseek-ai/cordis":"^4.0.1","@deepseek-ai/dsh-session":"^0.1.0-rc.6","@deepseek-ai/dsh-host-webserver":"^0.1.0-rc.6"},"peerDependencies":{"react":"^18.2.0","cordis":"^4.0.0-rc.7","react-dom":"^18.2.0","dsh-better-sidebar":"^0.13.0","@deepseek-ai/dsh-session":"^0.1.0-rc.6","@deepseek-ai/dsh-host-webserver":"^0.1.0-rc.6"},"peerDependenciesMeta":{"dsh-better-sidebar":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/dsh-better-sidebar-jupyter_0.2.0_1786892944489_0.5561470532130104","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@dong-victor/dsh-better-sidebar-jupyter","version":"0.2.1","keywords":["dsh","deepseek-harness","plugin","dsh-better-sidebar","jupyter","ipynb","notebook"],"license":"MIT","_id":"@dong-victor/dsh-better-sidebar-jupyter@0.2.1","maintainers":[{"name":"dong-victor","email":"dougzforever@gmail.com"}],"dsh":{"bundle":{"patch":"./cordis.patch.yml"},"client":{"inject":["@deepseek-ai/dsh-client-runtime"],"platform":"web"}},"dist":{"shasum":"6257b1815c7c5204ab3d96d7db28798acef5c4b3","tarball":"https://registry.npmjs.org/@dong-victor/dsh-better-sidebar-jupyter/-/dsh-better-sidebar-jupyter-0.2.1.tgz","fileCount":8,"integrity":"sha512-O3uHpaw6ndwzyuqoEUy9lbVe65oWdTn4cxl99KW+q1VsMYIaGfeKoX5WNyqvQCjmrjT9WvKXaw7z6JHpwMEFPw==","signatures":[{"sig":"MEQCICJjE9vnEOmHUkDvByN4JXsR6C6UmkkFf0YUqadNEKGYAiBoB5SaRoaRFUkfKX9VrnTHFW8SQQdpivY3SrvtcEuvYw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":376203},"main":"lib/index.js","type":"module","engines":{"node":"^22.19.0 || >=24.0.0"},"exports":{".":"./lib/index.js","./client":{"default":"./lib/client.js"},"./package.json":"./package.json","./python/bridge.py":"./python/bridge.py"},"gitHead":"e4441ea73bed94631741b2fc33330facc38fbb8b","scripts":{"test":"vitest run","build":"tsc --noEmit && tsdown","typecheck":"tsc --noEmit"},"_npmUser":{"name":"dong-victor","email":"dougzforever@gmail.com"},"_npmVersion":"11.12.1","description":"Jupyter notebook support for the dsh-better-sidebar editor: .ipynb opens inline as a runnable notebook viewer with IDEA/PyCharm-style run mode (Ctrl+Enter / Shift+Enter / run-all shortcuts, IDEA toolbar, gutter run icons, In/Out labels, execution duration","directories":{},"_nodeVersion":"24.15.0","dependencies":{"ws":"^8.18.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"react":"^18.2.0","tsdown":"^0.22.2","vitest":"^4.1.8","@types/ws":"^8.5.10","react-dom":"^18.2.0","typescript":"^5.6.0","@types/node":"^24.0.0","@types/react":"~18.3.1","@types/react-dom":"~18.3.1","dsh-better-sidebar":"workspace:*","@deepseek-ai/cordis":"^4.0.1","@deepseek-ai/dsh-session":"^0.1.0-rc.6","@deepseek-ai/dsh-host-webserver":"^0.1.0-rc.6"},"peerDependencies":{"react":"^18.2.0","cordis":"^4.0.0-rc.7","react-dom":"^18.2.0","dsh-better-sidebar":"^0.13.0","@deepseek-ai/dsh-session":"^0.1.0-rc.6","@deepseek-ai/dsh-host-webserver":"^0.1.0-rc.6"},"peerDependenciesMeta":{"dsh-better-sidebar":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/dsh-better-sidebar-jupyter_0.2.1_1786894645559_0.7834131762371528","host":"s3://npm-registry-packages-npm-production"}},"0.2.2":{"name":"@dong-victor/dsh-better-sidebar-jupyter","version":"0.2.2","keywords":["dsh","deepseek-harness","plugin","dsh-better-sidebar","jupyter","ipynb","notebook"],"license":"MIT","_id":"@dong-victor/dsh-better-sidebar-jupyter@0.2.2","maintainers":[{"name":"dong-victor","email":"dougzforever@gmail.com"}],"dsh":{"bundle":{"patch":"./cordis.patch.yml"},"client":{"inject":["@deepseek-ai/dsh-client-runtime"],"platform":"web"}},"dist":{"shasum":"a640b2f01e919249a7b4a5d53a2eae1e7b7ba592","tarball":"https://registry.npmjs.org/@dong-victor/dsh-better-sidebar-jupyter/-/dsh-better-sidebar-jupyter-0.2.2.tgz","fileCount":8,"integrity":"sha512-GfYA3k8Fl3znuAWH80aZy8476OPC7vserUCySSgV3XGS4KNMEdDbP+llULDqqNp/8HLXRAbq5Ea0rZLx52W2MA==","signatures":[{"sig":"MEUCIQD/cMwdMLUyTEjcICrHQ8Kxm48bfiDNtHwUZTityOSp4wIgfuUcgsfqmPTNiodtPVhXz1qSg/b1pHRK2NFjhEyuHgM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":382561},"main":"lib/index.js","type":"module","engines":{"node":"^22.19.0 || >=24.0.0"},"exports":{".":"./lib/index.js","./client":{"default":"./lib/client.js"},"./package.json":"./package.json","./python/bridge.py":"./python/bridge.py"},"gitHead":"59067de8e2d800cce040a901eda0529d921c1c25","scripts":{"test":"vitest run","build":"tsc --noEmit && tsdown","typecheck":"tsc --noEmit"},"_npmUser":{"name":"dong-victor","email":"dougzforever@gmail.com"},"_npmVersion":"11.12.1","description":"Jupyter notebook support for the dsh-better-sidebar editor: .ipynb opens inline as a runnable notebook viewer with IDEA/PyCharm-style run mode (Ctrl+Enter / Shift+Enter / run-all shortcuts, IDEA toolbar, gutter run icons, In/Out labels, execution duration","directories":{},"_nodeVersion":"24.15.0","dependencies":{"ws":"^8.18.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"react":"^18.2.0","tsdown":"^0.22.2","vitest":"^4.1.8","@types/ws":"^8.5.10","react-dom":"^18.2.0","typescript":"^5.6.0","@types/node":"^24.0.0","@types/react":"~18.3.1","@types/react-dom":"~18.3.1","dsh-better-sidebar":"workspace:*","@deepseek-ai/cordis":"^4.0.1","@deepseek-ai/dsh-session":"^0.1.0-rc.6","@deepseek-ai/dsh-host-webserver":"^0.1.0-rc.6"},"peerDependencies":{"react":"^18.2.0","cordis":"^4.0.0-rc.7","react-dom":"^18.2.0","dsh-better-sidebar":"^0.13.0","@deepseek-ai/dsh-session":"^0.1.0-rc.6","@deepseek-ai/dsh-host-webserver":"^0.1.0-rc.6"},"peerDependenciesMeta":{"dsh-better-sidebar":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/dsh-better-sidebar-jupyter_0.2.2_1786931249393_0.43737913844153997","host":"s3://npm-registry-packages-npm-production"}},"0.2.3":{"name":"@dong-victor/dsh-better-sidebar-jupyter","version":"0.2.3","keywords":["dsh","deepseek-harness","plugin","dsh-better-sidebar","jupyter","ipynb","notebook"],"license":"MIT","_id":"@dong-victor/dsh-better-sidebar-jupyter@0.2.3","maintainers":[{"name":"dong-victor","email":"dougzforever@gmail.com"}],"dsh":{"bundle":{"patch":"./cordis.patch.yml"},"client":{"inject":["@deepseek-ai/dsh-client-runtime"],"platform":"web"}},"dist":{"shasum":"f7c06dede9cc75d9e3831bd1687fed079cae2c45","tarball":"https://registry.npmjs.org/@dong-victor/dsh-better-sidebar-jupyter/-/dsh-better-sidebar-jupyter-0.2.3.tgz","fileCount":8,"integrity":"sha512-/GtdBmT+r9MFSvVpGC09vu5mkXlokkELxQS0NtPq0hjLvKnkllBr9O2yf59gEUwlzdkbkdtIUWUWO1OIEa6B2A==","signatures":[{"sig":"MEUCIASMQU0uMA9x3BFO3Vc1vfk57d0GRkK869rQdp4Q/8khAiEAw+TDR7F/xCFqUgvZzEh0/9r1fSy5BBjomv+GXf9lyzc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":403605},"main":"lib/index.js","type":"module","engines":{"node":"^22.19.0 || >=24.0.0"},"exports":{".":"./lib/index.js","./client":{"default":"./lib/client.js"},"./package.json":"./package.json","./python/bridge.py":"./python/bridge.py"},"gitHead":"e81756030b4b60a57db3720c9b0daba4d272e00c","scripts":{"test":"vitest run","build":"tsc --noEmit && tsdown","typecheck":"tsc --noEmit"},"_npmUser":{"name":"dong-victor","email":"dougzforever@gmail.com"},"_npmVersion":"11.12.1","description":"Jupyter notebook support for the dsh-better-sidebar editor: .ipynb opens inline as a runnable notebook viewer with IDEA/PyCharm-style run mode (Ctrl+Enter / Shift+Enter / run-all shortcuts, IDEA toolbar, gutter run icons, In/Out labels, execution duration","directories":{},"_nodeVersion":"24.15.0","dependencies":{"ws":"^8.18.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"react":"^18.2.0","tsdown":"^0.22.2","vitest":"^4.1.8","@types/ws":"^8.5.10","react-dom":"^18.2.0","typescript":"^5.6.0","@types/node":"^24.0.0","@types/react":"~18.3.1","@types/react-dom":"~18.3.1","dsh-better-sidebar":"workspace:*","@deepseek-ai/cordis":"^4.0.1","@deepseek-ai/dsh-session":"^0.1.0-rc.6","@deepseek-ai/dsh-host-webserver":"^0.1.0-rc.6"},"peerDependencies":{"react":"^18.2.0","cordis":"^4.0.0-rc.7","react-dom":"^18.2.0","dsh-better-sidebar":"^0.13.0","@deepseek-ai/dsh-session":"^0.1.0-rc.6","@deepseek-ai/dsh-host-webserver":"^0.1.0-rc.6"},"peerDependenciesMeta":{"dsh-better-sidebar":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/dsh-better-sidebar-jupyter_0.2.3_1787157083108_0.232676825542238","host":"s3://npm-registry-packages-npm-production"}},"0.2.4":{"name":"@dong-victor/dsh-better-sidebar-jupyter","version":"0.2.4","description":"Jupyter notebook support for the dsh-better-sidebar editor: .ipynb opens inline as a runnable notebook viewer with IDEA/PyCharm-style run mode (Ctrl+Enter / Shift+Enter / run-all shortcuts, IDEA toolbar, gutter run icons, In/Out labels, execution duration","type":"module","engines":{"node":"^22.19.0 || >=24.0.0"},"main":"lib/index.js","exports":{".":"./lib/index.js","./client":{"default":"./lib/client.js"},"./python/bridge.py":"./python/bridge.py","./package.json":"./package.json"},"dsh":{"bundle":{"patch":"./cordis.patch.yml"},"client":{"inject":["@deepseek-ai/dsh-client-runtime"],"platform":"web"}},"dependencies":{"ws":"^8.18.0"},"peerDependencies":{"@deepseek-ai/dsh-host-webserver":"^0.1.0-rc.6","@deepseek-ai/dsh-session":"^0.1.0-rc.6","cordis":"^4.0.0-rc.7","dsh-better-sidebar":"^0.13.0","react":"^18.2.0","react-dom":"^18.2.0"},"peerDependenciesMeta":{"dsh-better-sidebar":{"optional":true}},"devDependencies":{"@deepseek-ai/cordis":"^4.0.1","@deepseek-ai/dsh-host-webserver":"^0.1.0-rc.6","@deepseek-ai/dsh-session":"^0.1.0-rc.6","@types/node":"^24.0.0","@types/react":"~18.3.1","@types/react-dom":"~18.3.1","@types/ws":"^8.5.10","dsh-better-sidebar":"workspace:*","react":"^18.2.0","react-dom":"^18.2.0","tsdown":"^0.22.2","typescript":"^5.6.0","vitest":"^4.1.8"},"scripts":{"build":"tsc --noEmit && tsdown","typecheck":"tsc --noEmit","test":"vitest run"},"keywords":["dsh","deepseek-harness","plugin","dsh-better-sidebar","jupyter","ipynb","notebook"],"publishConfig":{"access":"public"},"license":"MIT","gitHead":"e1cbe6be4187d6050fdcbeee95cc806d467961c2","_id":"@dong-victor/dsh-better-sidebar-jupyter@0.2.4","_nodeVersion":"24.15.0","_npmVersion":"11.12.1","dist":{"integrity":"sha512-KZmNQQcZdEgMR/Mq6idYut5mFc74Tx+UuzD3xWop2izSm0kzEimHFe0tcLyoD8+217WEFN0hvuClH2B3OLXcWg==","shasum":"1b37c93111af12e2b48d0493a73ee89f3e84e87d","tarball":"https://registry.npmjs.org/@dong-victor/dsh-better-sidebar-jupyter/-/dsh-better-sidebar-jupyter-0.2.4.tgz","fileCount":8,"unpackedSize":401897,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDSL3aj9jx0YCyOr0n3BLukYQnWmlQAHHmfT7GjbmeAagIgRI/7ow7wMFzFb957OWTCyqDN+m/XDURw1PdQtObCC4I="}]},"_npmUser":{"name":"dong-victor","email":"dougzforever@gmail.com"},"directories":{},"maintainers":[{"name":"dong-victor","email":"dougzforever@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/dsh-better-sidebar-jupyter_0.2.4_1787157489531_0.6597114913647157"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-16T06:12:15.380Z","modified":"2026-08-19T16:38:09.867Z","0.1.0":"2026-08-16T06:12:15.725Z","0.2.0":"2026-08-16T15:09:04.641Z","0.2.1":"2026-08-16T15:37:25.737Z","0.2.2":"2026-08-17T01:47:29.537Z","0.2.3":"2026-08-19T16:31:23.275Z","0.2.4":"2026-08-19T16:38:09.699Z"},"license":"MIT","keywords":["dsh","deepseek-harness","plugin","dsh-better-sidebar","jupyter","ipynb","notebook"],"description":"Jupyter notebook support for the dsh-better-sidebar editor: .ipynb opens inline as a runnable notebook viewer with IDEA/PyCharm-style run mode (Ctrl+Enter / Shift+Enter / run-all shortcuts, IDEA toolbar, gutter run icons, In/Out labels, execution duration","maintainers":[{"name":"dong-victor","email":"dougzforever@gmail.com"}],"readme":"# dsh-better-sidebar-jupyter\r\n\r\nJupyter notebook support for [dsh-better-sidebar](https://github.com/omdsh-dev/DSH-better-sidebar):\r\n`.ipynb` files open **inline in the sidebar editor** as a runnable notebook view —\r\nPython syntax highlighting, cell execution through a lazy-start Python kernel\r\n(`jupyter_client` + `ipykernel` via `python/bridge.py`), streaming outputs, and\r\nsave-back.\r\n\r\nMerged from the Jupyter support of `@dong-victor/dsh-explorer`, adapted to the\r\nbetter-sidebar plugin architecture: the viewer registers through the\r\n`ctx.betterSidebar.registerFileViewer` service, and every route is\r\n**session-scoped** — the notebook must live inside the conversation's working\r\ndirectory.\r\n\r\n## Requirements\r\n\r\n- dsh-better-sidebar ≥ 0.13.0 (the `registerFileViewer` service)\r\n- Python with `jupyter_client` and `ipykernel` for cell execution:\r\n  `pip install jupyter_client ipykernel`\r\n\r\n## Install\r\n\r\n```sh\r\ncd ~/.dsh && dsh plugin --profile web add @dong-victor/dsh-better-sidebar-jupyter\r\n```\r\n\r\n(or add it from the Side card settings → 文件预览 → “添加预览插件”.)\r\n\r\n## What you get\r\n\r\n- `.ipynb` opens in the sidebar editor (single-click in the explorer / any\r\n  open-path flow), rendered by the inline notebook viewer.\r\n- **IDEA/PyCharm-style run mode** — shortcuts and toolbar mirror IntelliJ's\r\n  Jupyter support (Windows keymap):\r\n  - `Ctrl+Enter` — run the current cell (stays in the cell for editing).\r\n  - `Shift+Enter` — run the current cell **and select the cell below**; when\r\n    there is no cell below, a new one is created (IDEA behavior).\r\n  - `Ctrl+Alt+Shift+Enter` — run all code cells.\r\n  - `Ctrl+F2` — interrupt the running kernel.\r\n  - `Ctrl+Home` / `Ctrl+End` — move the caret to the start/end of the current\r\n    cell; outside an editor, focus the first/last cell of the notebook.\r\n  - `Ctrl/Cmd+S` — save.\r\n- **IDEA toolbar**: ▶ Run cell and select below · ▶▶ Run all · ■ Interrupt ·\r\n  ↻ Restart · ⏻ Shutdown · 🧹 Clear all outputs · ＋ Add cell below · ↑/↓ Move\r\n  cell · cell-type selector (Code/Markdown/Raw) · ⇡/⇣ select above/below ·\r\n  kernel status widget (state + kernel name) · save.\r\n- **Per-cell IDEA affordances**: green ▶ gutter run button on every code cell\r\n  (hover/selected), `In [n]` execution counter, `Out[n]` on results, and the\r\n  **execution duration in the cell's lower-left corner** (hover shows the\r\n  completion date/time). Error outputs render as **collapsible tracebacks**\r\n  (IDEA-style summary row + expand toggle).\r\n- Lazy kernel: the Python bridge starts on the first run — no startup cost for\r\n  plain browsing. Kernels keep running in the background while the editor is\r\n  closed, and finished executions are written back into the `.ipynb` file\r\n  (run-all survives tab switches / session switches / reconnects). Reopening a\r\n  notebook — or coming back after switching sessions — **re-syncs the whole\r\n  batch**: the executing cell shows as running with its latest partial output,\r\n  and the queued tail of a run-all batch shows as queued.\r\n- **Explorer indicator**: notebooks whose kernel is alive get a **green dot**\r\n  next to their file name in the sidebar file browser (pulsing while a cell\r\n  executes), so a background run is visible even with the notebook closed.\r\n- Syntax highlighting follows the app theme (IDEA/Darcula-style Python\r\n  highlighting, `--dsw-*` tokens).\r\n\r\n## Architecture\r\n\r\n- `src/index.ts` (host half): mounts the fenced routes\r\n  `/api/dsh-better-sidebar-jupyter/*` (env / notebook GET+PUT / kernel\r\n  lifecycle) and the kernel WebSocket upgrade, with one `KernelManager` per\r\n  notebook path. Every request carries `sessionId` (+ optional `cwd`) and a\r\n  `path`; `src/host/gate.ts` requires the canonical path to live inside the\r\n  session's authoritative working directory.\r\n- `python/bridge.py`: a JSON-lines RPC shim that owns the real Jupyter kernel\r\n  (all ZeroMQ handling stays in Python — no native ZMQ bindings in Node).\r\n- `src/client/` (client half): the `.ipynb` file viewer (`NotebookView`) wraps\r\n  the notebook editor UI (`EditorView` + cells + outputs), talking to the host\r\n  through a session-scoped `JupyterApi`.\r\n\r\n## Security\r\n\r\nAll routes pass the same browser-trust fence as the DSH `/api` gateway\r\n(Host-header loopback or `trustedHosts`), and notebook paths are gated to the\r\nsession's cwd — a cross-site page cannot reach the kernel or read/write files\r\noutside the conversation's directory.\r\n\r\n## License\r\n\r\nMIT\r\n","readmeFilename":"README.md"}