Common problems with copy-pasteable fixes. If your problem isn't listed, open an issue with the information requested in CONTRIBUTING.md.
After pip install notebook-intelligence, restart JupyterLab. If a restart doesn't help, verify both halves of the extension are enabled:
jupyter server extension list # look for "notebook_intelligence enabled"
jupyter labextension list # look for "@plmbr/notebook-intelligence ... enabled"If either is disabled or missing:
jupyter server extension enable notebook_intelligence
pip install --force-reinstall notebook-intelligence # if the labextension is missingThe chat sidebar appears as a left-rail icon in the JupyterLab UI. Click it to open the panel.
Seeing two NBI sidebar tabs with the same sparkle icon means two copies of the labextension are loaded at once. This happens after upgrading across the package rename: the labextension was renamed from @notebook-intelligence/notebook-intelligence to @plmbr/notebook-intelligence in the 5.0 line, and an upgrade installs the new one but can leave the old one behind. JupyterLab then loads both, and each registers its own sidebar tab.
Confirm it:
jupyter labextension listIf both @notebook-intelligence/notebook-intelligence and @plmbr/notebook-intelligence are listed as enabled, the first is the stale duplicate. Remove its directory (its path is shown in the list), checking both your environment prefix and the per-user location:
rm -rf <prefix>/share/jupyter/labextensions/@notebook-intelligence
rm -rf ~/.local/share/jupyter/labextensions/@notebook-intelligenceRestart JupyterLab and hard-refresh the browser; only @plmbr/notebook-intelligence should remain. If you would rather not delete files, jupyter labextension disable @notebook-intelligence/notebook-intelligence stops JupyterLab from loading the old extension reversibly. Note that pip uninstall does not remove the stale directory on its own, because the old labextension is no longer tracked by the current package.
NBI uses GitHub's device-flow login. The server extension prints the URL and one-time code to the JupyterLab terminal. Look there first.
If your browser blocks the popup, copy the URL from the terminal output and paste it into a new tab.
If the device-flow request itself fails (timeout, network error), check that your network allows outbound HTTPS to github.com and api.githubcopilot.com. See PRIVACY.md for the full egress list.
NBI started successfully but the configured provider returned an empty model list. Check, in order:
- Provider auth — open the NBI Settings dialog. For GitHub Copilot, sign in. For OpenAI-compatible or LiteLLM-compatible, paste an API key. For Ollama, ensure the daemon is running locally. For Claude mode, paste an Anthropic API key in the Claude tab.
- Custom Base URL — if you set one, confirm it points at the provider's chat-completions endpoint and that it's reachable from the JupyterLab process.
- Provider gating — if your admin disabled the provider via
disabled_providers, the dropdown won't list its models. Seeadmin-guide.md. - Model refresh — for Claude, click the refresh button in the Claude settings panel.
A 401 from the LLM provider almost always means an expired or invalid API key.
- GitHub Copilot — sign out and sign in again from NBI Settings → GitHub Copilot.
- OpenAI-compatible, LiteLLM-compatible, or Claude — paste a fresh key in NBI Settings under the respective provider.
- Stored Copilot token corrupted — delete
~/.jupyter/nbi/user-data.jsonand sign in again.
A 401 from a managed-skills manifest fetch means NBI_MANAGED_SKILLS_TOKEN is missing or expired. The reconciler logs the failure and leaves installed managed skills in place.
Claude mode requires the Claude Code CLI on the user's PATH. If the CLI is missing or fails to start, the chat sidebar hangs.
which claude # should print a path
claude --versionIf claude is installed in a non-default location, set the NBI_CLAUDE_CLI_PATH environment variable to its absolute path before starting JupyterLab.
If Claude mode worked previously but is now stuck, check the JupyterLab terminal for claude-agent-sdk errors. A failed-to-start agent thread is the usual culprit; restart JupyterLab to retry.
MCP stdio servers run as subprocesses of the user's Jupyter Server. If a server crashes at startup:
- Check the JupyterLab terminal for the server's stderr output.
- Verify the
commandandargsin~/.jupyter/nbi/mcp.jsonare correct and the binary is onPATH. - For
npx -yservers, confirm Node.js is installed (node --version). - Use the Reload MCP servers action from NBI Settings → MCP after fixing the config — this re-runs discovery without restarting JupyterLab.
If the LLM is connected but tools aren't being called, confirm the model supports tool calling. All GitHub Copilot models do; for other providers, check the provider's docs.
NBI does not have a separate log file. Server-side messages go to stderr of the JupyterLab process — the terminal where you ran jupyter lab.
To see more detail:
jupyter lab --debugFrontend errors go to the browser DevTools console (Cmd+Option+I on macOS, Ctrl+Shift+I on Linux or Windows). Look for messages from notebook-intelligence.
For configuration inspection:
cat ~/.jupyter/nbi/config.json
cat ~/.jupyter/nbi/mcp.json
ls ~/.jupyter/nbi/rules/ # ruleset files
ls ~/.claude/skills/ # Claude skills
ls ~/.claude/projects/ # Claude session transcriptsIf CLAUDE_CONFIG_DIR is set, the Claude CLI keeps its skills and session transcripts under $CLAUDE_CONFIG_DIR instead of ~/.claude, and NBI reads from the same place.
Do not share the contents of
~/.jupyter/nbi/config.jsonor~/.jupyter/nbi/user-data.json— they contain API keys or your encrypted GitHub token.
NBI reloads the Claude SDK session whenever a skill changes on disk. If a script or editor frequently rewrites files under ~/.claude/skills/ (autoformatter, sync tool), it triggers the banner. Pause the writer or move the skill out of ~/.claude/skills/ while editing.
The agent's shell-execute tools (execute_command and the embedded terminal) automatically redact values for env vars whose name matches sensitive substrings (TOKEN, SECRET, API_KEY, PASSWORD, OAUTH, BEARER, COOKIE, JWT, ACCESS_KEY, …) plus tokens with well-known credential prefixes (ghp_, sk-ant-, xoxb-, AKIA, …). This prevents a verbose command like env, printenv, or git with credential-helper tracing from pasting your GITHUB_TOKEN / ANTHROPIC_API_KEY into chat history.
If you're debugging a credential helper and need the raw value, set NBI_DISABLE_OUTPUT_SCRUB=1 in the JupyterLab process env and restart. Keep it off in normal use; the redaction is the only line of defense between an LLM-driven command and your secrets going to the model provider.
Tune the debounce delay in NBI Settings → Inline completion. Lower delays mean more requests, which means higher cost on paid providers. The default balances responsiveness against cost.
- Check GitHub issues for similar reports.
- Open a new issue including the information listed in CONTRIBUTING.md.