diff --git a/docs/source/_static/chat-ask-command.png b/docs/source/_static/chat-ask-command.png
new file mode 100644
index 000000000..48ee7dd89
Binary files /dev/null and b/docs/source/_static/chat-ask-command.png differ
diff --git a/docs/source/_static/chat-explain-code-output.png b/docs/source/_static/chat-explain-code-output.png
new file mode 100644
index 000000000..0a25252d0
Binary files /dev/null and b/docs/source/_static/chat-explain-code-output.png differ
diff --git a/docs/source/_static/chat-generate-command-response.png b/docs/source/_static/chat-generate-command-response.png
new file mode 100644
index 000000000..45ab63f34
Binary files /dev/null and b/docs/source/_static/chat-generate-command-response.png differ
diff --git a/docs/source/_static/chat-generate-file.png b/docs/source/_static/chat-generate-file.png
new file mode 100644
index 000000000..70d7796b2
Binary files /dev/null and b/docs/source/_static/chat-generate-file.png differ
diff --git a/docs/source/_static/chat-generate-input.png b/docs/source/_static/chat-generate-input.png
new file mode 100644
index 000000000..d9547512e
Binary files /dev/null and b/docs/source/_static/chat-generate-input.png differ
diff --git a/docs/source/_static/chat-generate-notebook-opened.png b/docs/source/_static/chat-generate-notebook-opened.png
new file mode 100644
index 000000000..fd0e0fb1e
Binary files /dev/null and b/docs/source/_static/chat-generate-notebook-opened.png differ
diff --git a/docs/source/_static/chat-hello-world.png b/docs/source/_static/chat-hello-world.png
new file mode 100644
index 000000000..033621cf0
Binary files /dev/null and b/docs/source/_static/chat-hello-world.png differ
diff --git a/docs/source/_static/chat-interface-blank.png b/docs/source/_static/chat-interface-blank.png
new file mode 100644
index 000000000..e696e4ab8
Binary files /dev/null and b/docs/source/_static/chat-interface-blank.png differ
diff --git a/docs/source/_static/chat-interface-selection.png b/docs/source/_static/chat-interface-selection.png
new file mode 100644
index 000000000..6dd943c62
Binary files /dev/null and b/docs/source/_static/chat-interface-selection.png differ
diff --git a/docs/source/_static/chat-learn-delete.png b/docs/source/_static/chat-learn-delete.png
new file mode 100644
index 000000000..0ec5a7462
Binary files /dev/null and b/docs/source/_static/chat-learn-delete.png differ
diff --git a/docs/source/_static/chat-learn-docs.png b/docs/source/_static/chat-learn-docs.png
new file mode 100644
index 000000000..74f5a70c5
Binary files /dev/null and b/docs/source/_static/chat-learn-docs.png differ
diff --git a/docs/source/_static/chat-replace-selection-input.png b/docs/source/_static/chat-replace-selection-input.png
new file mode 100644
index 000000000..7c1e1f859
Binary files /dev/null and b/docs/source/_static/chat-replace-selection-input.png differ
diff --git a/docs/source/_static/chat-replace-selection-output.png b/docs/source/_static/chat-replace-selection-output.png
new file mode 100644
index 000000000..af7073a63
Binary files /dev/null and b/docs/source/_static/chat-replace-selection-output.png differ
diff --git a/docs/source/users/index.md b/docs/source/users/index.md
index 2e12d0ce1..5adac39de 100644
--- a/docs/source/users/index.md
+++ b/docs/source/users/index.md
@@ -92,6 +92,116 @@ or
$ pip uninstall jupyter_ai_magics
+## The chat interface
+
+The easiest way to get started with Jupyter AI is to use the chat interface. The chat interface uses OpenAI's gpt-3.5-turbo model, the same model used by default in the ChatGPT web interface. To get started, you will need to set up an OpenAI account, obtain an API key, set the `OPENAI_API_KEY` environment variable to contain your key, and then start JupyterLab.
+
+:::{attention}
+:name: open-ai-privacy-cost
+The chat interface sends data to generative AI models hosted by third parties.
+Please be careful not to send confidential or sensitive data using the chat
+interface. In addition, please review your model provider's privacy policy and
+cost information to understand your payment obligations when using the
+chat interface.
+:::
+
+Once you have started JupyterLab, click the new "chat" icon in the side panel to open the chat interface.
+
+![Screen shot of the initial, blank, chat interface.](../_static/chat-interface-blank.png)
+
+To compose a message, type it in the text box at the bottom of the chat interface and press SHIFT+ENTER to send. You can press ENTER to add a new line. Once you have sent a message, you should see a response from Jupyter AI.
+
+![Screen shot of an example "Hello world" message sent to Jupyter AI, who responds with "Hello! Is there anything you would like to discuss or ask me?"](../_static/chat-hello-world.png)
+
+### Asking about something in your notebook
+
+Jupyter AI's chat interface can include a portion of your notebook in your prompt.
+
+:::{warning}
+:name: open-ai-selection-cost
+When you choose to include the selection with your message, this may increase the
+number of tokens in your request, which may cause your request to cost more money.
+Review your model provider's cost policy before making large requests.
+:::
+
+After highlighting a portion of your notebook, check "Include selection" in the chat panel, type your message, and press SHIFT+ENTER to send your message. Your outgoing message will include your selection.
+
+![Screen shot of JupyterLab with Jupyter AI's chat panel active. A Python function is selected, the user has "What does this code do?" as their prompt, and the user has chosen to include the selection with their message.](../_static/chat-interface-selection.png)
+
+Below your message, you will see Jupyter AI's response.
+
+![Screen shot of Jupyter AI's chat panel, showing an answer to the question asked above.](../_static/chat-explain-code-output.png)
+
+You can copy Jupyter AI's response to the clipboard so that you can paste it into your notebook, or into any other application. You can also choose to replace the selection with Jupyter AI's response by clicking "Replace selection" before you send your message.
+
+:::{warning}
+:name: replace-selection
+When you replace your selection, data is written immediately after Jupyter AI
+sends its response to your message. Review any generated code carefully before
+you run it.
+:::
+
+![Screen shot of Jupyter AI with a Python function selected, the user having typed "Rewrite this function to be iterative, not recursive" as their prompt, and with the user having chosen to include the selection with their message and to replace the selection with the response.](../_static/chat-replace-selection-input.png)
+
+After Jupyter AI sends a response, your notebook will be updated immediately with the response replacing the selection. You can also see the response in the chat panel.
+
+![Screen shot of Jupyter AI displaying a response in the chat panel and in the notebook.](../_static/chat-replace-selection-output.png)
+
+
+
+### Generating a new notebook
+
+You can use Jupyter AI to generate an entire notebook from a text prompt. To get started, open the chat panel, and send it a message starting with `/generate`.
+
+![Screen shot of a prompt reading "/generate A demonstration of how to use Matplotlib" in Jupyter AI](../_static/chat-generate-input.png)
+
+Generating a notebook can take a substantial amount of time, so Jupyter AI will respond to your message immediately while it works. You can continue to ask it other questions in the meantime.
+
+![Screen shot of Jupyter AI responding to a generate message with a message that it is working on a notebook.](../_static/chat-generate-command-response.png)
+
+:::{info}
+:name: generate-progress
+Especially if your prompt is detailed, it may take several minutes to generate
+your notebook. During this time, you can still use JupyterLab and Jupyter AI
+as you would normally. Do not shut your JupyterLab instance down while
+Jupyter AI is working.
+:::
+
+When Jupyter AI is done generating your notebook, it will send you another message with the filename that it generated.
+
+![Screen shot of Jupyter AI response indicating the file name that it wrote.](../_static/chat-generate-file.png)
+
+You can then open this file using the file browser.
+
+:::{warning}
+:name: generated-notebook
+Generated notebooks may contain errors and may have unintended side effects when
+you run the code contained in them. Please review all generated code carefully
+before you run it.
+:::
+
+![Screen shot of generated notebook built using Jupyter AI](../_static/chat-generate-notebook-opened.png)
+
+### Learning about local data
+
+Using the `/learn` command, you can teach Jupyter AI about local data so that it can include it when answering your questions. This data is **not** sent to remote AI model providers.
+
+To teach Jupyter AI about a folder full of documentation, for example, run `/learn docs/`. You will receive a response when Jupyter AI has indexed this documentation in a local vector database.
+
+![Screen shot of "/learn docs/" command and a response.](../_static/chat-learn-docs.png)
+
+You can then use `/ask` to ask a question specifically about the data that you taught Jupyter AI with `/learn`.
+
+![Screen shot of an "/ask" command and a response.](../_static/chat-ask-command.png)
+
+To clear the local vector database, you can run `/learn -d` and Jupyter AI will forget all information that it learned from your `/learn` commands.
+
+![Screen shot of a "/learn -d" command and a response.](../_static/chat-learn-delete.png)
+
+### Additional chat commands
+
+To clear the chat panel, use the `/clear` command. This does not reset the AI model; the model may still remember previous messages that you sent it, and it may use them to inform its responses.
+
## The `%%ai` magic command
The examples in this section are based on the [Jupyter AI example notebooks](https://github.com/jupyterlab/jupyter-ai/blob/main/examples/).