Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
version: 2
updates:
- package-ecosystem: npm
directory: /
schedule:
interval: weekly
day: monday
open-pull-requests-limit: 10
groups:
minor-and-patch:
update-types:
- minor
- patch

- package-ecosystem: npm
directory: /webview-ui
schedule:
interval: weekly
day: monday
open-pull-requests-limit: 10
groups:
minor-and-patch:
update-types:
- minor
- patch

- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
day: monday
open-pull-requests-limit: 5
172 changes: 172 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
# CI workflow for pixel-agents

name: CI

on:
pull_request:
paths-ignore:
- '**.md'
- 'LICENSE'
- '.github/FUNDING.yml'
push:
branches:
- main
paths-ignore:
- '**.md'
- 'LICENSE'
- '.github/FUNDING.yml'

permissions:
contents: read

concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}

jobs:
ci:
runs-on: ubuntu-latest
timeout-minutes: 15

steps:
- name: Checkout
id: checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup Node
id: setup_node
uses: actions/setup-node@v4
with:
node-version-file: .nvmrc
cache: npm
cache-dependency-path: |
package-lock.json
webview-ui/package-lock.json

- name: Install Root Dependencies
id: install_root
run: npm ci

- name: Install Webview Dependencies
id: install_webview
working-directory: webview-ui
run: npm ci

# --- Quality Checks (blocking) ---

- name: Type Check
id: type_check
if: always() && steps.install_root.outcome == 'success'
run: npm run check-types
continue-on-error: true

- name: Root Lint
id: root_lint
if: always() && steps.install_root.outcome == 'success'
run: npm run lint
continue-on-error: true

- name: Webview Lint
id: webview_lint
if: always() && steps.install_webview.outcome == 'success'
working-directory: webview-ui
run: npm run lint
continue-on-error: true

- name: Format Check
id: format_check
if: always() && steps.install_root.outcome == 'success'
run: npm run format:check
continue-on-error: true

# --- Build (blocking) ---

- name: Build
id: build
if: always() && steps.install_root.outcome == 'success' && steps.install_webview.outcome == 'success'
run: |
node esbuild.js
cd webview-ui && npm run build
continue-on-error: true

# --- Advisory Checks (non-blocking) ---

- name: Audit Root Dependencies
id: audit_root
if: always() && steps.install_root.outcome == 'success'
run: npm audit --audit-level=high
continue-on-error: true

- name: Audit Webview Dependencies
id: audit_webview
if: always() && steps.install_webview.outcome == 'success'
working-directory: webview-ui
run: npm audit --audit-level=high
continue-on-error: true

# --- Summary ---

- name: Write Step Summary
if: always()
env:
CHECKOUT: ${{ steps.checkout.outcome }}
SETUP_NODE: ${{ steps.setup_node.outcome }}
INSTALL_ROOT: ${{ steps.install_root.outcome }}
INSTALL_WEBVIEW: ${{ steps.install_webview.outcome }}
TYPE_CHECK: ${{ steps.type_check.outcome }}
ROOT_LINT: ${{ steps.root_lint.outcome }}
WEBVIEW_LINT: ${{ steps.webview_lint.outcome }}
FORMAT_CHECK: ${{ steps.format_check.outcome }}
BUILD: ${{ steps.build.outcome }}
AUDIT_ROOT: ${{ steps.audit_root.outcome }}
AUDIT_WEBVIEW: ${{ steps.audit_webview.outcome }}
run: |
status() {
if [ "$1" = "success" ]; then echo "✅ PASS"; else echo "❌ FAIL"; fi
}
{
echo "## CI Results"
echo
echo "| Check | Result |"
echo "| --- | --- |"
echo "| Checkout | $(status "$CHECKOUT") |"
echo "| Setup Node | $(status "$SETUP_NODE") |"
echo "| Install root deps | $(status "$INSTALL_ROOT") |"
echo "| Install webview deps | $(status "$INSTALL_WEBVIEW") |"
echo "| **Type check** | $(status "$TYPE_CHECK") |"
echo "| **Root lint** | $(status "$ROOT_LINT") |"
echo "| **Webview lint** | $(status "$WEBVIEW_LINT") |"
echo "| **Format check** | $(status "$FORMAT_CHECK") |"
echo "| **Build** | $(status "$BUILD") |"
echo "| Audit root _(advisory)_ | $(status "$AUDIT_ROOT") |"
echo "| Audit webview _(advisory)_ | $(status "$AUDIT_WEBVIEW") |"
} >> "$GITHUB_STEP_SUMMARY"

# --- Final Gate ---

