Skip to content

Repository files navigation

Limitless

A Home Manager module for a ready-to-use OpenCode 2 workspace.

Limitless pins OpenCode 2.0.19, supplies coding agents and local code-intelligence tools, and configures optional first-party MCP connections. OpenCode owns its service discovery, OAuth credentials, Code Mode, browser integration, and native notification delivery. Home Manager owns packages and non-secret configuration, with optional Linux service supervision.

Use it

{
  inputs.limitless.url = "github:your-org/limitless";

  outputs = { home-manager, limitless, ... }: {
    homeConfigurations.me = home-manager.lib.homeManagerConfiguration {
      modules = [
        limitless.homeModules.default
        { programs.limitless.enable = true; }
      ];
    };
  };
}

Run opencode, or its oc shell alias, from a project. It discovers or starts its native background service. Connect model providers through /connect.

Native browser tools are allowed for all agents. They require the OpenCode desktop app's attached browser and fail in TUI-only sessions.

Included capabilities

  • Agents: limitless and solo, a research subagent, and technical and design Oracle advisers.
  • Code intelligence: ast-grep search and replacement, TypeScript/Biome diagnostics, and seven LSP tools for definitions, hover, implementations, call hierarchy, references, symbols, and rename previews.
  • Language servers: TypeScript, Biome, JSON, YAML, Markdown, TOML, and Nix.
  • Artifacts: project-scoped folders under .limitless/artifacts/.
  • Source research: optional guarded GitHub checkouts under .limitless/repos/.
  • Service integrations: optional Atlassian, Notion, Sentry, Linear, and GitHub MCP presets with account-specific connection names and audited reads for support agents.
  • Anthropic subscription authentication: a pinned Claude Pro/Max plugin.
  • Git hygiene: .limitless/ is globally ignored by default.
  • Desktop app: optional OpenCode Desktop on Linux, sharing the Limitless runtime.

The plugin exposes 13 core tools directly with codemode = false. MCP tools use OpenCode's native Code Mode. Every Limitless tool resolves the invoking session's location.directory as its project root.

MCP connections

Each entry names one connection. Enable only the services you use:

programs.limitless.mcp.servers = {
  atlassian.preset = "atlassian";
  notion-work.preset = "notion";
  notion-personal.preset = "notion";
  sentry.preset = "sentry";
  linear.preset = "linear";
};

After applying Home Manager, run /mcps, select each connection, and sign in. Connections are ready only when OpenCode reports them as connected. Notion work and personal entries have separate OAuth identities even though their URLs match; authorize the intended workspace for each. Renaming a connection creates a new credential identity. Token refresh and OAuth state belong to OpenCode.

settings overlays the preset using native OpenCode V2 server fields. For example:

programs.limitless.mcp.servers.sentry = {
  preset = "sentry";
  settings.timeout.execution = 120000;
};

Set settings.disabled = true to retain a configured connection without connecting it. Additional servers can use programs.limitless.opencode.settings.mcp.servers. Use one configuration path per server name. Native-only servers receive the same role-based permissions, with no automatic read exceptions for support agents.

GitHub authentication

The hosted GitHub server requires an explicitly configured registered OAuth client or a PAT. Generic OAuth discovery alone is insufficient. For a registered client:

programs.limitless.mcp.servers.gh = {
  preset = "github";
  settings.oauth.client_id = "{env:GITHUB_MCP_CLIENT_ID}";
};

Include the native oauth.client_secret and callback settings when required by your registered application. Alternatively, supply a PAT through the OpenCode process environment:

programs.limitless.mcp.servers.gh = {
  preset = "github";
  settings = {
    oauth = false;
    headers.Authorization = "Bearer {env:GITHUB_MCP_TOKEN}";
  };
};

Keep token values out of Nix expressions and generated files. Ensure the credential is available to the background service; exporting a variable in a new terminal does not change an already-running service's environment. The preset enables context, repository, issue, pull-request, and Actions toolsets. GitHub MCP authentication is separate from Git clone/fetch/push credentials and the guarded research clone configuration below. Limitless does not install gh.

Use gh or github-mcp as the connection name. The name github overlaps the local github_clone tool. The module rejects overlapping tool namespaces and account prefixes such as notion plus notion_work; use notion-work instead.

Permissions and coverage

