diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..95cb3a3 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,37 @@ +name: Bug report +description: A skill gives wrong instructions or an example does not work +labels: ["bug"] +body: + - type: markdown + attributes: + value: | + Search existing issues first. Keep it short and specific. + - type: input + id: skill + attributes: + label: Skill + description: The skill directory, e.g. `blocks-api`, and the reference file if relevant. + validations: + required: true + - type: textarea + id: what-happened + attributes: + label: What happened + description: What went wrong, and what did you expect instead? + validations: + required: true + - type: textarea + id: request + attributes: + label: Request and response + description: The API call you made and what came back. Reference the key, never paste it. + render: text + validations: + required: false + - type: input + id: agent + attributes: + label: Agent and installer + description: e.g. `Claude Code`, installed with `npx skills add --global`. + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..fd74836 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: Blocks documentation + url: https://docs.blocks.team + about: Platform docs, including the REST API these skills call. + - name: Report a security vulnerability + url: https://github.com/BlocksOrg/skills/security/policy + about: Report vulnerabilities privately — do not open a public issue. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..b5a7058 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,27 @@ +name: Feature request +description: Suggest a new skill or an addition to an existing one +labels: ["enhancement"] +body: + - type: textarea + id: problem + attributes: + label: What problem does this solve? + description: What are you trying to get an agent to do with Blocks that the skills make hard or impossible today? + validations: + required: true + - type: textarea + id: proposal + attributes: + label: Proposed solution + description: A new skill, a new reference playbook, a changed recommendation — whatever you have in mind. + validations: + required: true + - type: checkboxes + id: checks + attributes: + label: Before submitting + options: + - label: I searched existing issues and this isn't a duplicate. + required: true + - label: I checked the existing skills and the Blocks docs and this isn't already covered. + required: true diff --git a/.github/ISSUE_TEMPLATE/question.yml b/.github/ISSUE_TEMPLATE/question.yml new file mode 100644 index 0000000..15991c6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/question.yml @@ -0,0 +1,14 @@ +name: Question +description: Ask a question about using the skills +labels: ["question"] +body: + - type: markdown + attributes: + value: | + Check the [README](https://github.com/BlocksOrg/skills#readme) and the [Blocks docs](https://docs.blocks.team) first. For security reports, see SECURITY.md — do not open a public issue. + - type: textarea + id: question + attributes: + label: Your question + validations: + required: true diff --git a/.github/assets/blocks-logo-dark.svg b/.github/assets/blocks-logo-dark.svg new file mode 100644 index 0000000..e698bb8 --- /dev/null +++ b/.github/assets/blocks-logo-dark.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.github/assets/blocks-logo-light.svg b/.github/assets/blocks-logo-light.svg new file mode 100644 index 0000000..2d691d3 --- /dev/null +++ b/.github/assets/blocks-logo-light.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..aeb74cb --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,20 @@ +## Summary + + + +## Linked issue + +Fixes # + +## How I verified + + + +## Checklist + +- [ ] `npx skills add . --list` lists every skill under `skills/` +- [ ] Frontmatter `name` matches the skill directory and `description` says when to trigger +- [ ] Examples use `https://api.blocks.team` and `$BLOCKS_API_KEY`; no real keys or internal hosts +- [ ] Docs links resolve and the skill does not restate what the public docs already cover +- [ ] PR title follows Conventional Commits (`type(scope): summary`) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..e9d4d34 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,90 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + workflow_dispatch: + +permissions: + contents: read + +jobs: + # Lints the workflow files themselves: unknown runner labels, bad expressions, + # shellcheck over every `run:` block. A workflow that fails to parse posts no + # check-run at all, so nothing else in this file would ever catch it. + actionlint: + name: Lint workflows + runs-on: ubuntu-latest + timeout-minutes: 5 + env: + ACTIONLINT_VERSION: 1.7.12 + # sha256 of actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz, from the + # release's published checksums file. + ACTIONLINT_SHA256: 8aca8db96f1b94770f1b0d72b6dddcb1ebb8123cb3712530b08cc387b349a3d8 + steps: + - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0 + - name: Install actionlint + run: | + tarball="actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz" + curl -fsSL -o "$tarball" \ + "https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}/${tarball}" + echo "${ACTIONLINT_SHA256} ${tarball}" | sha256sum --check --strict - + tar -xzf "$tarball" actionlint + - run: ./actionlint -color + + # Every skill must be discoverable by `npx skills add`, its frontmatter name + # must match its directory, and nothing in the repo may leak a real key or an + # internal host. The install script must at least parse. + validate: + name: Validate skills + runs-on: ubuntu-latest + timeout-minutes: 10 + env: + SKILLS_CLI_VERSION: 1.7.0 + steps: + - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0 + - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 + with: + node-version: 24 + - name: Frontmatter name matches directory + run: | + set -euo pipefail + status=0 + for file in skills/*/SKILL.md; do + dir=$(basename "$(dirname "$file")") + name=$(sed -n 's/^name:[[:space:]]*//p' "$file" | head -n1 | tr -d '"'"'"'') + if [ "$name" != "$dir" ]; then + echo "::error file=$file::frontmatter name '$name' does not match directory '$dir'" + status=1 + fi + if ! grep -q '^description:' "$file"; then + echo "::error file=$file::frontmatter is missing a description" + status=1 + fi + done + exit "$status" + - name: skills CLI discovers every skill + run: | + set -euo pipefail + listing=$(npx --yes "skills@${SKILLS_CLI_VERSION}" add . --list 2>&1 | sed 's/\x1b\[[0-9;?]*[a-zA-Z]//g') + echo "$listing" + status=0 + for dir in skills/*/; do + name=$(basename "$dir") + if ! printf '%s\n' "$listing" | grep -qE "^[^A-Za-z0-9_-]*${name}[[:space:]]*$"; then + echo "::error::skills CLI did not list '$name'" + status=1 + fi + done + exit "$status" + - name: No real keys or internal hosts + run: | + set -euo pipefail + if grep -rnE 'ApiKey [A-Za-z0-9_-]{30,}|api\.dev\.blocks\.team|appdev\.blocks\.team' \ + --exclude-dir=.git --exclude-dir=.github .; then + echo "::error::found what looks like a real API key or an internal host" + exit 1 + fi + - name: install.sh parses + run: sh -n install.sh diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..4d5aa23 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,37 @@ +name: CodeQL + +on: + push: + branches: [main] + pull_request: + schedule: + - cron: '23 5 * * 1' + workflow_dispatch: + +permissions: + actions: read + contents: read + security-events: write + +concurrency: + group: codeql-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + +jobs: + analyze: + # The check-run is always named "CodeQL", whether it runs or is skipped, so + # it can be a required status check. + name: CodeQL + # Code scanning on a private or internal repository needs GitHub Advanced + # Security. Skip until the repo is public: a skipped job still posts a + # check-run, which counts as passing for a required status check. + if: github.event.repository.visibility == 'public' + runs-on: ubuntu-latest + timeout-minutes: 20 + steps: + - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0 + - uses: github/codeql-action/init@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4.38.0 + with: + # This repo ships markdown and workflow files; only the workflows are code. + languages: actions + - uses: github/codeql-action/analyze@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4.38.0 diff --git a/README.md b/README.md index 9b7339e..f52727e 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,17 @@ +

