Repos
БесплатноНе проверенLocal repo intelligence platform for AI agents — track all repos, search commits, PRs, branches across your machine. CLI + MCP + Web dashboard.
Описание
Local repo intelligence platform for AI agents — track all repos, search commits, PRs, branches across your machine. CLI + MCP + Web dashboard.
README
Local repo intelligence platform for AI agents. Track all repos on your machine, search commits, PRs, branches across every repository. CLI + MCP server + Web dashboard.
Install
bun install -g @hasna/repos
Quick Start
# Scan all repos under ~/Workspace
repos scan
# List all tracked repos
repos repos
# Search across everything
repos search "authentication"
# Show stats
repos stats
# Start the dashboard
repos-serve # http://localhost:19450
CLI Commands
| Command | Description |
|---|---|
repos scan |
Discover and index all git repos |
repos repos |
List repositories |
repos repo <name> |
Get repo details |
repos registry relocate-primary |
Losslessly absorb a registered canonical target into a preserved legacy repo ID |
repos commits |
List commits |
repos branches |
List branches |
repos tags |
List tags |
repos prs |
List pull requests |
repos search <query> |
Unified search across all entities |
repos stats |
Global statistics |
repos activity |
Recent commit activity |
repos contributors |
Top contributors |
repos stale |
Stale repos with no recent commits |
repos heatmap |
Commit activity heatmap |
repos sync-github |
Sync PRs from GitHub |
repos gh-info <name> |
Fetch GitHub metadata |
repos gh-catalog |
Enumerate/cache GitHub repository catalog JSON for OpenLoops |
repos package health [path] |
Check package scripts, bins, lockfiles, and release metadata |
repos package drift [path] |
Compare package.json against bun.lock |
repos package resolve-bin [name] |
Resolve package bins from package.json, node_modules, or PATH |
repos ports scan [path] |
Scan listening ports and match package script port hints |
repos triage branches [path] |
Summarize branch, dirty, stale, merged, ahead/behind state |
repos triage prs [path] |
Summarize GitHub PR state through gh |
repos docs drift [path] |
Check README coverage for package and agent ops commands |
repos release health [path] |
Combine package, drift, docs, branch, and release-pipeline checks |
repos release parity [path] |
Check the standard ci.yml + tag-publish publish.yml pair and npm-latest-without-git-tag drift |
repos no-cloud inventory [path] |
Scan repos for legacy cloud package references and route-safe remediation metadata |
repos ops pr-queue |
Emit PR merge task seeds, optional bounded GitHub sync, reports, and todos upserts |
repos ops global-cli-smoke |
Check global CLIs, emit task seeds for failures, reports, and todos upserts |
repos ops package-hygiene |
Check Bun/npm Hasna package hygiene |
repos ops release-candidates |
Detect releasable repo changes or release blockers and emit task seeds |
repos ops release-pipeline-parity |
Flag repos missing the standard CI + tag-publish workflow pair or with npm-latest-without-git-tag drift |
repos ops docs-rules-drift |
Detect code changes that need docs, changelog, prompt, skill, or agent-rule updates |
repos ops dependency-refresh |
Detect dependency refresh needs and emit lifecycle-routed task seeds |
repos ops workspace-worktree-hygiene |
Scan workspace repos for stale, dirty, detached, or missing loop worktrees |
repos ops task-route-health |
Check that task-created lifecycle router loops are active and recently succeeding |
repos ops protected-release |
Emit a protected release task only when release-candidate gates are green |
Legacy list/search/status commands support --json for machine-readable output.
Primary registry relocation
repos registry relocate-primary repairs a stale primary route when the canonical
checkout is already registered as another row. The legacy ID survives and the
explicit target ID is absorbed only after its metadata is reconciled. The command
is a dry run unless --apply is given. Both modes require optimistic revisions
for both rows, a canonical target below the trusted user worktree root, a
credential-free host/owner/name remote, the target's exact HEAD, and a stable
idempotency key.
For the Infinity Machine cutover, the reviewed live registry map is exact:
| Repository | Preserved legacy ID | Absorbed canonical ID |
|---|---|---|
hasna/codewith |
661 | 1510 |
hasna/infinity |
662 | 1511 |
hasna/sandboxes |
663 | 1509 |
hasna/accounts |
664 | 1508 |
Do not infer these IDs from alphabetical order or from an older snapshot. Each apply still requires both live row revisions, the exact canonical path and HEAD, and the reviewed dry-run plan hash.
# Validation only (default)
repos registry relocate-primary \
--repo-id 663 \
--expected-current-path /dev/shm/infinity-local-build-20260710/repos/sandboxes \
--expected-source-revision '<legacy-updated-at>' \
--target-repo-id 1509 \
--target-path ~/.hasna/repos/worktrees/infinity-machine/sandboxes/aa2d66d2/primary-main-382840bccf52 \
--expected-target-revision '<target-updated-at>' \
--expected-remote github.com/hasna/sandboxes \
--expected-head <exact-lowercase-sha> \
--actor operator:<identity> \
--idempotency-key sandboxes-primary-cutover-v1 \
--json
# Apply only after reviewing the dry-run envelope
repos registry relocate-primary \
--repo-id 663 \
--expected-current-path /dev/shm/infinity-local-build-20260710/repos/sandboxes \
--expected-source-revision '<legacy-updated-at>' \
--target-repo-id 1509 \
--target-path ~/.hasna/repos/worktrees/infinity-machine/sandboxes/aa2d66d2/primary-main-382840bccf52 \
--expected-target-revision '<target-updated-at>' \
--expected-remote github.com/hasna/sandboxes \
--expected-head <exact-lowercase-sha> \
--actor operator:<identity> \
--idempotency-key sandboxes-primary-cutover-v1 \
--expected-plan-hash <sha256-from-dry-run> \
--apply \
--json
The source checkout is never read: it may be missing, dirty, or divergent because
the operation changes registry authority, not source files. Its database ID,
path, revision, and sanitized remote remain mandatory guards. The registered
target must be canonical, clean, exact-HEAD, remote-matched, and free of path
aliases. Its checkout, Git directory, common directory, and primary object
directory must all resolve inside the trusted worktree root. Nonempty object
alternates, HTTP alternates, partial-clone/promisor settings, and repository
config includes are rejected before refs or objects are read. This still allows
bundle-derived anchors and linked worktrees when their full Git authority stays
inside the trusted root. Cleanliness is verified without git status, worktree
diff, hooks,
fsmonitor, or repository-defined conversion callbacks: the command compares the
HEAD tree, stage-0 index, raw regular-file or symlink bytes, executable modes,
and non-ignored untracked inventory, and rejects conflicts or unsupported
entries. Dry run emits a request hash, plan hash, per-table counts, and hashed
collision decisions. Exact duplicate children may be deduplicated; divergent
commit, branch, tag, remote, PR, edge, or unknown foreign-key state blocks apply
without choosing a winner. Apply revalidates the plan under one immediate SQLite
transaction, reparents supported children and catalog- or path-bound worktree
leases, converges graph edges by their final mapped identity, deletes only the
absorbed target row, absorbs the target's operational metadata while retaining
the legacy ID and earliest creation time, verifies foreign keys, and writes a
sanitized receipt. Any failure rolls back everything, and an exact idempotent
retry reads back the original receipt.
Agent-loop ops commands emit compact JSON by default and bound returned lists with
--limit. Each supports --pretty for readable JSON, --todo <id> for a dry-run
todos comment preview, and --todo-apply to write that compact result back to a
task. Mutating todos integration is opt-in.
Loop producer commands use a stricter contract for deterministic OpenLoops jobs:
they emit task_suggestions, can write a private JSON report with --report-dir,
and can upsert a bounded number of deduped todos tasks with --upsert-tasks.
This lets loops follow the pattern: check expectation, write compact evidence,
upsert one task per unmet expectation, then let task-created headless workflows
claim the task. They should not dispatch prompts into tmux panes.
Examples:
repos ops pr-queue \
--sync-orgs hasna,hasnaxyz,hasnatools,hasnastudio,hasnaai,hasnaeducation,hasnafamily \
--state open \
--limit 100 \
--report-dir ~/.hasna/loops/reports/repo-pr-sync-producer \
--upsert-tasks \
--todos-project ~/.hasna/loops \
--task-list repo-pr-merge-queue \
--max-task-actions 50 \
--json
repos ops global-cli-smoke \
--report-dir ~/.hasna/loops/evidence/global-cli-smoke-native \
--upsert-tasks \
--todos-project ~/.hasna/loops \
--task-list global-cli-smoke \
--max-task-actions 20 \
--json
repos ops release-candidates \
--repo ~/workspace/hasna/opensource/open-codewith \
--github-repo hasna/codewith \
--package @hasna/codewith \
--branch main \
--tag-prefix rust-v \
--version-file codex-rs/Cargo.toml \
--report-dir ~/.hasna/loops/reports/open-codewith-release-candidates \
--upsert-tasks \
--todos-project ~/.hasna/loops \
--task-list repo-release-candidates \
--max-task-actions 1 \
--json
repos ops docs-rules-drift \
--repo ~/workspace/hasna/opensource/open-codewith \
--github-repo hasna/codewith \
--report-dir ~/.hasna/loops/reports/open-codewith-docs-rules-drift \
--upsert-tasks \
--todos-project ~/workspace/hasna/opensource/open-codewith \
--task-list codewith-product-backlog \
--max-task-actions 1 \
--json
repos ops workspace-worktree-hygiene \
--root ~/workspace/hasna/opensource \
--worktree-root ~/.hasna/loops/worktrees \
--stale-days 7 \
--report-dir ~/.hasna/loops/reports/opensource-worktree-hygiene \
--upsert-tasks \
--todos-project ~/.hasna/loops \
--task-list workspace-worktree-hygiene \
--max-task-actions 5 \
--json
--sync-max-repos is optional with --sync-orgs: omit it to paginate every
repo across the orgs (the default for the merge-queue producer, so no repo is
starved by a cap); pass it only to deliberately bound a run. Renamed or deleted
remotes (GitHub 404s) are skipped-and-continued and reported under
synced.skipped, never as errors. Genuine GitHub sync errors make the command
exit non-zero by default so loop health cannot silently run on stale metadata.
Use --allow-sync-errors only for exploratory reads where stale cached PR data
is acceptable.
Release-candidate producers intentionally exit zero when they find release
blockers after writing the report/task. The loop's job is to turn releasability
state into deduped tasks; only report/task write failures should make the
producer loop fail. Auto-routed release tasks are prepare-only: workers may
update changelogs, release notes, PRs, and evidence, but must not create or push
release tags, run npm publish/bun publish, or dispatch release workflows.
Actual publishing belongs in a separate approved/protected release step.
MCP Server
repos-mcp
34 tools available for AI agents:
list_repos,get_repo,search_reposlist_commits,search_commitslist_branches,list_tagslist_prs,search_prslist_remotessearch(unified)scan_reposget_stats,get_repo_statssync_github_prs,sync_all_github_prs,fetch_repo_metadatagraph_build,graph_query,graph_related,graph_path,graph_deps,graph_statspackage_health,package_drift,package_resolve_binports_scan,triage_branches,triage_prsdocs_drift,release_healthregister_agent,heartbeat,list_agents
REST API
repos-serve # Default port: 19450
| Endpoint | Method | Description |
|---|---|---|
/api/repos |
GET | List repos |
/api/repos/:id |
GET | Get repo + stats |
/api/search/repos |
GET | Search repos |
/api/commits |
GET | List commits |
/api/search/commits |
GET | Search commits |
/api/branches |
GET | List branches |
/api/tags |
GET | List tags |
/api/prs |
GET | List PRs |
/api/search |
GET | Unified search |
/api/stats |
GET | Global stats |
/api/scan |
POST | Trigger scan |
SDK
import { scanRepos, searchAll, listRepos, getGlobalStats } from "@hasna/repos";
const result = await scanRepos(["/home/user/code"]);
const repos = listRepos({ org: "myorg" });
const results = searchAll("authentication");
OpenLoops GitHub Catalog
OpenLoops should use the GitHub catalog contract instead of scraping CLI text:
# Refresh at most one GitHub API page, then return the first 100 matching records.
repos gh-catalog --sync --max-pages 1 --json --limit 100
# Continue a partial sync later without loading all repos in one run.
repos gh-catalog --sync --resume --max-pages 1 --json
# Enumerate cached records only, filtered for sequential multi-repo loop setup.
repos gh-catalog --json --org hasna --language TypeScript --tags open-loops --limit 25 --offset 0
SDK entry points:
import {
enumerateGithubRepoCatalog,
iterateGithubRepoCatalog,
syncGithubRepoCatalog,
} from "@hasna/repos";
const cache = syncGithubRepoCatalog({ maxPages: 1, resume: true });
const page = enumerateGithubRepoCatalog({
limit: 25,
offset: 0,
filter: { org: "hasna", packageScope: "@hasna", tags: ["open-loops"] },
});
for (const repo of iterateGithubRepoCatalog({ filter: { language: "TypeScript" } })) {
// Run one repository loop at a time.
}
The JSON envelope uses schema open-repos.github-catalog.v1 and includes source.cacheSyncedAt, source.staleAt, source.completed, source.nextCursor, page.nextOffset, GitHub rate-limit metadata, discovered accounts/orgs, and repository records. Each record includes owner/account, org, repo name/full name, default branch, visibility, archived/disabled/fork flags, topics, description, safe HTTPS/SSH clone URLs, pushed/updated timestamps, primary language, package hints, local path and branch/dirty/ahead/behind status when matched, and loop tags.
The catalog is cacheable and resumable. By default repos gh-catalog reads the cache and does not call GitHub; add --sync when OpenLoops intentionally wants to refresh data. The cache path defaults to ~/.hasna/repos/github-catalog.json and can be overridden with HASNA_REPOS_GITHUB_CACHE_PATH or --cache.
HTTP mode
Run a shared Streamable HTTP MCP server (stateless, 127.0.0.1 only):
repos-mcp --http # default port 8830
MCP_HTTP=1 repos-mcp # via env
repos-mcp --http --port 8830
- Health:
GET http://127.0.0.1:8830/health - MCP:
http://127.0.0.1:8830/mcp - Stdio remains the default when
--http/MCP_HTTP=1are not set. repos-servealso mounts/healthand/mcpon its HTTP port.
Data Storage
SQLite database at ~/.hasna/repos/repos.db with WAL mode and FTS5 full-text search.
License
Apache-2.0
Установить Repos в Claude Desktop, Claude Code, Cursor
unyly install reposСтавит в Claude Desktop, Claude Code, Cursor и VS Code — сам разбирается с npx, uvx и сборкой из исходников.
Впервые? Поставь CLI: curl -fsSL https://unyly.org/install | sh
Или настроить вручную
Выполни в терминале:
claude mcp add repos -- npx -y @hasna/reposFAQ
Repos MCP бесплатный?
Да, Repos MCP бесплатный — установка в пару кликов через Unyly без оплаты.
Нужен ли API-ключ для Repos?
Нет, Repos работает без API-ключей и переменных окружения.
Repos — hosted или self-hosted?
Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.
Как установить Repos в Claude Desktop, Claude Code или Cursor?
Открой Repos на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.
Похожие MCP
GitHub
PRs, issues, code search, CI status
автор: GitHubFilesystem
Secure file operations with configurable access controls.
Memory
Knowledge graph-based persistent memory system.
Template MCP Server
A CLI tool to create a new Model Context Protocol server project with TypeScript support, dual transport options, and an extensible structure
автор: mcpdotdirectCompare Repos with
Не уверен что выбрать?
Найди свой стек за 60 секунд
Автор?
Embed-бейдж для README
Похожее
Все в категории development