Tool access follows the agent's role:

Agents Access
limitless, solo Automatic approval for reads, writes, shell commands, and all MCP tools
research, oracle-solve, oracle-design Read, shell, edit, and AST tools for investigations and focused diagnostic changes; audited MCP reads; deny artifact creation and session changes

For each configured MCP server, support agents receive a deny rule followed by exact exceptions for audited read tools. Unknown tools, mutations, and mixed-purpose executors are unavailable to support agents. Read tools such as web fetch and artifact listing inherit the global allow rule.

Sensitive-file reads and potentially destructive shell commands no longer have default approval prompts. Shared instructions still require explicit user direction for destructive work. Managed-checkout edits remain denied.

readTools replaces a preset's exact read-tool list for support agents. Add names only after checking their behavior and the authenticated catalog. Wildcards are rejected. The optional https://mcp.linear.app/mcp/readonly endpoint can further restrict a Linear connection at the server. Linear's read-tool list is empty until verified names from an authenticated catalog are configured.

These rules control named-tool access. Shell commands can write files or call services, and Code Mode's raw HTTP fetch can send write requests. Support-agent instructions reserve implementation and external mutations for the primary agent; the tool permissions do not provide a sandbox. Later project configuration or agent definitions can override global permissions. Project-local MCP additions need their own permission rules. A configured server must be trusted to implement its advertised read operations correctly.

Preset Daily workflows Coverage limits
Atlassian Jira and Confluence search, reads, edits, comments, transitions Organization policies and enabled tool groups determine access. Uses the v2 flat catalog.
Notion Pages, databases, comments, queries, uploads Workers deployment and generic API administration are outside this preset. Tools can depend on plan.
Sentry Issues, events, traces, debugging Release/symbol uploads and broad administration require dedicated tooling. Mixed-purpose catalog execution is unavailable to support agents.
Linear Issues, projects, comments Exact read exceptions require authenticated discovery.
GitHub Repositories, issues, PRs, reviews, Actions Local Git and release uploads require separate tooling and authentication.

Before relying on a new connection, verify account identity, a representative read, an explicitly requested write, mutation denial in support agents, and token refresh. The repository checks generated configuration and policy behavior; account entitlements and live upstream tool catalogs require this authenticated verification.

Configuration and layout

nix/modules/
├── home.nix       # composition and Git hygiene
├── opencode.nix   # runtime, agents, plugins, and configuration assembly
├── desktop.nix    # optional OpenCode Desktop on the same runtime
├── service.nix    # optional Linux supervision and native service binding
├── lsp.nix        # language-server packages and plugin configuration
└── mcp.nix        # named connections and permission generation
nix/mcp-presets.nix # first-party endpoints and audited read-tool names
opencode/          # native defaults, agents, and shared instructions
packages/limitless/ # code-intelligence tools, artifacts, source research, policies

Native server settings go in programs.limitless.opencode.settings. Limitless enforces the default agent, managed plugins, ordered permissions, generated MCP policies, and the managed-checkout edit denial. opencode.extraAgentsFile appends additional instructions. opencode.disableClaudeCode = true wraps the executable with OPENCODE_DISABLE_CLAUDE_CODE=1.

Native terminal settings go in programs.limitless.opencode.cliSettings. The launcher supplies them through OPENCODE_CLI_CONFIG_CONTENT; declared values override matching preferences in ~/.config/opencode/cli.json. An explicitly supplied OPENCODE_CLI_CONFIG_CONTENT replaces the generated override. Apply Home Manager and relaunch the TUI after changing these Nix settings.

Configure language servers through programs.limitless.lsp: enable, servers.<name>.{enable,package,command,args,extensions,env}, extraServers, and extraPackages. Limitless owns these definitions in plugin options.lsp. Project-local OpenCode lsp settings do not change Limitless's tools.

skills.package can supply your own skill directories; skills.enable = false disables installation. The default package copies a top-level skills/ directory when present and is otherwise empty. OpenCode's built-in skills remain available.

Agents and models

limitless defaults to openai/gpt-6.1-sol-fast#max; solo defaults to openai/gpt-6-astra#xhigh. The main model remains independently selectable. solo denies delegation. OpenCode remembers a model per primary agent.