+ + + + Blocks + + +

+ # Blocks Agent Skills +[![CI](https://github.com/BlocksOrg/skills/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/BlocksOrg/skills/actions/workflows/ci.yml) +[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](./LICENSE) + Installable `SKILL.md` skills for working with the [Blocks](https://blocks.team) REST API from AI coding agents. ## Install diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..e477215 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,26 @@ +# Security + +## What this repository handles + +- This repository ships markdown skill files and a shell installer. Nothing here runs on + its own; an AI coding agent reads the skills and decides what to do. +- **`BLOCKS_API_KEY`** is the only secret the skills refer to. It stays in your environment + and is sent only as an `Authorization: ApiKey` header to `https://api.blocks.team`. The + skills never ask an agent to print it, write it to disk, or send it anywhere else. +- Presigned artifact URLs returned by the API are fetched without the `Authorization` + header, as the skills state, so the key is never sent to a storage host. +- `install.sh` runs `npx skills add` against this repository and nothing else. CI checks + that every example uses the public host and a placeholder key. + +## Trust boundaries + +- `main` requires review and passing checks, so what a user installs is what was reviewed. +- What an agent does with a session it reads is governed by the agent, its configuration, + and the credentials it holds. These skills only describe how to call the API. + +## Reporting a vulnerability + +Please report suspected vulnerabilities privately via +[GitHub's private vulnerability reporting](https://github.com/BlocksOrg/skills/security/advisories/new) +rather than opening a public issue. Include a description, reproduction steps, and impact. +We aim to acknowledge reports within a few business days.