Skip to content

edobry/minsky

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15,544 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Minsky — The cyberbrain for software organizations.

Minsky

An exocortex for software organizations led by a principal — the substrate that holds the cognition of one mind across a flock of agents, and translates declared intent into coordinated realized work.

"The power of intelligence stems from our vast diversity, not from any single, perfect principle." — Marvin Minsky, The Society of Mind

The principal — the human responsible for the work — declares intent; the substrate composes hooks, sessions, tasks, asks, memory, and reviewer agents to drive that intent to realization. Principality is recursive: every individual engineer running Minsky is the principal of their own flock, and an organization is a tree of principals all the way down to the ICs. Minsky is principal substrate at every level on that tree.

Minsky is a substrate, not an operator: it doesn't write or judge the work — it composes the environment agents and engineers already run inside, so the right practice is the only path through, not a request an agent could decline. Environmental alignment is the mechanism, not instruction: the same pre-commit hook that blocks an unformatted commit from a human blocks one from an agent, with no separate AI configuration to maintain.

The theory behind that mechanism — the control-system mapping the substrate follows, the attention-as-scarce-resource argument, the humility and noticing properties a substrate needs — is written up, not just implemented; the architecture underneath it is documented the same way.

Theory: docs/theory-of-operation.md — Architecture index: docs/architecture.md

What Minsky does

Task management with multiple backends

Coordinate work items across different storage systems:

# Minsky database (default)
minsky init --tasks-backend minsky

# GitHub Issues for open source projects
minsky init --tasks-backend github-issues

Session-based development

Isolated workspaces that prevent conflicts and enable parallel work:

# Start an isolated session for a task
minsky session start --task mt#123

