|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +ScriptDeck(脚本中台)— a lightweight Windows script launcher. It scans a directory tree for subfolders containing a script file (`.bat` or `.vbs`) and `readme.md`, then serves a browser UI to search, preview, and launch them. Not limited to Python — any project runnable via `.bat` / `.vbs` works. When a subfolder has both `.vbs` and `.bat`, only the `.vbs` is kept (VBS priority). |
| 8 | + |
| 9 | +## Commands |
| 10 | + |
| 11 | +```bash |
| 12 | +# Install dependency |
| 13 | +pip install flask |
| 14 | + |
| 15 | +# Run the server (visit http://127.0.0.1:5000) |
| 16 | +python main.py |
| 17 | + |
| 18 | +# Batch-inject bat metadata (:: title: / :: desc:) from readme.md files |
| 19 | +python inject_bat_meta.py |
| 20 | +``` |
| 21 | + |
| 22 | +No test suite, linter, or CI exists. Flask runs with `debug=False`. |
| 23 | + |
| 24 | +## Architecture |
| 25 | + |
| 26 | +### Backend — `main.py` (single file) |
| 27 | + |
| 28 | +- `scan_directory()` — recursive `os.walk` over `scan_root`, collects `.bat`/`.vbs`/`readme.md` per subfolder, applies exclude rules. **VBS priority rule**: when a subfolder has both `.vbs` and `.bat`, only `.vbs` is kept. Returns a sorted list of folder-grouped items, each script carrying a `type` (`"bat"`/`"vbs"`) discriminator. |
| 29 | +- `parse_bat_metadata()` — reads the first 10 lines of a `.bat` and extracts `:: title:` / `:: desc:` (or `REM` style) comments immediately after `@echo off`. |
| 30 | +- `parse_vbs_metadata()` — reads the first 10 lines of a `.vbs` and extracts `' title:` / `' desc:` comments (VBS single-quote style), stopping at the first non-comment line. |
| 31 | +- `_read_file_with_encoding()` — tries `utf-8-sig`, `utf-8`, `gbk`, `gb2312`, `gb18030` to handle Chinese-encoded files; falls back to `utf-8` with `errors='replace'`. |
| 32 | +- All mutating APIs (`/api/set-root`, `/api/exclude-bats`, `/api/exclude-script`) write `config.json` then re-scan and return fresh data in one response. |
| 33 | +- Global `CFG` dict is reloaded from disk at the start of each stateless request (`/api/scan`) and re-saved after mutations; no in-memory cache drift. |
| 34 | + |
| 35 | +### Frontend — vanilla JS, no framework |
| 36 | + |
| 37 | +- `static/js/app.js` — all client logic: state (`appState`), rendering (`render*`), event delegation, `localStorage` persistence for favorites/recent/theme/view-mode. |
| 38 | +- `static/css/app.css` — full stylesheet (~1560 lines), CSS custom-property-driven glassmorphism design system. |
| 39 | +- `templates/index.html` — Jinja2 template; vendor libs (Lucide icons, Marked.js) loaded locally from `static/js/vendor/`. |
| 40 | + |
| 41 | +### Title / description resolution priority |
| 42 | + |
| 43 | +When displaying a script card, title and summary are resolved in this order (see `flattenScripts()`): |
| 44 | +- **Title**: script meta `title:` → `readme.md` first line → filename (sans `.bat`/`.vbs`) |
| 45 | +- **Summary**: script meta `desc:` → first 3 lines of readme joined with `·` |
| 46 | + |
| 47 | +### API routes |
| 48 | + |
| 49 | +| Route | Method | Purpose | |
| 50 | +|-------|--------|---------| |
| 51 | +| `/` | GET | Render main page | |
| 52 | +| `/api/scan` | GET | Reload config, re-scan, return all items | |
| 53 | +| `/api/set-root` | POST | Change `scan_root` | |
| 54 | +| `/api/exclude-bats` | GET/POST | Query/update script filename exclude patterns | |
| 55 | +| `/api/exclude-script` | POST | Add/remove single-script exclusion by full path | |
| 56 | +| `/api/run-bat` | POST | Run script — `.bat` in a new `cmd` window (`chcp 65001`), `.vbs` via `wscript.exe` | |
| 57 | +| `/api/open-folder` | POST | Open folder in `explorer.exe` | |
| 58 | + |
| 59 | +## Platform Constraints |
| 60 | + |
| 61 | +- **Windows-only**: depends on `.bat`, `.vbs` (`wscript.exe`), `cmd`, `explorer.exe`, and Windows registry (see `add_startup.reg` / `remove_startup.reg`). |
| 62 | +- Paths use backslashes, normalized via `os.path.normpath`. |
| 63 | +- `startup.vbs` and `add_startup.reg` register a run-on-boot entry using a hardcoded Anaconda Python path — these are local conveniences, not portable. |
| 64 | + |
| 65 | +## Configuration — `config.json` |
| 66 | + |
| 67 | +- `scan_root` — directory to walk. |
| 68 | +- `exclude_dirs` — folder names to skip (also skips any dot-prefixed folder in `scan_directory`). |
| 69 | +- `exclude_bats` — filename patterns (`*`, `?`, `%`) that filter out script files (applies to both `.bat` and `.vbs`). |
| 70 | +- `exclude_scripts` — full paths to exclude specific scripts. |
| 71 | + |
| 72 | +## Dev Notes |
| 73 | + |
| 74 | +- Template edits require a server restart; CSS/JS changes only need a browser refresh. |
| 75 | +- Lucide icon names per script are chosen by keyword matching in `iconFor()` (`app.js`); default is `zap`. |
| 76 | +- Card colors are a deterministic hash of the folder+filename into a fixed palette (`colorFor()`). |
| 77 | +- README content is truncated to 3000 chars server-side; both metadata parsers (bat / vbs) only read the first 10 lines. |
| 78 | +- `inject_bat_meta.py` only injects `:: title:`/`:: desc:` into `.bat` files; it skips `.vbs` files (identified by the `type` field). |
0 commit comments