npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@lmctl-ai/lmctl

v0.1.273

Published

A provider-agnostic control plane for teams of AI coding agents — across providers, with independent review and durable memory.

Downloads

12,723

Readme

lmctl

A provider-agnostic control plane for teams of AI coding agents.

Homepage · Documentation · Changelog

AI agents shouldn't be locked to one provider or one context window. lmctl is a local-first control plane for running teams of AI coding agents — across providers, with adversarial cross-provider review and durable memory, composed in plain text. It coordinates the agent CLIs you already use (Claude, Codex, Gemini, and more); it's not an IDE and not another chatbot.

Two things set it apart from how "multi-agent" and "AI review" usually work:

  • Review is adversarial, not self-review. The reviewer is a different provider and model from the author — a Claude lead hands coding to Codex and has Gemini review it — so a model's blind spots aren't rubber-stamped by itself in a different hat. Different models have different (uncorrelated) blind spots; that model diversity is the point — a varied team catches what one model, or its clones, can't.
  • You build and tune the team — the provider doesn't. Most "multi-agent" tools have one provider auto-spawn agents you can't steer. In lmctl you divide the work, compose the team in plain text, pick the provider and model for each role, and tune how they interact.
  • Any model, local or remote — any mix in one team. Alongside the major CLIs, the OpenCode provider reaches any model: local (Ollama) or remote (DeepSeek, Qwen, OpenRouter, Copilot's GPT/Claude/Gemini, and more). Put any collection of them in a single team, working together — not one model at a time.

Public preview. Free to use during the preview. Closed-source, proprietary software distributed in binary form — see the License.

Install

npm install -g @lmctl-ai/lmctl

Usage

lmctl --help
lmctl status
lmctl plan ./my-project
lmctl lint ./my-project/my-project.lmctl
lmctl seed ./my-project/my-project.lmctl
lmctl chat ./my-project/my-project.lmctl Lead "Inspect the repo and propose next steps."
lmctl mail sent --json
lmctl mail sent --limit 100 --cursor "$NEXT_CURSOR" --json

lmctl status is team/SELF-scoped: from a member session it shows your identity, team roster busy/idle state, and recent activity in both directions. From a plain operator shell it shows a DB-wide summary. Use lmctl status --json for the full machine-readable view; --project and --web are not status flags.

Start with the plan -> lint -> seed -> chat flow. lmctl does not manage foreground vs. background execution for provider turns or shell commands; use the provider or host runtime's own background/task surface when you need async execution. Daemon, web, and API surfaces are secondary integration paths; the CLI is the golden path for onboarding. To inspect the daemon, run lmctl api daemon state while lmctl serve is running; authenticate with LMCTL_API_TOKEN=<token> or start local serve with --insecure-no-auth. Lintable teamfile templates for research, writing, and review teams ship in the examples gallery.

lmctl top-level subcommands are: api, chat, serve, device, team, terminal, tail, health, session, session-index, restore, restore-teamfile, ls, lint, seed, hire, refresh, clone, plan, diagnose, diagnose-prompt, mail, status, running, and db. Run lmctl <command> --help for details on each, and see the documentation to define your first team.

Abstract managed-team providers retain the config keys workspace.provider1, workspace.provider2, and workspace.provider3. Set their concrete provider names directly in ~/.lmctl/state.db; the key names remain stable for compatibility:

sqlite3 ~/.lmctl/state.db "INSERT OR REPLACE INTO lmctl_config(key,value,updated_at) VALUES('workspace.provider1','claude',strftime('%Y-%m-%dT%H:%M:%fZ','now'));"
sqlite3 ~/.lmctl/state.db "INSERT OR REPLACE INTO lmctl_config(key,value,updated_at) VALUES('workspace.provider2','codex',strftime('%Y-%m-%dT%H:%M:%fZ','now'));"
sqlite3 ~/.lmctl/state.db "INSERT OR REPLACE INTO lmctl_config(key,value,updated_at) VALUES('workspace.provider3','gemini',strftime('%Y-%m-%dT%H:%M:%fZ','now'));"

lmctl mail exposes low-level, read-only/record-only primitives over the event-log substrate: list pending or sent messages, read event history/ content, inspect historical provider evidence and causal lineage, and declare handling/acknowledgement. mail pending defaults to messages addressed to SELF when run from a member session; an explicit --receiver overrides that scope. From a plain operator shell with no SELF marker, it retains the fleet-wide discovery view. Missing causal capture is shown as an explicit tree root rather than guessed from timestamps. For every mail subcommand, --json is the stable external contract and includes schema_version: 1; default text output is for humans and may change. JSON failures use {status:"error", errorKind, message}. The unbounded sent and tree scans are cursor-paginated, with 100 results by default and 1,000 maximum; pass next_cursor back through --cursor until it is null. schema_version is the authoritative output-contract version; the separate schema: "event-log-v1" field identifies the backing substrate.

Stable top-level success fields are:

  • sent: schema_version, schema, identity, filters, messages, next_cursor.

  • history: schema_version, schema, message_id, events.

  • seen: schema_version, schema, message_id, receiver, db, transcript, answered.

  • pending: schema_version, schema, filters, messages.

  • read: schema_version, schema, message_id, message_type, in_reply_to, sender, receiver, content, pending_state.

  • deliver: schema_version, schema, message_id, message_type, receiver, outcome, provider_status, message.

  • handle: schema_version, schema, message_id, handling_by, handling_at, appended.

  • ack: schema_version, schema, message_id, acked_by, appended, pending_outcome.

  • tree: schema_version, schema, root, since, since_timestamp, sent, next_cursor, orphan_policy, incomplete_capture_note.

  • lmctl chat <teamfile> <alias> "message" drives or messages a member. If a member-origin target is busy, chat queues the message for that sender->receiver lane; the next chat from that same sender to that receiver, when it is free, delivers the queued lane plus the new message. The lane key is (sender, receiver): a chat to that receiver from anyone else does not flush your queued mail. If you go idle waiting for the reply you queued, nothing else will unblock it — you are the only party whose next chat flushes that lane.

Model selection

Teamfiles can pin provider models with _MEMBER_ ... model=<id>. For provider=opencode, GitHub Copilot reasoning variants can also be selected with effort=<variant>, for example:

_MEMBER_ alias=Reviewer provider=opencode model=github-copilot/gpt-5.4 effort=xhigh sessiondir=/repo

If ~/.config/opencode/opencode.json is missing, lmctl lint warns and points to this sample config. Copy it into your opencode config location and adjust it for the models your account can access.

Requirements

  • Node.js >= 24.15.0. lmctl uses built-in node:sqlite, so installation has no native SQLite build step.

Links

License

Proprietary — free during the public preview, © Lattice Systems LLC, all rights reserved. Not licensed for redistribution or modification. Provided as-is, without warranty. See the full License.