- name: Fail If Any Blocking Check Failed
if: always()
env:
CHECKOUT: ${{ steps.checkout.outcome }}
SETUP_NODE: ${{ steps.setup_node.outcome }}
INSTALL_ROOT: ${{ steps.install_root.outcome }}
INSTALL_WEBVIEW: ${{ steps.install_webview.outcome }}
TYPE_CHECK: ${{ steps.type_check.outcome }}
ROOT_LINT: ${{ steps.root_lint.outcome }}
WEBVIEW_LINT: ${{ steps.webview_lint.outcome }}
FORMAT_CHECK: ${{ steps.format_check.outcome }}
BUILD: ${{ steps.build.outcome }}
run: |
failed=0
for step in CHECKOUT SETUP_NODE INSTALL_ROOT INSTALL_WEBVIEW \
TYPE_CHECK ROOT_LINT WEBVIEW_LINT FORMAT_CHECK \
BUILD; do
eval "val=\$$step"
if [ "$val" != "success" ]; then
echo "::error::$step failed"
failed=1
fi
done
exit "$failed"
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"dist": true // set this to false to include "dist" folder in search results
},
// Turn off tsc task auto detection since we have the necessary tasks as npm scripts
"typescript.tsc.autoDetect": "off",
"#js/ts.tsc.autoDetect#": "off",
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"[json]": {
Expand Down
12 changes: 12 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,18 @@
"group": "watch",
"reveal": "never"
}
},
{
"label": "Run CI (act)",
"type": "shell",
"command": "act push -j ci --container-architecture linux/amd64",
"group": "test",
"presentation": {
"reveal": "always",
"panel": "dedicated",
"clear": true
},
"problemMatcher": []
}
]
}
27 changes: 20 additions & 7 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ This project is licensed under the [MIT License](LICENSE), so your contributions

### Prerequisites

- [Node.js](https://nodejs.org/) (LTS recommended)
- [VS Code](https://code.visualstudio.com/) (v1.109.0 or later)
- [Node.js](https://nodejs.org/) (v22 recommended)
- [VS Code](https://code.visualstudio.com/) (v1.107.0 or later)

### Setup

Expand Down Expand Up @@ -45,9 +45,10 @@ This starts parallel watchers for both the extension backend (esbuild) and TypeS
| `assets/` | Bundled sprites, catalog, and default layout |

## Code Guidelines

### Constants

**No unused locals or parameters** (`noUnusedLocals` and `noUnusedParameters` are enabled): All magic numbers and strings are centralized — don't add inline constants to source files:
**No unused locals or parameters** (`noUnusedLocals` and `noUnusedParameters` are enabled). All magic numbers and strings are centralized — don't add inline constants to source files:

- **Extension backend:** `src/constants.ts`
- **Webview:** `webview-ui/src/constants.ts`
Expand All @@ -59,18 +60,30 @@ The project uses a pixel art aesthetic. All overlays should use:

- Sharp corners (`border-radius: 0`)
- Solid backgrounds and `2px solid` borders
- Hard offset shadows (`2px 2px 0px`, no blur)
- Hard offset shadows (`2px 2px 0px`, no blur) — use `var(--pixel-shadow)`
- The FS Pixel Sans font (loaded in `index.css`)

These conventions are enforced by custom ESLint rules (`eslint-rules/pixel-agents-rules.mjs`):

| Rule | Scope | What it checks |
|---|---|---|
| `no-inline-colors` | Extension + Webview | No hex/rgb/rgba/hsl/hsla literals outside `constants.ts` |
| `pixel-shadow` | Webview only | Box shadows must use `var(--pixel-shadow)` or `2px 2px 0px` |
| `pixel-font` | Webview only | Font family must reference FS Pixel Sans |

These rules are set to `warn` — they won't block your PR but will flag violations for cleanup.

## Submitting a Pull Request

1. Fork the repo and create a feature branch from `main`
2. Make your changes
3. Run the full build to verify everything passes:
3. Verify everything passes locally:
```bash
npm run build
npm run lint # Extension lint
cd webview-ui && npm run lint && cd .. # Webview lint
npm run build # Type check + esbuild + Vite
```
This runs type-checking, linting, esbuild (extension), and Vite (webview).
CI runs these same checks automatically on every PR.
4. Open a pull request against `main` with:
- A clear description of what changed and why
- How you tested the changes (steps to reproduce / verify)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ This is the source code for the free [Pixel Agents extension for VS Code](https:

## Requirements

- VS Code 1.109.0 or later
- VS Code 1.107.0 or later
- [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code) installed and configured

## Getting Started
Expand Down
Loading