{"slug": "point-any-app-at-a-local-llm-on-your-mac-openai-compatible-endpoints", "title": "Point any app at a local LLM on your Mac (OpenAI-compatible endpoints)", "summary": "A developer explains how to redirect any app using OpenAI's Chat Completions API to a local LLM on a Mac by changing the base URL to Ollama's or LM Studio's local endpoint. This works because most AI apps accept a custom base URL and the local runners expose the same API format. The trick enables free, private local inference without the app noticing the switch.", "body_md": "Most apps that grew an \"AI\" feature in the last two years talk to one of a handful of cloud APIs, and almost all of them speak the same dialect: the OpenAI Chat Completions format. That one detail is the reason you can pull the cloud out and run the whole thing locally on a Mac without the app ever noticing.\n\nHere is the trick, why it works, and the gotchas that bite.\n\nOpenAI's `/v1/chat/completions`\n\nendpoint became the de facto standard. So when an app lets you \"use your own key\" or \"set a custom base URL,\" it is almost always going to POST to `{base_url}/chat/completions`\n\nwith a JSON body of messages and read back the same shape. It does not care what is on the other end, only that the response matches.\n\nLocal runners leaned into this. Both popular Mac ones expose exactly that endpoint:\n\n`http://localhost:11434/v1`\n\n(its native API lives on `/api`\n\n, but the `/v1`\n\npath speaks the OpenAI dialect).`http://localhost:1234/v1`\n\n.So \"make this app local\" usually reduces to: point its base URL at one of those, put any non-empty string where it wants an API key, and pick a model you have pulled.\n\nOllama:\n\n```\nbrew install ollama        # or the .dmg from ollama.com\nollama serve &             # server on :11434\nollama pull llama3.1:8b    # pull a model once\n```\n\nConfirm it speaks OpenAI:\n\n```\ncurl http://localhost:11434/v1/chat/completions \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"model\": \"llama3.1:8b\",\n    \"messages\": [{\"role\": \"user\", \"content\": \"say hi in 3 words\"}]\n  }'\n```\n\nIf that returns a `choices[0].message.content`\n\n, any OpenAI-compatible client can use it. In the app, set:\n\n`http://localhost:11434/v1`\n\n`ollama`\n\n(or literally anything; it is ignored)`llama3.1:8b`\n\nLM Studio is the same idea with a GUI: load a model, toggle the server on, and use base URL `http://localhost:1234/v1`\n\n.\n\nThe pattern shows up everywhere once you look for it. The official OpenAI SDKs are the clearest example: change one field.\n\n``` python\nfrom openai import OpenAI\n\nclient = OpenAI(base_url=\"http://localhost:11434/v1\", api_key=\"ollama\")\nr = client.chat.completions.create(\n    model=\"llama3.1:8b\",\n    messages=[{\"role\": \"user\", \"content\": \"summarize this in one line: ...\"}],\n)\nprint(r.choices[0].message.content)\n```\n\nSame code, cloud or local. Only the `base_url`\n\nchanged. In JavaScript it is the `baseURL`\n\noption; in a lot of CLI and editor tools it is an `OPENAI_BASE_URL`\n\nenvironment variable. Some end-user apps expose it too: DEVONthink 4, for instance, lets its Chat point at Ollama or LM Studio directly, so search and summarize run over your own documents with nothing leaving the machine.\n\nIt is not always drop-in. The places it breaks, roughly in order of how often they catch people:\n\n`num_ctx`\n\n). If an app sends a big document and the model only reads the last 2k tokens, it looks like the model \"ignored\" your content. Raise the context in the model config, or send smaller chunks.Two reasons that actually matter. It is free after the download, so there is no per-token meter running while you iterate on a prompt fifty times. And nothing leaves the machine, which for anything sensitive (client data, personal notes, a private codebase) is the difference between \"I can use AI on this\" and \"I am not allowed to.\"\n\nThe best part is that because it is one interface, you do not have to commit. Keep a cloud base URL for the genuinely hard reasoning and a local one for the bulk, private, high-volume work, and switch between them by changing a single string.\n\n*Written with AI assistance and edited by a human. Endpoint details reflect public docs as of July 2026 and move quickly, so check each project's current docs for exact paths and defaults.*", "url": "https://wpnews.pro/news/point-any-app-at-a-local-llm-on-your-mac-openai-compatible-endpoints", "canonical_source": "https://dev.to/jacksonxly/point-any-app-at-a-local-llm-on-your-mac-openai-compatible-endpoints-4o8l", "published_at": "2026-07-10 00:17:10+00:00", "updated_at": "2026-07-10 01:05:55.076071+00:00", "lang": "en", "topics": ["developer-tools", "large-language-models", "ai-infrastructure"], "entities": ["OpenAI", "Ollama", "LM Studio", "DEVONthink"], "alternates": {"html": "https://wpnews.pro/news/point-any-app-at-a-local-llm-on-your-mac-openai-compatible-endpoints", "markdown": "https://wpnews.pro/news/point-any-app-at-a-local-llm-on-your-mac-openai-compatible-endpoints.md", "text": "https://wpnews.pro/news/point-any-app-at-a-local-llm-on-your-mac-openai-compatible-endpoints.txt", "jsonld": "https://wpnews.pro/news/point-any-app-at-a-local-llm-on-your-mac-openai-compatible-endpoints.jsonld"}}