I work at a university and handle data--such as student grades--that institutional policy prohibits from being sent to cloud-based LLMs. However, the built-in Notebook Assistant automatically sends notebook data to cloud LLMs without distinction.
To address this, I prototyped a framework that assigns privacy levels to notebook data, separating what must remain confidential from what can safely be sent to the cloud, and processes them accordingly via Claude Code. Or rather, I had Claude Code build it for me.
The goal is to route confidential data to a local LLM (via LM Studio) while letting Claude Code handle everything else. I have only been developing and testing on Windows, and since the package invokes the Claude Code CLI directly, modifications will almost certainly be required for macOS and Linux environments.

Installation

Prerequisites

Claude Code CLI -- Download and install from the official site.
(*Verifyinstallation*)​​ClaudeCommand["--version"]
Node.js -- Download and install the latest LTS version from the official Node.js site.
Running the
claude
command in your terminal will launch an interactive login flow--just follow the on-screen instructions to complete authentication.

Setting Up in Mathematica

After launching Mathematica, define
$packageDirectory
as your preferred directory and add it to the path:
$packageDirectory="...";​​AppendTo[\$Path,$packageDirectory];
Then download the files and folders from the following repositories and place them in
$packageDirectory
:
https://github.com/transreal/claudecode
https://github.com/transreal/NBAccess
Load the package with:
$CharacterEncoding="UTF-8";​​<<claudecode.wl

Basic Usage

The two main entry points are:
ClaudeQuery
-- primarily for obtaining results as values (default:
AutoEvaluate -> False
)
​
ClaudeEval
-- primarily for generating and executing expressions (default:
AutoEvaluate -> True
)
You can ask questions freely, and the system will generally give you reasonable answers:
ClaudeQuery["How do I use claudecode?"]​​​​ClaudeQuery["How do I configure data confidentiality settings?"]
A helper palette called "Claude Code" is also installed automatically for convenient access to common operations.
Below is a simple execution example.
Cells designated as Confidential or marked with Mark (as confidential) from the palette are kept secret. Secret cells have a red background. Cells computed using secret cells are treated as variables with secret dependencies and are set to an orange background.
Running NBPlotDependencyGraph[EvaluationNotebook[nb]] plots the dependency graph for that notebook. Running NBPlotDependencyGraph[] without arguments plots a dependency graph spanning all notebooks.
When you run ClaudeQuery or ClaudeEval, information from secret cells or cells that depend on secret variables cannot be referenced. However, since it would be difficult to perform computations with no information at all, the LLM can reference only metadata such as the data type, data size, and list of key values. You can use ClaudeEval to have the LLM assemble computation expressions, then execute the calculations without sending the secret data flow to the LLM.
In[]:=
ClaudeEval["Import srcores.xlsx as a confiential variable scores."]
The file in NotebookDirectory is scores.xlsx (likely a typo for "srcores"). Here's the import as a confidential variable with column keys displayed:

In[]:=
scores=Confidential[First@Import[FileNameJoin[{Quiet@Check[NotebookDirectory[],$packageDirectory],"scores.xlsx"}],{"Dataset"}]]​​​​NonConfidentialRow"scoresのキー: ",Normal[Keys[scores[[1]]]]," "

Out[]=
student
Midterm Exam
Final Exam
student1
78.0
70.0
student2
55.0
60.0
student3
90.0
80.0
student4
85.0
88.0
student5
62.0
59.0
student6
30.0
40.0
student7
95.0
90.0
student8
70.0
73.0
student9
60.0
65.0
student10
75.0
75.0

 Cells declared with Confidential[] cannot be declassified.

Out[]=
scoresのキー: {student,Midterm Exam,Final Exam}
Done. Check the code output, then use
ContinueEval
to continue.
In[]:=
ClaudeQuery["What is the first line of the scores?"]
Since `scores` is confidential, I'll extract and display its first row:
NonConfidential[scores[1]]
In[]:=
ClaudeEval["Caluculate the meand and the standard deviation of the 'Midterm Exam' and 'Final Exam', respectively."]
Since scores is confidential, the result will automatically be marked as confidential-dependent.
In[]:=
Module[{mid,fin},​​mid=Normal[scores[All,"Midterm Exam"]];​​fin=Normal[scores[All,"Final Exam"]];​​Grid[{​​{"","Mean","Standard Deviation"},​​{"Midterm Exam",N[Mean[mid]],N[StandardDeviation[mid]]},​​{"Final Exam",N[Mean[fin]],N[StandardDeviation[fin]]}​​},Frame->All,Alignment->Center,Spacings->{2,1}]​​]

Out[]=
Mean
Standard Deviation
Midterm Exam
70.
19.2296
Final Exam
70.
14.922
Done. Check the code output, then use
ContinueEval
to continue.
In[]:=
ClaudeQuery["What is the value of scores and Out[23]?"]
Both `scores` and `Out[23]` are marked as confidential in your notebook, so their actual values are hidden from me.
Here is what I can see from the metadata:
◼
  • scores (`Out[19]`): A confidential `Association` with 210 keys, including: `InitialData`, `student`, `Midterm Exam`, `Final Exam`, `FontColor`, `ImageSize`, `ImageMargins`, `Background`, `Alignment`, `ItemSize`
  • ◼
  • Out[23]: Confidential-dependent data (462 characters) — this is the Grid table showing the mean and standard deviation of the Midterm Exam and Final Exam columns, computed in Step 2.
  • Since these were wrapped with `Confidential`, their contents are intentionally excluded from the context sent to me. If you'd like me to see the values, you can either:
    ◼
  • Re-import the data without the `Confidential` wrapper
  • ◼
  • Use `NonConfidential[...]` to explicitly reveal specific parts
  • This confidentiality mechanism is working as designed — it protects sensitive student data from being sent outside the notebook.

    CITE THIS NOTEBOOK

    Privacy-aware LLM integration for Wolfram​
    by Katsunobu Imai​
    Wolfram Community, STAFF PICKS, March 26, 2026
    ​https://community.wolfram.com/groups/-/m/t/3670605