{
  "markdown": "<p align=\"center\">\n  <picture>\n    <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://shieldcn.dev/header/surface.svg?title=Skills%20Board&amp;subtitle=Your%20team%27s%20skills.%20All%20in%20one%20place.&amp;size=wide&amp;align=left&amp;font=space-grotesk&amp;border=true&amp;radius=18&amp;watermark=false&amp;logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMiAzMiI%2BPHBhdGggZmlsbD0iIzZiZDU4ZiIgZD0iTTMgM2gyNnY3SDExdjRoMTRsNCA0djExSDN2LTdoMTh2LTRIN2wtNC00VjNaIi8%2BPC9zdmc%2B&amp;logoColor=6bd58f&amp;bg=111a14&amp;accent=6bd58f&amp;titleColor=f7f8f4&amp;subtitleColor=aab5aa&amp;mode=dark\" />\n    <img alt=\"Skills Board — Your team's skills. All in one place.\" src=\"https://shieldcn.dev/header/surface.svg?title=Skills%20Board&amp;subtitle=Your%20team%27s%20skills.%20All%20in%20one%20place.&amp;size=wide&amp;align=left&amp;font=space-grotesk&amp;border=true&amp;radius=18&amp;watermark=false&amp;logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMiAzMiI%2BPHBhdGggZmlsbD0iIzAwODQzZCIgZD0iTTMgM2gyNnY3SDExdjRoMTRsNCA0djExSDN2LTdoMTh2LTRIN2wtNC00VjNaIi8%2BPC9zdmc%2B&amp;logoColor=00843d&amp;bg=f7f8f4&amp;accent=00843d&amp;titleColor=17231b&amp;subtitleColor=5e6b61&amp;mode=light\" />\n  </picture>\n</p>\n\n<p align=\"center\">\n  Skills Board, the agent-native skills registry for teams. Keep your team's AI skills in one place, so everyone knows where to find and use them.\n</p>\n\n<p align=\"center\">\n  <a href=\"https://github.com/TommyBez/skillsboard/stargazers\">\n    <picture>\n      <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://shieldcn.dev/github/stars/TommyBez/skillsboard.svg?variant=outline&amp;size=xs&amp;theme=zinc&amp;font=geist&amp;mode=dark\" />\n      <img alt=\"GitHub stars\" src=\"https://shieldcn.dev/github/stars/TommyBez/skillsboard.svg?variant=outline&amp;size=xs&amp;theme=zinc&amp;font=geist&amp;mode=light\" />\n    </picture>\n  </a>\n  <a href=\"./LICENSE\">\n    <picture>\n      <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://shieldcn.dev/badge/license-MIT-27272a.svg?variant=outline&amp;size=xs&amp;theme=zinc&amp;font=geist&amp;mode=dark&amp;logo=false\" />\n      <img alt=\"MIT license\" src=\"https://shieldcn.dev/badge/license-MIT-27272a.svg?variant=outline&amp;size=xs&amp;theme=zinc&amp;font=geist&amp;mode=light&amp;logo=false\" />\n    </picture>\n  </a>\n  <a href=\"https://github.com/TommyBez/skillsboard/actions/workflows/ci.yml\">\n    <picture>\n      <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://shieldcn.dev/github/ci/TommyBez/skillsboard.svg?workflow=ci.yml&amp;branch=main&amp;variant=outline&amp;size=xs&amp;theme=zinc&amp;font=geist&amp;mode=dark\" />\n      <img alt=\"CI status\" src=\"https://shieldcn.dev/github/ci/TommyBez/skillsboard.svg?workflow=ci.yml&amp;branch=main&amp;variant=outline&amp;size=xs&amp;theme=zinc&amp;font=geist&amp;mode=light\" />\n    </picture>\n  </a>\n</p>\n\n<p align=\"center\">\n  <a href=\"https://www.skillsboard.sh\"><strong>Try the hosted app</strong></a>\n  ·\n  <a href=\"#run-locally\">Run it locally</a>\n  ·\n  <a href=\"./CONTRIBUTING.md\">Contribute</a>\n</p>\n\n## Why Skills Board\n\nUseful skills tend to disappear into chats, bookmarks, and personal agent setups. Skills Board gives a team one searchable place to collect them and lets every teammate choose how to use them.\n\n- **One team library.** Save useful skills once, organize them with team-specific tags, and make them easy to find again.\n- **Different agents welcome.** Share the same entry across Claude, Codex, Cursor, and other agent setups.\n- **A choice of handoff.** Open the original source, copy a compatible install command, or download the latest skill files as a ZIP.\n- **Organization-scoped access.** Create a team, invite members, and keep each library available to its members.\n- **Optional MCP access.** Connect compatible agents to authenticated, scope-controlled tools for finding and organizing team skills and collections.\n\n> [!IMPORTANT]\n> A saved skill is a team's own choice, not a security review, compatibility certification, or pinned release. Skills Board reads the latest available source; inspect that source before using it in an agent.\n\n## How it works\n\n1. Create a team library and add a skill from its GitHub repository.\n2. Skills Board keeps the original source visible and records the entry for the team.\n3. Teammates search by task, description, repository, or tag.\n4. Each teammate opens the source, copies a compatible command, or downloads the latest files as a ZIP.\n\nThe public catalog can help with discovery when the deployment has Vercel OIDC available. The team library and direct GitHub flow remain the core product.\n\n## Run locally\n\n### Prerequisites\n\n- Node.js 20.9 or newer\n- pnpm 10\n- PostgreSQL 15 or newer\n\n### 1. Install the app\n\n```bash\ngit clone https://github.com/TommyBez/skillsboard.git\ncd skillsboard\ncorepack enable\npnpm install\ncp .env.example .env.local\n```\n\nGenerate a Better Auth secret with `openssl rand -base64 32`, then add it and your PostgreSQL connection string to `.env.local`.\n\n### 2. Prepare the database\n\nApply the committed Drizzle migrations to a new database. This creates both the Better Auth tables and the application-specific tables from the versioned SQL in `drizzle/`.\n\n```bash\npnpm db:migrate\n```\n\n### 3. Start developing\n\n```bash\npnpm dev\n```\n\nOpen [http://localhost:3000](http://localhost:3000). Restart the server after changing `DATABASE_URL`, because the PostgreSQL pool is created when the module loads.\n\n### Environment variables\n\n| Variable | Required | Purpose |\n| --- | --- | --- |\n| `DATABASE_URL` | Yes | PostgreSQL connection string used by the application; Neon may use the pooled URL here. |\n| `DATABASE_URL_UNPOOLED` | For migrations on Neon | Direct PostgreSQL connection used by Drizzle migrations. It can match `DATABASE_URL` for local, non-pooled Postgres. |\n| `BETTER_AUTH_SECRET` | Yes | Secret used to sign and encrypt authentication data. |\n| `BETTER_AUTH_URL` | Recommended | Public application origin; use `http://localhost:3000` locally. |\n| `CRON_SECRET` | Yes for hosted release cleanup | Dedicated random secret used to authenticate the daily expired collection-release cleanup configured in `vercel.json`. |\n| `RESEND_API_KEY` | Yes outside development | Sends sign-in OTP and team invitation emails through Resend. |\n| `EMAIL_FROM` | Yes outside development | Verified Resend sender for OTP and invitation emails (e.g. `Skills Board <login@your-verified-domain.com>`). |\n| `RESEND_WEBHOOK_SECRET` | Yes for hosted email delivery | Verifies Resend bounce, complaint, suppression, and unsubscribe webhooks. |\n| `EMAIL_PRIVACY_SECRET` | Yes in Vercel Production | At least 32 random bytes encoded as base64 or hex; the dedicated root for email hashes and encrypted unsubscribe links. Local/self-hosted environments can fall back to a domain-separated key derived from `BETTER_AUTH_SECRET`. |\n| `EMAIL_PRIVACY_SECRET_PREVIOUS` | Only during key rotation | JSON array of retained base64/hex roots used for dual-hash suppression lookup and unsubscribe-token decryption. A prior root cannot be removed while retained records still depend on it. |\n| `KV_REST_API_URL` | Yes outside development | REST endpoint of the Upstash Redis database that counts email capture submissions per client address. On Vercel, the Marketplace integration writes it into the project by itself. |\n| `KV_REST_API_TOKEN` | Yes outside development | REST token for that database, written by the same integration. The read-only token it also writes is not used. |\n| `UPSTASH_REDIS_REST_URL` | Self-hosted alternative | Same endpoint under the canonical Upstash name, for a database created by hand. The Upstash client reads it before `KV_REST_API_URL`, so a Vercel project leaves it unset. |\n| `UPSTASH_REDIS_REST_TOKEN` | Self-hosted alternative | Same token under the canonical Upstash name, read before `KV_REST_API_TOKEN`. With neither pair complete, the capture form keeps working and is not rate limited. |\n| `GITHUB_TOKEN` | No | Raises GitHub API rate limits for metadata and ZIP downloads. |\n| `VERCEL_OIDC_TOKEN` | No | Supplied automatically by Vercel for the optional skills.sh catalog. |\n\nSign-in and sign-up use email one-time codes (no passwords). Outside development, configure both `RESEND_API_KEY` and a domain-verified `EMAIL_FROM`; the fallback Resend test sender only works for Resend’s own test recipients. In development, OTP emails are skipped and any 6-digit code works. Without Vercel OIDC, the Discover catalog degrades gracefully while team libraries continue to work.\n\nHosted deployments run the collection-release retention cleanup once per day. Set `CRON_SECRET` in the Vercel Production environment before deploying; the endpoint fails closed when the secret is absent. Self-hosted deployments can invoke `/api/cron/collection-release-retention` from their scheduler with `Authorization: Bearer <CRON_SECRET>`.\n\nThe public email capture form is rate limited to five submissions an hour per client address, counted in Upstash Redis under hashed addresses. On Vercel, add an Upstash Redis database from the Marketplace in a region close to the deployment and connect it to the project: the integration writes `KV_REST_API_URL` and `KV_REST_API_TOKEN` into Production and Preview, and nothing else has to be set. Self-hosted deployments point at a database created in `console.upstash.com` and set `UPSTASH_REDIS_REST_URL` and `UPSTASH_REDIS_REST_TOKEN` instead. The Upstash client reads the canonical pair first and falls back to the `KV_REST_API_` one, so where both are present the canonical pair is what counts. Either way the form fails open: with no credentials, or with Redis unreachable, submissions are accepted uncounted and the gap is logged.\n\nProduct communications are separate from transactional OTP and invitation email. Signup consent is optional and off by default, can be changed under **Settings → Email**, and is enforced with local consent history, suppression records, signed unsubscribe links, and verified Resend delivery webhooks. See [`docs/email-compliance.md`](./docs/email-compliance.md) before configuring a product broadcast.\n\n## MCP access\n\nSkills Board exposes an OAuth-protected MCP endpoint at `/api/mcp`. After signing in, open **Settings → MCP** to connect it. The tools can search team skills and collections, retrieve install commands, and discover public or repository skills. With `skills:write`, they can save new skills and organize collections. They cannot edit or delete saved team skills, install them in an agent, or execute them.\n\nThe full contract lives at [skillsboard.sh/developers](https://www.skillsboard.sh/developers) (Markdown at [`/developers.md`](https://www.skillsboard.sh/developers.md)): the public endpoints, the OAuth flow, every tool and the scope it needs, and the versioning, error, and rate-limit conventions the HTTP surface follows. The machine-readable index of all of it is [`/llms.txt`](https://www.skillsboard.sh/llms.txt).\n\n## Official plugin\n\nThis repository is also the marketplace for the official Skills Board plugin. The plugin ships the MCP server configuration above and one skill that explains how to use a team library from an agent. It is not tied to one client: the directory in [`plugin/`](./plugin) carries an [Agent Plugins](https://agent-plugins.org) 1.0.0 manifest, and a Claude Code manifest alongside it. Installing it is an alternative to the manual MCP setup above rather than a step after it.\n\nIn Claude Code:\n\n```bash\n/plugin marketplace add TommyBez/skillsboard\n/plugin install skills-board@skills-board\n```\n\nIn any client the `plugins` CLI supports:\n\n```bash\nnpx plugins add TommyBez/skillsboard\n```\n\nInstalling the plugin configures the MCP server. Connecting it still requires signing in to Skills Board and approving the requested scopes in the client.\n\n## Tech stack\n\n| Layer | Technology |\n| --- | --- |\n| Application | Next.js 16 App Router, React 19, TypeScript |\n| UI | Tailwind CSS 4, shadcn/ui, Base UI |\n| Authentication | Better Auth (email OTP) with organizations and OAuth provider support |\n| Data | PostgreSQL, Drizzle ORM |\n| Email | Resend and React Email |\n| Agent access | Model Context Protocol via `mcp-handler` |\n| Hosting | Vercel and Neon in the hosted deployment; self-hosting is supported |\n\n## Project commands\n\n| Command | What it does |\n| --- | --- |\n| `pnpm dev` | Start the Turbopack development server. |\n| `pnpm typecheck` | Run the TypeScript compiler without emitting files. |\n| `pnpm check` | Run the repository's required local checks. |\n| `pnpm db:generate --name <description>` | Generate a versioned migration after changing the schema. |\n| `pnpm db:check` | Check that the schema and committed migration snapshots match. |\n| `pnpm db:migrate` | Apply pending migrations to the configured database. |\n| `pnpm db:push` | Push the schema only to a throwaway database used for prototyping. |\n| `pnpm build` | Create a production build. |\n| `pnpm start` | Start the production server. |\n| `pnpm email` | Preview React Email templates on port 3001. |\n\n## Contributing\n\nIssues and pull requests are welcome. Read [CONTRIBUTING.md](./CONTRIBUTING.md) before making a substantial change, follow the [Code of Conduct](./CODE_OF_CONDUCT.md), and report vulnerabilities through the process in [SECURITY.md](./SECURITY.md).\n\nSee the people who have helped build Skills Board on the [contributors page](https://github.com/TommyBez/skillsboard/graphs/contributors).\n\n## License\n\nSkills Board is available under the [MIT License](./LICENSE).\n",
  "bytes": 13661,
  "sha": "68301fdfcc6bae75812e43e3176bee50bba36d3026cd70d4f2db31ad0ae521c8",
  "repo_slug": "tommybez/skillsboard",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_tommybez_skillsboard_9bcb84b4/readme"
}