Upgrade from 0.x to 1.0
What changes from 0.12, what to do about it, and how to try 1.0 before it ships.
Try 1.0 before the release
pip install llmslim installs 0.12.0 until 1.0 is on PyPI. These pages describe the main branch, which becomes the 0.13 release candidate and then 1.0. To try it now, install it from GitHub. It reports its version as 0.12.0 until the release changes it.
pip install "llmslim @ git+https://github.com/Thanatos9404/llmslim"
pip install "llmslim[mcp,server] @ git+https://github.com/Thanatos9404/llmslim" # with extrasChecklist
In the order you are likely to meet them:
- Python 3.10 or newer (below).
Memory.searchshows a session's date once (below). If you compare its text to recorded output, passdate_format="%Y-%m-%d"or record it again.- Some helper names left the
__all__lists of integration modules andllmslim.server(below). planner_versionis the release (below): trace ids change in every release.- A keyless
llmslim serveor proxy answers only to this machine's names (below). - Database outages are a 503, not a 500 (below).
Python 3.10 or newer
1.0 requires Python 3.10. Python 3.9 reached end of life in October 2025, and the MCP server and most framework extras already needed 3.10. On Python 3.9, pip keeps installing 0.12.0, so nothing breaks by surprise; the public API doesn't change. The extras lose their python_version markers.
A session's date is shown once
When Memory.search selects from a long history, the first kept turn of a session shows its full stamp, and so does a later turn whose time differs from the one shown last. Any other kept turn used to repeat the date, [2026-10-17] assistant: ...; it now shows assistant: ... alone, under the stamp above it. date_format now defaults to None. The repeated date was most of each kept turn's label, so more turns fit. A history that fits the budget whole still shows the full stamp on every turn.
from llmslim.memory import Memory
memory = Memory("memory.db") # 1.0: role: text under the session's stamp
memory = Memory("memory.db", date_format="%Y-%m-%d") # the labels of 0.12, byte for byte[2026-10-17 (Sat) 14:05] user: I'm planning a trip to Jaipur in December for my sister's wedding.
assistant: ... Congratulations! December is a lovely time to visit Jaipur.
user: Which hotels near the City Palace would you suggest?[2026-10-17 (Sat) 14:05] user: I'm planning a trip to Jaipur in December for my sister's wedding.
[2026-10-17] assistant: ... Congratulations! December is a lovely time to visit Jaipur.
[2026-10-17] user: Which hotels near the City Palace would you suggest?Stored text still can't pass for a label: where a label can be the role alone, a line in a code block or table that starts with user:, assistant:, system: or tool: is indented by two spaces. With a date_format string, only dated lookalikes are indented, as before.
Narrower public lists
Before 1.0 freezes the public API, these names left __all__. They stay importable from the modules that define them, but they are internal now, so a later release may change them:
llmslim.serverexportscreate_appandmain(and the experimentalChatUpstream);api_keys_fromandis_loopbackare internal.llmslim.integrations.web_searchexportsWebSearchSource,WebSearchResultand their errors; its 20 helper functions and limits are internal.llmslim.integrations.sarvamkeeps its documented classes and functions, their result types and errors (35 names, down from 42). Its guard prefixes, default limits andsarvam_chat_cost_inrare internal, and it no longer re-exports the text and document limits.sarvam_textandsarvam_documentskeep their documented names.llmslim.planning.planner.PLANNER_VERSIONandllmslim.planning.progressive.PLANNER_VERSIONstill import, but left those modules'__all__.
llmslim.tokens, llmslim.mcp and llmslim.integrations.openai_agents now declare __all__, without renaming or removing anything. A star import (from module import *) gets only what __all__ lists. API stability says what is public.
planner_version is the release
PlanMetrics.planner_version and ContextTrace.planner_version were fixed at "0.7.0" ("0.6.0" for plan_context) since 0.7.0, though planner output changed in later releases. They are now llmslim.__version__, read when the plan is made. ContextTrace.trace_id is derived from the envelope and this version, so the same envelope gets a new trace id in each release. If you stored trace ids or compared planner_version to a constant, compare to the release instead.
import llmslim
from llmslim import plan_context
plan = plan_context(messages=[{"role": "user", "content": "Hello"}], model="sarvam-105b")
assert plan.metrics.planner_version == llmslim.__version__ # 0.12 said "0.6.0" hereKeyless servers answer only to this machine
A server on 127.0.0.1 is reachable from any page the user opens: a cross-site request could store a planted instruction in memory, and DNS rebinding let a page read and delete every memory. So a keyless llmslim serve and the llmslim proxy now answer only requests whose Host names this machine (localhost, a *.localhost name, 127.0.0.0/8, [::1]) and refuse with a 403 any request whose Origin is another site. Clients that send no Origin, such as curl, SDKs and agents, aren't affected.
- If clients reach a keyless server by another name (
host.docker.internalfrom a container, say), add it with--allowed-host(repeatable;*for any),LLMSLIM_ALLOWED_HOSTSorcreate_app(..., allowed_hosts=[...]). - Servers with API keys accept any
Hostas before, unless you pin names the same way. - The proxy takes
--allowed-hostandcreate_proxy_app(..., allowed_hosts=[...]).
Cleaner errors from servers
When Postgres or MongoDB can't be reached, llmslim serve answers a 503 with "type": "store_unavailable" and Retry-After: 5 (0.12 answered a plain-text 500), and recovers by itself when the database is back. Any other failure in a route is a JSON 500, "type": "server_error". llmslim serve and llmslim mcp exit at start with one line when the store can't be opened. Hostile JSON (too deep, wrong types, out-of-range times, a lone surrogate) is a 400, and Memory.add refuses a timestamp with no UTC time with a ValueError.
Output that changes
Which turns search keeps is output content, which a minor release may improve (see API stability). Between 0.12 and 1.0:
- a reply short enough to be one window inherits its session's relevance, as a user turn does, so conversations between two people stored as
userandassistantkeep more of the second speaker's turns; fit(/v1/context/fit,fit_context) stays within about 2% of its budget for any text: when compression can't get there (one long code block, say), the result is cut to the longest head that fits the budget;- the Docker image installs the Postgres and MongoDB drivers.
What's new
Each has its own guide:
llmslim import: Claude Code, ChatGPT, Claude.ai, Mem0 and JSONL history, in one command.explain=True: why each turn was kept, cut or left out.- MongoDB as a memory store.
- An OpenAI-compatible chat endpoint in
llmslim serve(experimental). - Remote MCP:
llmslim mcp --transport http(experimental). - Mastra tools and an output processor in the TypeScript client (already on npm as 0.2.0).
- Release files attested with SLSA build provenance and an SBOM;
SECURITY.mdshows how to verify them.
Questions
Do I have to change my code?
Most code runs unchanged. Check the Python version, any import of a name that left __all__, any test that compares Memory.search text byte for byte, and any client that reaches a keyless server by a name other than localhost.
Will my stored memory open in 1.0?
Yes. 1.0 reads SQLite files and Postgres tables written by 0.12.
What does 1.0 promise that 0.x didn't?
Semantic versioning for the public API: no breaking change before 2.0, and a deprecation period of at least two minor releases and 90 days before anything is removed. See API stability.