PageSourceSearch

https://joplinapp.org/assets/js/112fd495.8c0a9471.js

js joplinapp.org collected 2026-09-24 08:44:32 UTC 14,105 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunk_joplin_doc_builder=self.webpackChunk_joplin_doc_builder||[]).push([[3794],{3905:function(e,t,n){n.d(t,{Zo:function(){return u},kt:function(){return m}});var a=n(67294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function i(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?o(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):o(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function l(e,t){if(null==e)return{};var n,a,r=function(e,t){if(null==e)return{};var n,a,r={},o=Object.keys(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var s=a.createContext({}),p=function(e){var t=a.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},u=function(e){var t=p(e.components);return a.createElement(s.Provider,{value:t},e.children)},c="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},h=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,o=e.originalType,s=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),c=p(n),h=r,m=c["".concat(s,".").concat(h)]||c[h]||d[h]||o;return n?a.createElement(m,i(i({ref:t},u),{},{components:n})):a.createElement(m,i({ref:t},u))}));function m(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var o=n.length,i=new Array(o);i[0]=h;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l[c]="string"==typeof e?e:r,i[1]=l;for(var p=2;p<o;p++)i[p]=n[p];return a.createElement.apply(null,i)}return a.createElement.apply(null,n)}h.displayName="MDXCreateElement"},53966:function(e,t,n){n.r(t),n.d(t,{assets:function(){return s},contentTitle:function(){return i},default:function(){return d},frontMatter:function(){return o},metadata:function(){return l},toc:function(){return p}});var a=n(87462),r=(n(67294),n(3905));const o={sidebar_label:"AI chat",title:"AI chat",description:"Joplin can connect to a chat model \u2014 either a cloud service or one running on your own machine \u2014 so that the AI chat panel and plugins can use it to summarise, rewrite, or answer questions about yo..."},i="AI chat",l={unversionedId:"apps/ai_chat",id:"apps/ai_chat",title:"AI chat",description:"Joplin can connect to a chat model \u2014 either a cloud service or one running on your own machine \u2014 so that the AI chat panel and plugins can use it to summarise, rewrite, or answer questions about yo...",source:"@site/help/apps/ai_chat.md",sourceDirName:"apps",slug:"/apps/ai_chat",permalink:"/help/apps/ai_chat",draft:!1,editUrl:"https://github.com/laurent22/joplin/tree/dev/readme/apps/ai_chat.md",tags:[],version:"current",frontMatter:{sidebar_label:"AI chat",title:"AI chat",description:"Joplin can connect to a chat model \u2014 either a cloud service or one running on your own machine \u2014 so that the AI chat panel and plugins can use it to summarise, rewrite, or answer questions about yo..."},sidebar:"helpSidebar",previous:{title:"WebDAV synchronisation",permalink:"/help/apps/sync/webdav"},next:{title:"AI chat panel",permalink:"/help/apps/ai_chat_panel"}},s={},p=[{value:"Turning it on",id:"turning-it-on",level:2},{value:"Picking a provider",id:"picking-a-provider",level:2},{value:"Private network vs remote: the &quot;Allow remote providers&quot; switch",id:"private-network-vs-remote-the-allow-remote-providers-switch",level:2},{value:"Token usage",id:"token-usage",level:2},{value:"Testing your setup",id:"testing-your-setup",level:2},{value:"Plugins that use AI chat",id:"plugins-that-use-ai-chat",level:2},{value:"Disabling AI",id:"disabling-ai",level:2}],u={toc:p},c="wrapper";
1function d(e){let{components:t,...n}=e;return(0,r.kt)(c,(0,a.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"ai-chat"},"AI chat"),(0,r.kt)("div",{className:"donate-links"},(0,r.kt)("p",null,(0,r.kt)("a",{parentName:"p",href:"https://www.paypal.com/donate/?hosted_button_id=WQCERTSSLCC7U"},(0,r.kt)("img",{parentName:"a",src:"https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/badges/Donate-PayPal-green.svg",alt:"Donate using PayPal"}))," ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/sponsors/laurent22/"},(0,r.kt)("img",{parentName:"a",src:"https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/badges/GitHub-Badge.svg",alt:"Sponsor on GitHub"}))," ",(0,r.kt)("a",{parentName:"p",href:"https://www.patreon.com/joplin"},(0,r.kt)("img",{parentName:"a",src:"https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/badges/Patreon-Badge.svg",alt:"Become a patron"}))," ",(0,r.kt)("a",{parentName:"p",href:"https://joplinapp.org/donate/#donations"},(0,r.kt)("img",{parentName:"a",src:"https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/badges/Donate-IBAN.svg",alt:"Donate using IBAN"})))),(0,r.kt)("p",null,"Joplin can connect to a chat model \u2014 either a cloud service or one running on your own machine \u2014 so that the ",(0,r.kt)("a",{parentName:"p",href:"/help/apps/ai_chat_panel"},"AI chat panel")," and plugins can use it to summarise, rewrite, or answer questions about your notes. The model itself is configured in ",(0,r.kt)("strong",{parentName:"p"},"one place")," in the settings. Plugins then use that model without needing their own API keys."),(0,r.kt)("p",null,"This page covers the underlying configuration. For the chat panel built into the editor, see ",(0,r.kt)("a",{parentName:"p",href:"/help/apps/ai_chat_panel"},"AI chat panel"),"."),(0,r.kt)("h2",{id:"turning-it-on"},"Turning it on"),(0,r.kt)("p",null,"AI is ",(0,r.kt)("strong",{parentName:"p"},"off by default"),". To enable it:"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"Open the ",(0,r.kt)("a",{parentName:"li",href:"/help/apps/config_screen"},"Configuration screen")," and go to the ",(0,r.kt)("strong",{parentName:"li"},"AI")," section."),(0,r.kt)("li",{parentName:"ol"},"Tick ",(0,r.kt)("strong",{parentName:"li"},"Enable AI features"),"."),(0,r.kt)("li",{parentName:"ol"},"Pick a ",(0,r.kt)("strong",{parentName:"li"},"Chat provider")," and fill in its settings."),(0,r.kt)("li",{parentName:"ol"},"Click ",(0,r.kt)("strong",{parentName:"li"},"Test AI configuration")," to verify it works.")),(0,r.kt)("p",null,"AI features are only available on the desktop app."),(0,r.kt)("h2",{id:"picking-a-provider"},"Picking a provider"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Provider"),(0,r.kt)("th",{parentName:"tr",align:null},"What it is"),(0,r.kt)("th",{parentName:"tr",align:null},"Setup"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},(0,r.kt)("strong",{parentName:"td"},"Joplin Cloud AI")),(0,r.kt)("td",{parentName:"tr",align:null},"A chat model hosted by Joplin Cloud. Available to Joplin Cloud users on supported plans."),(0,r.kt)("td",{parentName:"tr",align:null},"Zero config \u2014 Joplin reuses your sync credentials. Selected automatically the first time you enable AI if you are syncing with Joplin Cloud.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},(0,r.kt)("strong",{parentName:"td"},"OpenAI-compatible")),(0,r.kt)("td",{parentName:"tr",align:null},"Any service that speaks the OpenAI API: OpenAI itself, Ollama, LM Studio, OpenRouter, vLLM, and many others."),(0,r.kt)("td",{parentName:"tr",align:null},"Set the base URL (e.g. ",(0,r.kt)("inlineCode",{parentName:"td"},"https://api.openai.com/v1")," or ",(0,r.kt)("inlineCode",{parentName:"td"},"http://localhost:11434/v1")," for Ollama), the API key, and the model name.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},(0,r.kt)("strong",{parentName:"td"},"Anthropic")),(0,r.kt)("td",{parentName:"tr",align:null},"Direct calls to Anthropic's Claude models."),(0,r.kt)("td",{parentName:"tr",align:null},"Set your API key and a model id (e.g. ",(0,r.kt)("inlineCode",{parentName:"td"}
1,"claude-3-5-sonnet-latest"),").")))),(0,r.kt)("p",null,"You can change provider at any time."),(0,r.kt)("h2",{id:"private-network-vs-remote-the-allow-remote-providers-switch"},'Private network vs remote: the "Allow remote providers" switch'),(0,r.kt)("p",null,"To protect against accidentally sending your notes to a cloud service, Joplin keeps a second, separate switch: ",(0,r.kt)("strong",{parentName:"p"},"Allow remote AI providers"),". By default it is off."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"Private-network providers")," work with this switch off \u2014 your notes never leave your own network. This covers Ollama, LM Studio, or any other OpenAI-compatible server reachable at:",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"localhost"),", ",(0,r.kt)("inlineCode",{parentName:"li"},"127.0.0.1")," or ",(0,r.kt)("inlineCode",{parentName:"li"},"::1")),(0,r.kt)("li",{parentName:"ul"},"a private LAN address: ",(0,r.kt)("inlineCode",{parentName:"li"},"10.x.x.x"),", ",(0,r.kt)("inlineCode",{parentName:"li"},"172.16.x.x"),"\u2013",(0,r.kt)("inlineCode",{parentName:"li"},"172.31.x.x"),", ",(0,r.kt)("inlineCode",{parentName:"li"},"192.168.x.x"),", ",(0,r.kt)("inlineCode",{parentName:"li"},"169.254.x.x"),", or an IPv6 unique-local (",(0,r.kt)("inlineCode",{parentName:"li"},"fc00::/7"),") / link-local (",(0,r.kt)("inlineCode",{parentName:"li"},"fe80::/10"),") address"),(0,r.kt)("li",{parentName:"ul"},"a hostname ending in ",(0,r.kt)("inlineCode",{parentName:"li"},".localhost"),", ",(0,r.kt)("inlineCode",{parentName:"li"},".internal")," or ",(0,r.kt)("inlineCode",{parentName:"li"},".home.arpa")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"Remote providers")," (Joplin Cloud AI, Anthropic, OpenAI, and any other public endpoint) need this switch on. If it's off, AI calls to a remote provider fail with a clear error.")),(0,r.kt)("p",null,"A private-network provider does not require an API key, since these servers usually have no authentication. You can still set one if your server expects it \u2014 leave the field empty otherwise."),(0,r.kt)("p",null,"Note that ",(0,r.kt)("inlineCode",{parentName:"p"},".local")," hostnames are treated as remote. Unlike the names above, ",(0,r.kt)("inlineCode",{parentName:"p"},".local")," is resolved via mDNS/Bonjour and can point at any machine on the network you happen to be joined to, which isn't a safe assumption on public Wi-Fi. Use the machine's LAN IP address instead."),(0,r.kt)("h2",{id:"token-usage"},"Token usage"),(0,r.kt)("p",null,"Most chat providers charge per token. To help you keep an eye on usage, Joplin tracks cumulative input and output tokens for the ",(0,r.kt)("strong",{parentName:"p"},"currently configured provider")," and shows them in Settings \u2192 AI. There's a ",(0,r.kt)("strong",{parentName:"p"},"Reset token usage")," button next to the counters."),(0,r.kt)("p",null,"When you change provider or endpoint, the counters reset automatically so you don't mix totals from different services."),(0,r.kt)("h2",{id:"testing-your-setup"},"Testing your setup"),(0,r.kt)("p",null,"The ",(0,r.kt)("strong",{parentName:"p"},"Test AI configuration"),' button sends a one-message chat ("Reply with the single word OK.") to your active provider and shows the response inline. This is the fastest way to confirm everything works end-to-end \u2014 the configuration screen does not validate provider details until you actually call the model.'),(0,r.kt)("p",null,"If the test fails, the error message is shown directly below the button. Common ones:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("em",{parentName:"li"},'"Joplin Cloud AI requires Joplin Cloud sync"')," \u2014 you picked Joplin Cloud AI but you're not syncing with Joplin Cloud. Either restore Joplin Cloud sync or pick a different provider."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("em",{parentName:"li"},'"Remote AI providers are not allowed"')," \u2014 turn on ",(0,r.kt)("strong",{parentName:"li"},"Allow remote AI providers"),"."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("em",{parentName:"li"},'"No choices in response \u2014 check that the base URL includes /v1"')," \u2014 common for local Ollama / LM Studio servers; the base URL needs the ",(0,r.kt)("inlineCode",{parentName:"li"},"/v1")," suffix.")),(0,r.kt)("h2",{id:"plugins-that-use-ai-chat"},"Plugins that use AI chat"),(0,r.kt)("p",null,"Plugins can call ",(0,r.kt)("inlineCode",{parentName:"p"},"joplin.ai.chat()")," to ask the model a question. They cannot choose the provider or the model \u2014 both come from your settings. That means a plugin written against OpenAI will also work against Ollama or Joplin Cloud AI with no changes."),(0,r.kt)("p",null,"If a plugin uses AI, you'll see it in the plugin's description. The plugin can read your notes as part of building its prompt, so the usual rules apply: if you're using a remote provider, that note content goes to the provider."),(0,r.kt)("h2",{id:"disabling-ai"},"Disabling AI"),(0,r.kt)("p",null,"Untick ",(0,r.kt)("strong",{parentName:"p"},"Enable AI features")," in Settings \u2192 AI. While the master toggle is off, no AI call from any plugin or built-in feature succeeds, regardless of provider settings or the remote-allow switch."))}d.isMDXComponent=!0}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.