Documentation
¶
Overview ¶
Package setup connects logos to the agents that will use it.
The engine has never been the hard part of adopting this. The hard part is the nine steps between cloning the repo and an agent actually answering from your vault — install a runtime, pull models, choose a vault, index it, find the right config file for your host, and hand-write JSON full of absolute paths. Every one of those is a place to give up, and none of them is the part worth having.
So this package does the wiring. It finds the MCP hosts installed on the machine and registers logos with each one, preferring the host's own registration command where there is one and merging its config file where there is not.
Why the host's CLI comes first ¶
Claude Code and Codex both ship a command for this. Using it means their config format stays their problem: when they change it, their command changes with it and logos keeps working. Hand-writing another application's config is a standing bet that its format will not move, and that bet is only worth taking when there is no alternative — which is the case for Claude Desktop and Cursor — or when the CLI would register at the wrong scope or cannot be exercised by a test, which is why Cline, Devin and GitHub Copilot are merged.
Where a file does have to be written, it is read, merged, backed up and then replaced atomically. Someone's other MCP servers are not ours to lose.
Index ¶
Constants ¶
const Name = "logos"
Name is what logos calls itself in a host's server list.
const OldName = "brain"
OldName is what 0.4 setup registered the server as. Setup replaces such an entry through 0.4.x; this goes before 0.5.0.
Variables ¶
This section is empty.
Functions ¶
func LogosPlugin ¶
LogosPlugin reports whether the Logos plugin is installed in Claude Code, and at which version. The plugin carries its own MCP server, so registering logos with `claude mcp add` on top of it lists every tool twice and pays the per-session cost twice. Claude Code records installed plugins in this file, keyed "<plugin>@<marketplace>".
func RenderConfig ¶
RenderConfig renders the server block a host's config needs, in the requested format, for printing rather than writing. It exists for the same reason MergeFile does: a host logos does not know how to find can still be wired, by hand, if the user can see what a working entry looks like. An empty format means json — the shape most MCP hosts actually use, and the one this package already writes for Claude Desktop and Cursor.
Types ¶
type Host ¶
type Host struct {
Name string
// Detect reports whether this host is installed. Presence-based: a command
// on PATH, or a config directory that exists. A host nobody has installed
// is skipped, never failed — "not installed" is not an error.
Detect func() bool
// Where is the config path or command shown in the report.
Where func() string
// Config is the file this host's registration rewrites, so it can be
// backed up first. Empty means the file does not exist yet or logos does
// not know where it lives — a host registered through its own CLI still
// rewrites a file, and knowing which one is the only way back from a wrong
// --vault.
Config func() string
// Register points the host at this server.
Register func(Server) (Outcome, error)
// List reports every MCP server this host currently has registered, read
// back rather than assumed. Nil means this host exposes no way to read
// that back — not an error, just a question this host cannot answer.
List func() ([]Registration, error)
// RemoveOld removes the entry 0.4 setup registered under OldName, and
// reports whether there was one. Nil for a host 0.4 never wired.
RemoveOld func() (bool, error)
}
A Host is one application that can talk to an MCP server.
func Hosts ¶
func Hosts() []Host
Hosts returns every MCP host logos knows how to connect to, in the order they are reported.
Each entry is a promise to keep working as somebody else's application changes, so a host is added when people ask for it, not speculatively. Aider is not here because it has no MCP client to register with; `logos setup --print-config` is the answer for a client that is not on the list.
type Outcome ¶
type Outcome string
Outcome says what happened to one host.
const ( // Registered means the host now points at this logos. Registered Outcome = "registered" // Updated means it already had a logos entry and it was replaced. Updated Outcome = "updated" // Unchanged means the host was already pointed at exactly this logos, so // the registration rewrote its config with the bytes already in it. Setup // is run more than once — after moving a vault, after an update, or just to // check — and calling that "updated" reports work that did not happen. Unchanged Outcome = "already connected" // Skipped means the host is not installed here. Skipped Outcome = "not installed" // Failed means it is installed and something went wrong. Failed Outcome = "failed" // Pending means the host is installed and would be wired. Only Plan produces // it — it is what the user is being asked to approve. Pending Outcome = "would wire" )
func MergeFile ¶
MergeFile is mergeJSON, exported for `logos setup --config <path>` — a host whose location on disk logos has no convention for, but whose file is the same mcpServers-keyed JSON that Claude Desktop and Cursor already read. The internal hosts in Hosts() are a closed, curated list on purpose (see the package doc); this is the escape hatch for every MCP client that is not on it, so that "not one of the four we special-case" does not mean "logos cannot help you connect this".
type Registration ¶
Registration is one server as a host currently reports it — the name it was given and the command line the host will actually run.
type Result ¶
type Result struct {
Host string
Outcome Outcome
Where string // config path or command, for the report
// Backup is the copy of this host's config taken before it was changed,
// empty when there was nothing to copy. Reported, because a backup nobody
// is told about is a backup nobody uses.
Backup string
// CommentsOnlyInBackup is set when the original config had comments.
// Writing it back as JSON drops them, and the backup is the one place
// they still exist.
CommentsOnlyInBackup bool
Err error
// Replaced is set when the entry 0.4 setup wrote under OldName was
// removed, and ReplaceErr when that was tried and failed. Neither fails the
// host: logos is registered either way, and the leftover is reported.
Replaced bool
ReplaceErr error
}
A Result is one host's line in the report.
func Install ¶
Install registers the server with every host that is present.
One host failing does not stop the others: a user with a broken Cursor config still wants Claude wired up, and the report tells them which is which.
func Plan ¶
Plan reports what Install would do, without doing any of it.
Registering logos with every AI tool on someone's machine is a large action for someone evaluating one integration, and it used to happen with no gate at all — not even --yes. Showing the list first costs one function and turns an imposition into a choice.
It does not distinguish "would register" from "would update": finding that out means reading a config the user has not yet agreed to have touched, and for the CLI-based hosts it means asking their command, which is not free. Pending is the honest answer to "what will happen here".
type Server ¶
type Server struct {
// Bin is the absolute path to the logos binary. Absolute because a host
// launches it from a working directory nobody chose.
Bin string
Args []string
// Env is what the host must set. LOGOS_VAULT belongs here and must be
// absolute for the same reason Bin is.
Env map[string]string
}
A Server is the command a host should run to reach this logos.