FAQ#
Distilled from the issue tracker: the questions that keep arriving, answered the way the maintainers actually answered them, with the thread linked so you can read the reasoning in full. Knowing these saves everyone a round trip — several are settled design decisions, and knowing the reasoning saves you from re-arguing them by accident.
Contributing#
Can I add support for language X?#
Yes — this is the contribution the project is built to receive, and it needs no issue first. Follow the language-support path; the maintainers’ answer to “would you accept this?” has consistently been yes when the work follows the established pattern (#1598, #1709). A request with no volunteer attached tends to sit — the path is walked by whoever wants the language.
Can my agent or CLI be supported as a hooks client?#
Also a welcomed PR (#1837,
#1869). The accepted shape is small and
established: a client enum entry in src/serena/hooks.py, a handler branch in
src/serena/config/client_setup.py, a context YAML under
src/serena/resources/config/contexts/, and docs — around 170 lines across four files
(#1581 is the precedent).
What does a fast-merging pull request look like here?#
The tracker’s record is consistent: a scoped fix with the root cause named in the title; an issue first and then the PR that closes it; a language server that follows the template; a docs correction. PRs of these shapes routinely merge within hours. Two mechanical points help: keep “Allow edits by maintainers” enabled on your fork branch (#1720 had to be merged out-of-band without it), and keep reports brief and structured — a summary first, detail beneath.
My fix was closed and a maintainer landed a different one. Did I waste my time?#
No — this is a normal outcome for fixes that touch solidlsp internals or bend a design
principle. The pattern in the record: the diagnosis and the test survive into the maintainer’s
deeper fix, sometimes with explicit co-author credit
(#1719 →
#1726). The way to make your work land intact is
to fix the cause the design wants fixed, not the symptom in front of you — and when in doubt,
that is exactly what an issue-first conversation is for.
Is there work I should not pick up?#
Issues labeled for core team only are design work the maintainers have reserved — spec
discussions that end in maintainer commits, not calls for PRs. Anything beyond
CONTRIBUTING.md’s three welcome categories (isolated additions along existing lines, small
bug fixes, documentation) wants an issue first. And a few things are settled as out of scope:
directory badges, monetization layers, and hardening added for problems that have not been
diagnosed (#1790 carries the fullest statement
of that principle).
My PR has had no review for days — is something wrong?#
No — a few quiet days are normal here and say nothing about your PR’s fate (D1655). Critical fixes move at once; everything else waits for the attention it deserves rather than the first free minute. Unhurried is not unwatched.
Do I need an issue before sending a pull request?#
For the three welcome categories — isolated additions along existing lines, small bug fixes, documentation — no. For everything else yes, and it is enforced: design-first is house doctrine, and code-first PRs are closed regardless of quality, up to multi-thousand-line features (“4150 loc of changes is the limit of PRs that we accept before prior discussion in an issue… Jokes aside”, #1330; “It’s not a comment on the quality of the code”, #1234). The maintainers frame the rule as protecting your time as much as theirs: “Our prior discussion rule serves to ensure an optimal outcome from the get-go. Serena is not a vibe-coded project” (#1651); “We really cannot skip the software design phase for changes like this” (#1629). And expect an agreed idea to sometimes come back smaller from a maintainer’s keyboard: the polyglot proposal of #703 shipped as a net addition of under 200 lines in #704.
Why was my defensive-hardening fix or tiny config option rejected?#
Because the first review question is whether the problem is real, and a hypothetical does not count. Hardening gets asked “Has this actually happened to you?” — and an unanswered question ends in “No response from OP, therefore closing” (#1649). Speculative robustness is quantified bluntly: “That’s not a diagnosed problem — that’s an undiagnosed CI flake, and this is 245 lines of production hardening against it” (#1790). Config options face the same test from the other side: the use case is interrogated (“Do you actually need the per-project override?”, #1067) and the complexity must pay for itself — “we can’t merge something that increases complexity just to support it” (#1016). Stopgaps for problems with a known proper design are refused outright: “We have to do this properly or not at all” (#932). So reproduce the failure or defend the use case in the thread — and answer review questions promptly.
My PR was closed unmerged — or has sat open for months. What does either mean?#
Often neither means what it looks like. Closed frequently means the author went quiet (“No reaction, closing”, #1352) or closed it themselves to resubmit a cleaner branch — and the maintainers visibly regret losing people (“may I ask why you decided to close and delete the code? :(“, #1409). Closed can even mean merged: work lands as a manually squashed commit or inside a maintainer’s PR with co-author credit. Open, conversely, is deliberate: there is no stale bot, because “We want the closing of issues/PRs to be a deliberate decision” (#596), and some PRs are kept open purely as design reference (#896). Age alone signals nothing; respond to pings and keep the branch alive.
I fixed one language server — why is it on hold, or redone at a different layer?#
“On hold” here usually means “being generalised”, not ignored. The maintainers consistently
prefer the general mechanism over a per-language special case: a per-LS feature gets parked
— “This is on hold as we consider centralising this in order to support this for all
language servers” (#1544, which then landed
for every server) — and a narrow fix gets replaced by one at the right layer (“a more
general fix was needed to unblock the dispatcher thread for all tool executions”,
#1746). Before adding a per-LS knob, check
whether ls_specific_settings or the initialization-options passthrough already covers it.
Dependency bumps follow the same logic: JDTLS version PRs were parked while downloads gained
pinning and checksum verification
(#1219,
#1238) — comment in the design issue rather
than PRing ahead of it.
What happens to low-effort AI-generated pull requests?#
They are closed without detailed review, and bluntly — “Stop submitting this AI slop”
(#1661). The tell the maintainers cite is a
description that does not match the content: “The module mcp.server.global_check does not
exist, the PR content is not doing what the PR description states”
(#1689). Using AI assistance is not the
offense — submitting changes you have not understood and verified is, and incoherent volume
costs you standing for everything you send afterwards.
Can I add a tool exposing another LSP capability — hover, completions, inlay hints?#
Tools are judged by whether their output helps an LLM and what it costs in tokens — not by whether the LSP offers the data. Completions were rejected on exactly that ground (“requesting completions [is] unlikely to be useful to LLMs”, #896). Capabilities the maintainers do want, they design and ship themselves, initially as opt-in tools — a contributed diagnostics tool was closed with “the diagnostic feature we will incorporate is significantly more extensive” (#661), and hover docs went the same way (#873). So propose the capability in an issue, make the LLM-utility case, and expect the core team to take the implementation over.
Settled design decisions#
Why is Serena an MCP server rather than a CLI?#
“Because language servers are stateful and so is serena” (#1772). The session holds live language-server processes, caches and project state; a stateless invocation model would rebuild that on every call.
One missing language runtime makes all symbolic tools fail — is that a bug?#
Intentional, and defended when challenged (#1670):
the configured language list expresses intent, so an unavailable server fails fast rather than
degrading silently. The per-machine escape hatch is project.local.yml, which can narrow the
language list without touching the shared project config.
Can I point Serena at my own language-server binary — or plug in an external LSP client?#
Custom binaries: partially, and per-language by design — the language-server-specific settings can override the server path where a wrapper implements it, and the dependency-provider redesign (#917) lets any server be adapted; missing overrides get added on request, sometimes same-day (#977). External LSP clients — driving Serena’s servers from Neovim, say — no, and that is a position, not a gap: “Serena is a fully integrated system where everything is finely tuned to work in unison. This is precisely what makes Serena work so well” (#1089).
Security: what counts, and what does not#
Serena’s security model is documented at Security, and it draws one line worth understanding before you file anything: what you configure is trusted. Your config, your projects, the tools you enable — Serena assumes you meant it.
A scanner flagged the shell tool / gave the MCP server a low grade.#
Not a security issue, and the maintainers have answered it consistently (#1585 among others): an agent’s shell tool is inherently arbitrary code execution — that is what it is for — and meaningful confinement comes from sandboxing, not from warnings or opt-outs inside Serena. The security page says it plainly: reports amounting to “Serena’s tools can execute commands or modify files” describe intended functionality, and advisories that fail to recognise this are rejected.
So what does count?#
Anything that crosses the trust line: a way for input you did not choose to trust to cause effects you did not ask for. The verified-download machinery is a concrete example of the model defending itself — every fetched dependency is checked against the checksum database, because a tampered download is exactly the kind of untrusted input the model exists to refuse. If the scenario requires you to have already trusted the thing doing the damage, it is the documented model at work; if it does not, the maintainers want to hear about it.
How do I report one?#
Privately. The repository has GitHub’s private vulnerability reporting enabled — use it rather than a public issue, name the trust boundary being crossed, and show the crossing. The security page’s own words: advisories are welcome for issues that violate the model it describes.
Gotchas while working on Serena#
I changed a config file and nothing happened.#
Configuration is read at startup; changes take effect after a restart (#1798). To add a language to a running instance, use the dashboard’s add-language button. An explicitly empty language-server list is treated as intentional, not repaired.
I restarted the server — why is my harness still talking to the old one?#
With the default stdio transport, your MCP client owns the server process: Serena starts
when the client connects and ends with it, so “restart the server” is a client-side act.
Tell your harness to reconnect its MCP servers — in Claude Code, /mcp lists them and
offers a reconnect; other clients have an equivalent — or restart the session. The reconnect
runs the launch command again, which is exactly what re-reads configuration and picks up a
rebuilt branch.
Over sse or streamable-http, the server runs on its own and the client merely attaches —
there, restarting really does mean restarting the server process yourself.
A language has several server implementations — which one runs?#
Languages are configured per project, not globally, and server priorities are configurable in
serena_config.yml (#1736,
D1735).
Running Serena: the questions the tracker keeps answering#
These are user-side rather than contributor-side, but they account for more tracker volume than everything above combined — worth knowing whichever side you are on.
Does Serena support monorepos and multiple languages in one project?#
Yes, fully, since the LanguageServerManager redesign
(#704): list them under languages: in
.serena/project.yml, pass several to serena project create, or add one at runtime from
the dashboard — “Serena now has full monorepo support, you just need to set the languages in
your project.yml” (D542). Detection at
creation is deliberately conservative (every language is another running server), so if
symbol tools return nothing, check the detected language in project.yml first. One live
nuance (#1260): activating the monorepo root
gives repo-wide symbols with the root’s memories; activating a nested subproject isolates
its memories but narrows scope to that child. Older refusals of multi-server support predate
the redesign — don’t cite them as current.
Symbolic tools hang or time out while file tools keep working. What’s wrong?#
That split is the diagnosis: “If the symbolic tools do not work, it means something went
seriously wrong and the language server is not reacting”
(#336). Triage in the maintainers’ order:
check for an open duplicate, check project.yml detected the right language, and run
serena project index as the smoke test — if indexing does not run through, the language
server is the problem. Use the right context (ide-assistant for Claude Code), and for
diagnosis run with --log-level DEBUG --trace-lsp-communication True
(#240). Years of reports carry one triage
signal: Python is stable, so if only language X hangs, it is X’s server — and for old C# or
TypeScript complaints, upgrade first, because both servers were wholesale replaced.
Serena is slow or eats RAM on my large project. What can I actually do?#
Separate the first call from steady state. First call: “if a project was not previously
indexed, the first call will perform indexing of the entire project”
(#731) — so pre-index with
serena project index, raise --timeout (it is per file), and shrink the surface with
ignored_paths. Steady state: the cost is almost always the language server itself, which
Serena cannot make faster — clangd on an llvm-scale tree projected six-plus hours, “a
limitation of the clangd language server, which is, unfortunately, slow”
(#890) — so enable only the languages you
need. On Windows, exclude development directories from antivirus scanning: that, not the
file walk, was the culprit in slow-indexing reports
(#1628).
Does Serena respect .gitignore — and why is vendor/ still being scanned?#
Serena ignores everything your project’s .gitignore ignores, plus ignored_paths in
.serena/project.yml (#299). Two deliberate
boundaries explain the surprises. The global gitignore is intentionally not parsed
(“We discussed internally, and decided not to parse the global gitignore, at least for now”,
#577). And Serena’s ignore handling governs
only Serena’s own tools — the language server is a separate program that scans files by its
own rules (“It is the PHP language server… which will read these files. At the Serena
level, the settings are respected”, #577);
tune the server itself through ls_specific_settings.
Serena fails to connect or times out in my client but runs fine standalone.#
The standard triage: start the launch command manually in a terminal, run
serena project health-check, and read ~/.serena/logs — “If they work, the only sources
of errors can be in [the client’s] MCP config or in some side effects due to many MCP
Servers being present. Maybe you need a global path to uvx…”
(#635). Common culprits: a non-absolute
uvx path, other MCP servers interfering, a config the agent wrote for itself instead of
the readme’s command, and — in headless or container setups — the dashboard trying to open
a browser (--enable-web-dashboard false,
#648). First-run timeouts are activation
running synchronously at startup: pre-index the project, raise the client’s MCP timeout, or
run SSE mode, where the server is started once, by you
(#494).
Serena can’t see files that clearly exist.#
Work down the list. Gitignored files are not symbol-indexed, by design and by
recommendation (“you can adjust a corresponding setting in the config — though I wouldn’t
recommend it”, #1361). Blanket ignoring of
dot-directories was removed in #1203 — only
VCS directories are skipped now, so upgrade if dot-folders still come back empty. And some
older per-language hard-coded ignore lists (Java’s dist/lib/classes/out,
TypeScript’s coverage) silently hid real code — the maintainer position is that those
lists were a mistake and .gitignore patterns should govern
(#1645); several are gone, so again:
upgrade.
My agent barely uses Serena’s tools and keeps reaching for grep.#
Two setup steps get skipped. A project must be activated — “You cannot even use any of its actual tools without activating a project” (#241) — and the agent should read Serena’s initial instructions at session start and again after every context compaction, “since there is no way to know which information will get lost as a result of compacting” (same thread). Claude Code adds a third factor: it truncates each MCP server’s instructions, and the supported fix is the serena-hooks CLI — “With this, the instructions are always fully read and claude code uses Serena consistently” (#1303). Beyond that, some fumbling is model behaviour Serena cannot fix (“we’re at the mercy of Anthropic here”, #1398) — and the cap on oversized search results is deliberate context protection, “a feature, not a bug” (#237).
The first symbol query returns empty — or results go stale after outside edits.#
Two timing bugs, now largely closed — upgrade first. Early-session emptiness came from
fixed readiness waits instead of the server’s actual signal, fixed per server (pyright:
“Fixed by 30c84f15e”, #1681; Scala’s wait
replaced in #1859) — on older versions,
treat an early empty as “not indexed yet”, never as a real no. Post-edit staleness came
from didChangeWatchedFiles being advertised but never sent, fixed by syncing in the
manager (#1718) — with the maintainer’s
scoping that find_symbol and get_symbols_overview were never affected; the gap hit
find_referencing_symbols with an explicit path. A restart clears it on pre-fix versions.
One report in this class remains open and unreproduced
(#1593) — “it was a real phenomenon.”
Language-server processes pile up after my client exits.#
Not expected — but two things are true at once. The MCP client owns the server lifecycle by design, and “Serena already kills the language server itself in the case of regular termination” (#1490). What people actually hit were leak classes on abnormal exits, each since fixed: the pre-stdio project scan blind to client death (#1685), and a per-session zombie child (#1488). Upgrade first; the one still-open case is Scala’s Bloop daemon surviving session kills (#1816). If you still see orphans, report the exact spawn-and-kill circumstances — “it ate my RAM” alone is not actionable.
Java via Eclipse JDT-LS keeps failing. What is the recommended setup?#
JDT-LS is the most fragile backend Serena wraps — “It’s a fickle beast”
(#1174): slow first start, ~500 MB of
first-activation downloads, a bundled JRE that can mismatch newer source levels, and
corruptible workspace metadata whose real error hides in .metadata/.log. The maintainers’
standing recommendation: “I would highly recommend using Serena through the JetBrains
plugin for Java and similar languages. All such issues and many other then disappear”
(#1469). Failing that, upgrade — many
JDT-LS fixes landed on main.
How does the JetBrains plugin relate to all this?#
It is Serena’s paid, more capable backend — “the Jetbrains symbol indexing is more powerful
than the LSP variant… the small fee for the plugin is so far the only way for us to get
some income from Serena” (D903). You
still register Serena as an MCP server, selecting the backend with
--language-backend JetBrains or in serena_config.yml (per-project override exists too,
#1031). Each new IDE release needs a new
marketplace build — approval ranges from hours to about a week, slower around holidays
(#856); interim builds are on the
maintainers’ release page (#1032). Rider is
not supported (“Supporting it would effectively double all implementation efforts”,
#964 — though they may reconsider). And as
of early 2026, JetBrains’ built-in Claude Agent could not be given MCP servers at all — a
JetBrains-side limitation (D1045).
Should I install Serena through Anthropic’s official Claude Code plugin?#
No — configure it directly as an MCP server per Serena’s docs. The maintainers’ words: “The plugin does not add anything extra… There’s no point in using the plugin” (#910); “There are 0 benefits to installing it as a Claude code plugin” (#961). The wrapper lags the launch command, and Oraios cannot fix it — their PR to the plugin registry was auto-closed because it accepts no outside contributions (D877). It also has nothing to do with Serena’s own JetBrains plugin, whatever the similar names suggest.
Do I need to re-run indexing to keep the cache fresh? Should .serena/cache be committed?#
No and no. “The cache is always updated when file content changes… information from the
cache is never stale” (D678) — so
serena project index is a startup-speed optimization for large repos, never a freshness
requirement (the one gap: the cache is not pruned, so it grows). The transient parts are
git-ignored automatically since #283, and a
maintainer’s own habit is ignoring the whole of .serena, force-adding memories when
needed (D362). The contrast worth
remembering: the cache maintains itself; your memories do not.
Have a question this page should carry? Ask it on the tracker — that is where every entry above came from.