# Work in the isolated environment
cd $(minsky session dir mt#123)

# Create a PR when ready
minsky session pr create --title "Fix critical bug" --type fix

Unified CLI and MCP surfaces

Minsky exposes all commands as both CLI and MCP tools, so AI agents interact with the same surface as human developers. There is no separate AI API — the same session start, tasks create, and session pr create commands work whether a human is typing them in a terminal or an agent is calling them via MCP.

Why Minsky?

Not a code review bot

Tools like CodeRabbit, GitHub Copilot Review, and Greptile operate at PR time — they review code after it is written. Minsky audits the development environment: the hooks, gates, and workflows that shape how code gets written in the first place. By the time code reaches a PR, Minsky's quality gates have already run many times.

Not a task tracker

Minsky is the coordination substrate that makes your existing tools work as a coherent system. Your linter, test runner, and CI pipeline already exist — Minsky configures them to run at the right moments and surfaces their results in a consistent format. It does not replace them.

Alignment through environment, not instruction

The core design principle: the same pre-commit hook that blocks a human developer from committing unformatted code blocks an AI agent too. No special AI configuration is needed. The environment enforces the constraints uniformly.

This is the difference between instruction-based alignment ("tell the AI to write clean code") and environmental alignment ("make unformatted code impossible to commit"). Minsky implements the latter.

Self-hosted and provider-agnostic

Minsky runs on your infrastructure, in your git repository. It integrates with Anthropic, OpenAI, and Google models via the Vercel AI SDK (@ai-sdk/anthropic, @ai-sdk/openai, @ai-sdk/google) — you choose the provider. This contrasts with hosted agent platforms (e.g., Claude Managed Agents) which are cloud-only, single-provider, and designed for async business tasks rather than development workflows.

Git-native

Sessions are isolated git clones. Changesets are branches. Pull requests are the integration mechanism. There is no proprietary state format — everything lives in git and is inspectable with standard tools.

Attention as the scarce resource

Underneath every mechanism above sits a scarcer resource than CPU or storage: principal attention. A pre-commit hook catching unformatted code, a session starting from a clean git clone, a BLOCKED task surfaced in review — each one routes a decision to the cheapest thing that can resolve it, and pulls in the principal only when nothing cheaper will do.

Two symmetric failure modes follow. Waste is asking about choices the substrate could have resolved from policy. Usurp is deciding things — architectural calls, precedent-setting naming, scope expansions — that structurally belong to the principal. Minsky treats these as a single routing problem: different kinds of asks (permission, direction, escalation, review, notification) need different transports and cost models, not one-size-fits-all confirmation dialogs.

The full argument — and the emerging ask taxonomy — is in the companion essay on attention as the binding resource.

Quick start

Installation

# Clone repository
git clone https://github.com/edobry/minsky.git
cd minsky

# Install with Bun (recommended)
bun install
bun link

# Or with npm
npm install
npm link

Initialize a project

# Interactive setup — configures task backend and git hooks
minsky init

# Developer-local setup — MCP registration + local config + DB connection
minsky setup

minsky setup owns the database connection so most projects need zero database thought. It resolves persistence.postgres.connectionString through the config loader first: on a machine that already has a Minsky project configured, it finds and reuses that connection (printing which config source it came from — user config, repo config, or an environment variable — after a quick connectivity check); on a fresh machine with nothing configured, it falls straight into the same interactive wizard described below. Schema migrations are not a manual step — Minsky auto-migrates the schema on first connect (MINSKY_AUTO_MIGRATE defaults to true), so there is never a minsky persistence migrate command to run as part of onboarding.

Configure the database directly

minsky setup db is the same interactive wizard minsky setup falls into automatically, available standalone when you want to (re)configure the database without touching MCP registration — e.g. to point at a different connection, or for non-interactive/scripted use:

minsky setup db

It offers three ways to get a connection string:

  • Docker (detected automatically) — prints a copy-paste one-liner to start a local Postgres, then captures the resulting connection string. Minsky does not manage the container; you run and stop it with your own Docker.
  • Supabase free tier — points you at the no-credit-card signup and prompts for the connection string.
  • Bring your own — paste any existing Postgres connection string.

Before writing anything it shows a plan and asks to confirm (the config write is the only mutating step). It is re-runnable — running it again updates the connection string and re-verifies.

Non-interactive / scripted use:

# Supply the connection string directly; --yes skips the confirmation prompt.
minsky setup db --connection-string "postgresql://user:password@host:5432/dbname" --yes

# minsky setup accepts the same two flags, used only if no connection can be
# inherited from existing config:
minsky setup --connection-string "postgresql://user:password@host:5432/dbname" --yes

On failure it reports which step failed (validate / connectivity / config-write / migrate / verify) with an actionable message; connection strings are masked in all output.

Create and work on tasks

# Create a task
minsky tasks create --title "Add user authentication"

# Start a session
minsky session start --task mt#1

# Work in the isolated environment
cd $(minsky session dir mt#1)

# Make changes, then create a PR
minsky session pr create --title "feat: Add user authentication"

Shell completions (bash / zsh / fish)

minsky ships tab-completion for bash, zsh, and fish via @pnpm/tabtab. One-time setup:

# Interactive: prompts for which shell to set up
minsky completions install

# Then re-source your shell config (or open a new shell)
exec $SHELL -l

After install, tab-complete top-level commands, subcommands, option flags, AND option values:

minsky <TAB>                          # → tasks, session, rules, git, config, mcp, ...
minsky tasks <TAB>                    # → list, get, create, status, ...
minsky tasks list --<TAB>             # → --backend, --status, --tag, ...
minsky tasks list --status <TAB>      # → TODO, PLANNING, READY, IN-PROGRESS, ...
minsky git merge --conflict-strategy <TAB>  # → automatic, guided, manual

Value completion (--status <TAB> → enum values) is automatic for any option whose underlying Zod schema in the shared command registry is a finite enum (z.enum([...]), z.union([z.literal(...), ...]), or any of those wrapped in .optional() / .default(...) / .nullable()). Free-form options (z.string(), z.number()) produce no values — those fall through to the shell's default behavior.

To uninstall, run minsky completions uninstall. For manual install (bypassing the interactive prompt), minsky completions bash, minsky completions zsh, or minsky completions fish emit the raw completion script to stdout — pipe it into the appropriate shell config.

Dynamic value completion (tasks get <TAB> → live task IDs queried from the DB at TAB time) is tracked separately as mt#1894. Windows and PowerShell are not supported.

Design philosophy

Minsky applies principles from organizational cybernetics — the study of control and communication in complex systems. The right feedback loops and control structures make good practices the path of least resistance:

  • Fast feedback loops (pre-commit hooks) catch issues immediately
  • Progressive gates (pre-push, CI/CD) balance thoroughness with productivity
  • Isolation (session-based development) prevents conflicts and enables parallel work

The central insight is agent equivalence: the incentive structures that guide human developers guide AI agents equally well. This isn't coincidence — it is design. AI agents do not need to be taught to follow best practices; the environment makes following best practices the only path to success, the same as for humans.

For the full theoretical background, see docs/theory-of-operation.md. For the recursive-principality argument (every level of an organization is itself a principal-substrate relationship), see Position: Levels of principality.

Architecture

Minsky follows a clean architecture with domain logic separated from adapters and infrastructure. The same domain operations (task management, session lifecycle, PR creation) work whether accessed via CLI or MCP. See docs/architecture.md for the system-level walk-through.

Brand & identity

Notion links below are in the Minsky workspace (private; request access). The agent-consumable skill surfaces and docs/brand-system.md are in this repo and require no external account.

The brand thesis lives in Position: Principal substrate vs team substrate — the unit-of-analysis distinction that names what Minsky is and what it deliberately is not.

The agent-consumable brand foundation — locked myth, cultural code, layered references, vocabulary, bridge-as-affect discipline — lives in the minsky-brand skill.

Operational implementation tokens — typography stack, color palette in OKLCH, motion budget with prefers-reduced-motion, WCAG contrast targets — live in docs/brand-system.md.

Marketing-surface design patterns (Idiom B product-screenshot-dominant, layout, anti-patterns, the new-surface workshop process) live in the marketing-site-design skill.

The principal's literary voice — the corpus-grounded register used in long-form prose — is codified in the pz-voice skill.

Configuration notes

Observability (Braintrust)

To use Braintrust for LLM observability, both an API key and a project name are required. The project name has no default — it must be set explicitly so traces do not silently accumulate in a project named after someone else's installation:

# Configure via config
minsky config set observability.providers.braintrust.apiKey --value <your-key>
minsky config set observability.providers.braintrust.projectName --value <your-project>

# Or via environment variables
export BRAINTRUST_API_KEY=<your-key>
export BRAINTRUST_PROJECT_NAME=<your-project>

# Verify connectivity
minsky observability smoke-test

See observability.providers.braintrust.projectName in the configuration schema (packages/domain/src/configuration/schemas/observability.ts).

Postgres schema migrations (bundle-aware resolver)

minsky persistence migrate resolves the migrations folder in a bundle-aware way — it no longer requires running from the Minsky repo root. The resolver probes candidates in order:

  1. import.meta.dir/../storage/migrations/pg — source-tree (dev)
  2. import.meta.dir/storage/migrations/pg — bundled dist (co-located with dist/minsky.js)
  3. dirname(process.argv[1])/storage/migrations/pg — secondary bundled probe
  4. <cwd>/packages/domain/src/storage/migrations/pg — legacy repo-root fallback

The first candidate whose meta/_journal.json exists wins. When using the production bundle (dist/minsky.js) from an arbitrary working directory, candidates 2 and 3 resolve to the migrations co-located with the bundle.

Pending-migration detection (per-migration hash, not row count)

persistence migrate (both --dry-run and --execute) reports which local migrations are pending — not yet recorded as applied — by comparing each local .sql file's sha256 hash against the full set of hashes recorded in drizzle.__drizzle_migrations, NOT by subtracting row counts (fileCount - appliedCount). A raw count comparison silently reports 0 pending whenever the DB's applied-row count meets or exceeds the local file count for any reason unrelated to a specific migration's apply state — a historical ledger squash/consolidation, a duplicate or orphaned ledger row, an out-of-band insert — while a genuinely-unapplied migration goes unreported. The per-migration hash comparison is robust to any such count offset: a migration is pending iff its file's hash is absent from the ledger, full stop.

getPostgresMigrationsStatus exposes this as pendingCount (a number) and pendingTags (the specific migration tags, e.g. ["0060_slow_kang"]); the dry-run plan additionally carries plan.pendingFiles (the same set, as filenames with .sql). A missing or unreadable migration file (partial checkout, in-flight rename, permissions issue) is never silently dropped — it is reported pending and logged as a warning, so the operator sees the read failure rather than an unexplained gap in the count.

The pending list is informational, not a guaranteed preview of what migrate() will apply. drizzle-orm's own migrate() does not decide what to run by hash-set membership — it applies by a single-row timestamp high-water-mark (the latest created_at already in the ledger vs. each journal entry's when). When the ledger has an anomaly (a duplicate/orphaned row, an out-of-band insert, migrations recorded out of when-order), the hash-missing set this tool reports and the set drizzle's own high-water-mark check will actually apply can diverge — a migration this list names may be silently skipped by drizzle (permanently shadowed), or the reverse. Every CLI listing of pending migrations is labeled accordingly; treat it as "these files' hashes are not recorded as applied," not as an exact forecast of migrate()'s next run.

CI workflows

Workflow Trigger Purpose
bundle-boot-smoke every PR / main push Builds the bundle and asserts GET /health returns 200
cold-start-migrate every PR / main push Builds the bundle, runs minsky persistence migrate --execute from a temp dir outside the repo, then asserts the tasks table was created and --dry-run reports 0 pending migrations

The cold-start-migrate workflow is the regression gate for the bundle-aware migration resolver. It proves that the production binary can find and apply its bundled migrations from an arbitrary working directory.

Contributing

Contributions welcome. See CONTRIBUTING.md for guidelines.

Documentation

License

MIT — See LICENSE for details.

Acknowledgments

Named after Marvin Minsky, whose Society of Mind theory inspired the idea that intelligence emerges from the coordination of simpler processes. Just as Minsky proposed that minds are societies of simpler agents, this tool orchestrates development tools into coherent workflows.

The organizational cybernetics principles draw from Stafford Beer's Viable System Model: organizations of humans or AI agents need the same control structures to function effectively.

About

a coding agent workflow tool inspired by organizational cybernetics

Resources

Contributing

Stars

Watchers

Forks

Releases

Used by

Contributors

Languages