Research uses openai/gpt-6.1-sol-fast#max; Oracle Solve uses openai/gpt-6-astra#max; Oracle Design uses anthropic/claude-opus-5-5#xhigh. Subagents keep the processing tier of their configured model.

Limitless owns implementation, integration, and final validation. Research owns focused investigations: explaining behavior, diagnosing complex bugs, testing hypotheses, and proposing complete solutions. Oracle Solve provides independent technical judgment when evidence conflicts, an investigation stalls, correctness is uncertain, or the consequences warrant deeper scrutiny. Oracle Design advises on consequential architecture, interfaces, ownership, and maintainability. Research can resolve a question without an Oracle consultation; either Oracle can be consulted directly when its judgment is needed.

All support agents can run tests and make focused diagnostic edits directly in the shared workspace, including reproduction tests, fixtures, and temporary instrumentation. They report changed files, their purpose, commands, results, and material interference. Limitless reviews the diagnostic changes and decides what to retain or remove; automatic cleanup is not required. Limitless waits when work could conflict or an investigation gates the next change, and otherwise works on independent tasks. All agents account for shared files, services, and test resources and preserve concurrent work. Diagnostic scope and implementation ownership are instruction-level policies; edit permissions cannot distinguish those purposes.

Astra, Sol 6.1, and their Fast modes use conservative client budgets of 872,000 context tokens and 828,400 input tokens, overriding OpenCode's 400K subscription default. These derive from the Codex catalog's override ceiling with 5% input headroom. These budgets have not been verified against the subscription backend. With OpenCode's default 10% compaction buffer, automatic compaction starts at approximately 745,560 input tokens. Reasoning variants, Fast mode, and output limits come from the upstream catalog.

OpenAI models use native provider compaction for automatic and manual requests by default. Configure providers.openai.settings.compaction.type through opencode.settings; individual model settings can override the provider policy.

providers.disabled defaults to [ "google-vertex" "google-vertex-anthropic" ] to avoid ambient Vertex selection.

Anthropic subscription authentication

Run /connect, select Anthropic, and choose Claude Pro/Max. The plugin is pinned to ex-machina-co/opencode-anthropic-auth release v2.0.0-next.3, commit e03f023c8ea1771a829cee51024b8675ffede24c. API-key authentication retains standard Anthropic request behavior.

Warning

Anthropic does not officially support using Claude Pro/Max through OpenCode. This compatibility path may violate its terms or put an account at risk. Disable it with programs.limitless.plugins.anthropicAuth.enable = false.

Connecting Max replaces the saved Anthropic API-key credential and vice versa. Credentials from the earlier experimental Limitless plugin require signing in again. OpenCode continues to display API prices for subscription models. The upstream plugin targets SDK 2.0.4 and reports Claude Code compatibility version 2.1.280. When Anthropic returns a structured newer-version requirement, it adopts that exact minimum and permits one retry for the affected session, agent, and model. Ordinary errors and rate limits do not trigger this recovery.

An optional override is available when an explicit version is required:

programs.limitless.plugins.anthropicAuth.claudeCodeVersion = "2.1.280";

The option defaults to null, preserving the bundled version and automatic recovery. Setting a version supplies ANTHROPIC_CLAUDE_CODE_VERSION to both managed and on-demand OpenCode servers and disables automatic version adoption. An explicit environment value takes precedence. The plugin reads it at startup and uses it for both the user-agent and billing metadata; apply Home Manager and restart the OpenCode server after changing it. This setting controls the plugin's reported compatibility version, independently of any installed Claude Code executable.

Refresh rotation is deduplicated within a process. ANTHROPIC_BASE_URL can override the endpoint; ANTHROPIC_INSECURE cannot disable TLS verification.

Guarded source research

programs.limitless.github = {
  enable = true;
  allowedRepos = [ "owner/repo" ];
  tokenFile = "/run/agenix/github-read-token";
};

Without tokenFile, the tool reads tokenEnv, which defaults to GITHUB_TOKEN. Use a fine-grained read-only token for private repositories. The token is passed to Git through ephemeral github.com-scoped environment configuration and never written to URLs, arguments, tool results, or repository configuration.

