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
1 change: 1 addition & 0 deletions .agents/skills/envoic
7 changes: 7 additions & 0 deletions .claude-plugin/plugins.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Generated from skills/envoic/templates/claude-plugins.yaml
plugins:
- id: envoic-skill
name: envoic
description: Scan, audit, and clean up Python venvs, node_modules, and dev artifacts consuming disk space.
skills:
- skills/envoic
33 changes: 33 additions & 0 deletions .cursorrules
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Generated from skills/envoic/templates/cursor.cursorrules
# Source of truth: skills/envoic/SKILL.md

# envoic - Environment Scanner

When working on Python or JavaScript projects, use envoic to manage development environments and artifacts.

## Quick Reference

uvx envoic scan . # Python: discover .venv, conda, artifacts
uvx envoic scan . --deep # include sizes
uvx envoic manage . # interactive delete
uvx envoic info .venv # health check single env
uvx envoic clean . --dry-run # preview stale cleanup

npx envoic scan . # JS: discover node_modules, artifacts
npx envoic manage . # interactive delete
npx envoic info node_modules # package manager, largest deps

## Safety

- Always run a scan before delete actions.
- Prefer --dry-run before actual deletion.
- Never delete lock files.
- CAREFUL tier: .tox/, .nox/, *.egg-info - warn before deleting.
- Use --json for programmatic parsing.

## Canonical Skill Files

- Full workflow: skills/envoic/SKILL.md
- Command catalog: skills/envoic/references/commands.md
- Safety guide: skills/envoic/references/safety.md
- Troubleshooting: skills/envoic/references/troubleshooting.md
33 changes: 33 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Generated from skills/envoic/templates/copilot-instructions.md
# Source of truth: skills/envoic/SKILL.md

# envoic - Environment Scanner

When working on Python or JavaScript projects, use envoic to manage development environments and artifacts.

## Quick Reference

uvx envoic scan . # Python: discover .venv, conda, artifacts
uvx envoic scan . --deep # include sizes
uvx envoic manage . # interactive delete
uvx envoic info .venv # health check single env
uvx envoic clean . --dry-run # preview stale cleanup

npx envoic scan . # JS: discover node_modules, artifacts
npx envoic manage . # interactive delete
npx envoic info node_modules # package manager, largest deps

## Safety

- Always run a scan before delete actions.
- Prefer --dry-run before actual deletion.
- Never delete lock files.
- CAREFUL tier: .tox/, .nox/, *.egg-info - warn before deleting.
- Use --json for programmatic parsing.

## Canonical Skill Files

- Full workflow: skills/envoic/SKILL.md
- Command catalog: skills/envoic/references/commands.md
- Safety guide: skills/envoic/references/safety.md
- Troubleshooting: skills/envoic/references/troubleshooting.md
26 changes: 26 additions & 0 deletions .github/workflows/skills.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Skill CI

on:
pull_request:
paths:
- 'skills/envoic/**'
- '.cursorrules'
- '.github/copilot-instructions.md'
- '.claude-plugin/plugins.yaml'
- '.agents/skills/envoic/**'
- 'scripts/sync-agent-instructions.py'
- 'scripts/validate-skill.py'
- '.github/workflows/skills.yml'

jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Validate skill metadata and layout
run: python3 scripts/validate-skill.py
- name: Validate generated adapter files are in sync
run: python3 scripts/sync-agent-instructions.py --check
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,39 @@ uv tool install envoic # Python
npm install -g envoic # JavaScript
```

## Agent Skill

envoic is available as an [Agent Skill](https://agentskills.io) for coding agents:

| Tool | Auto-detected file | Notes |
|---|---|---|
| Cursor | `.cursorrules` | Generated from `skills/envoic/templates/cursor.cursorrules` |
| GitHub Copilot | `.github/copilot-instructions.md` | Generated from `skills/envoic/templates/copilot-instructions.md` |
| OpenAI Codex | `.agents/skills/envoic/SKILL.md` | Symlink/copy of canonical skill |
| Claude Code | `.claude-plugin/plugins.yaml` | Generated from `skills/envoic/templates/claude-plugins.yaml` |

Install from marketplace in Claude Code:

/plugin marketplace add mahimailabs/envoic

Canonical skill source:

```text
skills/envoic/
SKILL.md
agents/openai.yaml
references/
templates/
```

Sync generated adapter files after skill updates:

```bash
python3 scripts/sync-agent-instructions.py
```

If your environment does not support symlinks, copy `skills/envoic/` into `.agents/skills/envoic/`.

## Docs

- Site: https://mahimailabs.github.io/envoic/
Expand Down
74 changes: 74 additions & 0 deletions scripts/sync-agent-instructions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#!/usr/bin/env python3
"""Sync agent adapter files from canonical templates.

Usage:
python scripts/sync-agent-instructions.py
python scripts/sync-agent-instructions.py --check
"""

from __future__ import annotations

import argparse
import shutil
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]

COPIES = [
(
ROOT / "skills/envoic/templates/cursor.cursorrules",
ROOT / ".cursorrules",
),
(
ROOT / "skills/envoic/templates/copilot-instructions.md",
ROOT / ".github/copilot-instructions.md",
),
(
ROOT / "skills/envoic/templates/claude-plugins.yaml",
ROOT / ".claude-plugin/plugins.yaml",
),
]


def check_only() -> int:
failed = False
for src, dst in COPIES:
if not src.exists():
print(f"missing source template: {src}")
failed = True
continue
if not dst.exists():
print(f"missing destination file: {dst}")
failed = True
continue
if src.read_text() != dst.read_text():
print(f"out of sync: {dst} (expected to match {src})")
failed = True
if failed:
print("Run: python scripts/sync-agent-instructions.py")
return 1
print("Agent instruction files are in sync.")
return 0


def sync_files() -> int:
for src, dst in COPIES:
if not src.exists():
raise FileNotFoundError(f"source template not found: {src}")
dst.parent.mkdir(parents=True, exist_ok=True)
shutil.copyfile(src, dst)
print(f"synced {dst.relative_to(ROOT)}")
return 0


def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--check", action="store_true", help="validate without writing")
args = parser.parse_args()
if args.check:
return check_only()
return sync_files()


if __name__ == "__main__":
raise SystemExit(main())
73 changes: 73 additions & 0 deletions scripts/validate-skill.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#!/usr/bin/env python3
"""Validate envoic skill layout and required metadata."""

from __future__ import annotations

import re
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]
SKILL = ROOT / "skills/envoic/SKILL.md"
CODEX_SKILL = ROOT / ".agents/skills/envoic/SKILL.md"
OPENAI_YAML = ROOT / "skills/envoic/agents/openai.yaml"
PYTHON_CLI = ROOT / "packages/python/src/envoic/cli.py"
JS_CLI = ROOT / "packages/js/src/cli.ts"
EXPECTED_COMMANDS = ("scan", "list", "info", "manage", "clean")


def fail(msg: str) -> None:
print(f"ERROR: {msg}")
raise SystemExit(1)


def parse_frontmatter(text: str) -> str:
match = re.match(r"^---\n(.*?)\n---\n", text, flags=re.DOTALL)
if not match:
fail(f"missing YAML frontmatter in {SKILL}")
return match.group(1)


def ensure_field(frontmatter: str, field: str) -> None:
if not re.search(rf"(?m)^{re.escape(field)}\s*:\s*", frontmatter):
fail(f"missing required frontmatter field '{field}' in {SKILL}")


def main() -> int:
if not SKILL.exists():
fail(f"missing {SKILL}")

text = SKILL.read_text()
frontmatter = parse_frontmatter(text)
ensure_field(frontmatter, "name")
ensure_field(frontmatter, "description")

if not OPENAI_YAML.exists():
fail(f"missing {OPENAI_YAML}")

if not CODEX_SKILL.exists():
fail(
"missing .agents/skills/envoic/SKILL.md (expected symlink/copy for Codex auto-discovery)"
)

if not PYTHON_CLI.exists() or not JS_CLI.exists():
fail("missing Python/JS CLI files for command validation")
py_text = PYTHON_CLI.read_text()
js_text = JS_CLI.read_text()
for command in EXPECTED_COMMANDS:
py_marker = (
f'@app.command(name="{command}")'
if command == "list"
else f"def {command}("
)
js_marker = f'.command("{command}")'
if py_marker not in py_text:
fail(f"expected Python command '{command}' not found in {PYTHON_CLI}")
if js_marker not in js_text:
fail(f"expected JS command '{command}' not found in {JS_CLI}")

print("Skill metadata/layout validation passed.")
return 0


if __name__ == "__main__":
raise SystemExit(main())
89 changes: 89 additions & 0 deletions skills/envoic/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
---
name: envoic
description: >-
Scan, audit, and clean up Python virtual environments (.venv, conda),
node_modules, and development artifacts consuming disk space. Use when
the user mentions disk space, environment cleanup, stale venvs,
node_modules bloat, project cleanup, broken environments, dangling
symlinks, or asks about disk usage from development tools. Also use
when encountering ENOSPC errors, slow installs from cache bloat, or
when onboarding into a project and needing to verify environment health.
license: BSD-3-Clause
compatibility: >-
Requires uvx (from uv) or pip for Python scanning.
Requires npx (from Node.js 18+) or npm for JavaScript scanning.
Works on Linux, macOS, and Windows.
metadata:
author: mahimailabs
version: "0.0.1"
repository: https://github.com/mahimailabs/envoic
---

# envoic - Environment Scanner and Cleanup Skill

Use envoic to discover and safely clean Python virtual environments, `node_modules`, and development artifacts.

## Quick Start

```bash
uvx envoic scan .
uvx envoic manage . --dry-run
npx envoic scan . --deep
```

If `uvx` is unavailable, install Python package with `pip install envoic`.
If `npx` is unavailable, install JS package with `npm install -g envoic`.

## Primary Workflows

### 1) Onboarding Health Check

1. Run `uvx envoic info .venv` (or `npx envoic info node_modules`).
2. If environment is broken or stale, propose delete-and-recreate steps.

### 2) Disk Space Recovery

1. Run `uvx envoic scan <root> --deep` and/or `npx envoic scan <root> --deep`.
2. Identify largest stale candidates.
3. Run `manage --dry-run`, then actual cleanup only after confirmation.

### 3) Build/Test Artifact Cleanup

1. Scan project root.
2. Prefer deleting SAFE artifacts first.
3. Warn for CAREFUL artifacts.

## Safety Contract

1. Always scan before delete.
2. Prefer `--dry-run` before destructive operations.
3. Never delete lock files or project manifest files.
4. Require explicit user confirmation for non-dry-run cleanup.

See full policy in `references/safety.md`.

## Verified Trigger Phrases

- "Find and remove stale virtualenvs"
- "Clean old node_modules and caches"
- "I hit ENOSPC, free up disk from dev artifacts"
- "Audit environment sprawl in this workspace"
- "Check if this .venv is broken"
- "List largest build artifacts"
- "Dry-run cleanup plan for Python and JS"
- "Find dangling venv symlinks"
- "Clean test/build caches safely"
- "Generate JSON report for stale environments"

## References

- Full command catalog: `references/commands.md`
- Safety and risk tiers: `references/safety.md`
- Troubleshooting and fallbacks: `references/troubleshooting.md`

## Tool-Specific Surface Files

- Codex: `.agents/skills/envoic/SKILL.md` (symlink/copy of this skill)
- Cursor: `.cursorrules` (generated adapter)
- Copilot: `.github/copilot-instructions.md` (generated adapter)
- Claude: `.claude-plugin/plugins.yaml` (generated adapter)
5 changes: 5 additions & 0 deletions skills/envoic/agents/openai.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
display_name: envoic
short_description: Scan and safely clean Python venvs, node_modules, and build artifacts.
default_prompt: >-
Audit this workspace for stale environments and dev artifacts using envoic,
show a dry-run cleanup plan first, and only then propose deletions.
Loading