allowedRepos must be nonempty unless allowUnrestrictedRepos = true. The policy also covers every transitive submodule; non-GitHub hosts are rejected. Clones are depth-one, project-local snapshots. Default-branch requests refresh immediately; explicit branches, tags, and SHAs use distinct deterministic paths. Dirty checkouts are never overwritten. New clones are staged and published atomically. LFS objects are not materialized.

Managed repositories are read-only supporting source. The edit policy denies normal writes below .limitless/repos/; shell access is not sandboxed. Set git.ignoreStorage = false if the repository should manage .limitless/ itself.

Artifacts

artifact_create creates a project-local folder under .limitless/artifacts/ with a manifest recording its slug, optional title, timestamp, and creating session. Use normal file tools to add notes, source, assets, or generated outputs. artifact_list reports valid artifacts and folders with invalid/missing manifests. Explicit duplicate slugs fail; generated slugs include a random suffix. Failed creation cleans up only its own incomplete manifest and empty folder.

Native service and Tailscale

OpenCode starts its native background service on demand by default. Use opencode service status and opencode service restart to inspect and manage it.

For automatic startup at user login and process supervision on Linux, enable the Home Manager systemd user service:

programs.limitless.opencode.service = {
  enable = true;
  hostname = "127.0.0.1";
  port = 4096;
};

hostname defaults to 127.0.0.1; port defaults to OpenCode's native 49374. Declare 4096 explicitly to retain an existing Tailscale proxy target:

Tailscale HTTPS → 127.0.0.1:4096 → OpenCode

Reuse the declared port in your proxy configuration. The listener stays on loopback, and OpenCode's native authentication still applies through the proxy.

The service persists hostname and port through native opencode service commands when they differ, stops any existing native daemon, then runs serve --service in the foreground. It preserves the private password, CORS configuration, and configured service environment. Private service files remain writable and outside the Nix store. Disabling supervision leaves the last persisted binding in place.

Enabling, starting, or restarting this unit can interrupt active work and persistent terminals. The unit takes ownership of the shared native daemon. While enabled, use systemd for lifecycle commands:

systemctl --user status opencode
systemctl --user restart opencode
systemctl --user stop opencode

opencode service stop is normally undone by supervision. A local OpenCode client can still start a native daemon after the unit is stopped. Keep local clients on the configured OpenCode version; clients that replace the daemon with another version can conflict with supervision. Restarting a failed process is automatic; this unit does not detect a live but unhealthy process.

Home Manager applies changed units automatically when systemd.user.startServices is enabled. Changes to the runtime, binding, configuration, agents, or installed skills trigger a restart. With service switching disabled, apply the suggested systemd commands yourself.

The unit starts with the systemd user manager, normally at login. Boot startup is optional: user lingering starts that manager before login and keeps it running after logout. To opt in, set this in your NixOS system configuration:

users.users."your-user".linger = true;

On other systemd distributions, an administrator can enable lingering with loginctl enable-linger <your-user>. Tailscale's proxy must also start at boot.

Desktop app

On Linux, install OpenCode Desktop alongside the CLI:

programs.limitless.desktop.enable = true;

The desktop package is pinned to the same 2.0.19 release as the CLI. It connects to the running native service, including the supervised unit, and otherwise starts one with the Limitless-configured opencode executable in place of its bundled CLI. Desktop sessions therefore use the same configuration, plugins, agents, and launcher environment as the TUI. The desktop replaces any background service with a different version, so the module rejects an opencode.package of another version. Upgrade both pins together.

The app runs from the Nix store; its built-in updater stays inactive. Update it by updating Limitless.

Notifications and browser

Limitless enables sound by default and supplies a TUI handler that dings for:

  • A newly completed final assistant response in a top-level session.
  • A permission request.
  • A question or other input prompt.

Completion requires successful execution, a normally finished answer, and an empty inbox. Child completion, errors, interruptions, and compaction-only runs are silent. A later background result can resume the main session and produce another response. The handler uses OpenCode's native sound playback and preserves visual notifications and error toasts. Configure sound, volume, and visual notifications through the native CLI settings:

programs.limitless.opencode.cliSettings.attention = {
  sound = true;
  volume = 0.4;
  notifications = true;
};

Set opencode.cliSettings.attention.sound = false to disable the ding. Sound and visual notifications are independent; visual notifications normally appear when the terminal is unfocused. Preferences omitted from cliSettings can be changed through the TUI and stored in ~/.config/opencode/cli.json.

The package's ./tui entry replaces the pinned built-in opencode.notifications handler by ID. Existing -opencode.notifications directives also disable this handler. OpenCode loads the TUI entry automatically from the Limitless plugin.

Native browser tools require the session to be open in the desktop app with the experimental browser setting enabled. A TUI-only session has no attached browser.

Prompt-cache status

A dot in the prompt footer estimates whether the provider still holds the session's prompt cache:

Color Meaning
Green A request is running, or the latest reply finished within the cache lifetime.
Red The cache lifetime has elapsed since the latest reply; the next request likely rewrites it.
Gray The provider's cache lifetime is unknown.

Lifetimes are 5 minutes for anthropic (OpenCode sends only 5-minute cache breakpoints) and 30 minutes for openai (GPT-5.6 and later guarantee at least 30 minutes). The dot is a timer estimate: warming requests are invisible to the TUI, and providers can evict early.

The plugin is TUI-only and ships as Solid source that OpenCode compiles at load. Home Manager links it into ~/.config/opencode/plugins/limitless-cache-status. Disable it with programs.limitless.plugins.limitless.cacheStatus.enable = false.

Migration from the previous Limitless layout

This release removes these options and packages:

Removed Migration
slack.*, Gary, Slack tools Remove Slack configuration and retire its bot credentials when no longer used.
tools.agentBrowser.*, agent-browser package/skill Use OpenCode's desktop-backed browser when needed.
tools.acli.*, Atlassian CLI skill Add an atlassian MCP connection and authorize it.
tools.notion.*, notion-cli package/skill Add separately named notion MCP connections for each workspace.
tools.sentry.*, sentry package/skill Add a sentry MCP connection. Install specialized release tooling separately if required.
mcp.linear.enable Set mcp.servers.linear.preset = "linear" and sign in through /mcps.
notifications.* Use opencode.cliSettings.attention; sound defaults to enabled, and visual notifications are configured independently. Arbitrary command hooks are retired.
opencode.service.alias and its attach alias Use native OpenCode service discovery. Optional Linux supervision uses opencode.service.{enable,hostname,port}.
limitless-fast agent, agents.fastSubagents Use limitless. Select a -fast model alias to request Fast processing for a session.

If migrating from the old systemd service, remove opencode.service.alias and declare port = 4096 to preserve its old default. Applying the generation with supervision enabled replaces the old unit and takes over any native daemon. If using native on-demand startup instead, disable the unit before launching OpenCode. Do not keep a separate OpenCode supervisor alongside this unit. Applying these settings is a Home Manager operation; repository checks use isolated fixtures.

For an existing Linear API key, the connection's native settings can explicitly set oauth = false and headers.Authorization = "Bearer {env:LINEAR_API_KEY}". Default connections use OAuth. Former CLI token files are not imported into MCP authentication; authorize and verify each new connection before retiring tokens.

OpenCode 1 sessions are not migrated. Back up OpenCode state and record your flake revision before switching major versions. Rollback requires the matching runtime and state backup; never run V1 and V2 against the same writable state directory.

Development

Use nix develop, then bun install --frozen-lockfile and bun run ci. The gate runs formatting/lint checks, TypeScript, tests, module checks, and all six package builds. The suite covers Limitless-owned behavior: tool safety and lifecycle, role permission outcomes, MCP namespace collisions, launcher environment handling, and native service supervision. It leaves configuration values and upstream packages to their owners.

Runtime, desktop app, Limitless plugin SDK, and schema are pinned to 2.0.19, with effect@4.0.0-rc.112; update them together. The cache-status plugin's type-only dev dependencies (@opencode/theme, @opentui/*, solid-js) follow the same OpenCode release. Re-audit native capabilities and MCP read exceptions when upgrading. Vendor references for the current allowlists are linked in the integration table above.

The desktop package patches the minified main process so the app runs its CLI in place instead of copying it into its data directory; the build fails if that code changes. Its install check verifies the CLI version and native terminal module.

When upgrading OpenCode, verify that the TUI still replaces a built-in handler with a later external definition of the same ID, that the built-in notifications ID is still opencode.notifications, and that execution events still project matching idle-message boundaries. The sound filter depends on these pinned behaviors.

About

An opinionated OpenCode setup powered by Nix.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages