diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
new file mode 100644
index 0000000..fefd16a
--- /dev/null
+++ b/.github/copilot-instructions.md
@@ -0,0 +1,87 @@
+# Copilot instructions for shopdb-flask
+
+Follow these when suggesting code. They are enforced by a naming/style hook and
+by CI (`.github/workflows/ci.yml`) - suggestions that break them fail the build.
+`CONTRIBUTING.md` is the full authority; this is the short version.
+
+## Naming (LOCKED - the hook rejects violations)
+
+- **DB tables**: lowercase, concatenated, plural. No underscores, no dashes.
+ `machines`, `networkdevices`, `businessunits` - NOT `machine_types`, `BusinessUnits`.
+- **DB columns**: lowercase, concatenated, singular. No underscores.
+ `machineid`, `lastzabbixsync`, `isactive` - NOT `machine_id`, `last_zabbix_sync`.
+- **Foreign keys**: referenced table (singular) + `id`: `locationid`, `vendorid`.
+- **Booleans**: `is`/`has` prefix: `isactive`, `isshopfloor`.
+- **Index names**: `idx_
_` (underscores allowed here only).
+
+### Python
+
+- A variable, attribute, function, or dict key that holds a DB value MUST match
+ the column name exactly - do NOT convert to snake_case.
+ Column `machineid` -> `Machine.machineid`, `{"machineid": 1}`, local `machineid`.
+- Pure code that does NOT mirror a DB field uses normal snake_case (PEP 8):
+ `loop_count`, `current_user`, `validate_input()`.
+- Classes: PascalCase, spelled out (`NetworkDevice`, `AssetType`).
+
+### JavaScript / Vue
+
+- A JS variable holding an API field value matches the API key exactly - do NOT
+ camelCase it. API `{"machineid": 1}` -> `response.machineid`, never `machineId`.
+- Components: PascalCase (`AssetDetail.vue`). CSS classes: lowercase-with-dashes.
+
+### API
+
+- Endpoints: lowercase plural nouns, no underscores/dashes: `/api/networkdevices`.
+- Query params + response keys match column names: `?locationid=5`,
+ `{"machineid": 1, "lastzabbixsync": "..."}`.
+
+### Allowed acronyms only
+
+Universal: id url api http https json jwt sql os ip dns csv pdf cors ttl uuid
+html css orm. Domain: cmm cnc pc usb vnc winrm ssh ssl tls tcp udp smtp ldap
+vlan sso dnc focas clm mtconnect. Anything else: spell it out.
+
+### Banned shorthand
+
+Never use `cfg ctx mgr req res env util helper` or `db` as a standalone variable
+name. Spell out: `config context manager request response environment utilities`.
+`_bp` is fine only as a suffix with a meaningful prefix (`printers_bp`).
+
+## Style (ASCII only)
+
+- NO emojis anywhere - code, comments, strings, UI.
+- NO em-dashes, en-dashes, Unicode arrows, or smart quotes. Plain ASCII only.
+- Comments default to NONE. Add one only when the WHY is non-obvious; keep inline
+ `#`/`//` comments terse. Docstrings stay normal English.
+- Dark theme is the default; keep UI functional and professional.
+
+## Architecture (do not violate)
+
+- **Plugins are the product.** Plugin code lives in `plugins//{models,api,services,schemas}/`
+ with a `manifest.json` (single source of truth: name, version, dependencies,
+ api_prefix) and a `BasePlugin` subclass in `plugin.py`.
+- **Plugins never import core internals.** Use the contract surface `shopdb.api`
+ (e.g. `from shopdb.api import db, Asset, success_response`). Adding to that
+ surface is a contract-version bump + a `docs/PLUGIN-HOOKS` update in the same PR.
+- **Migrations, never `db.create_all()`.** The core Alembic chain is in
+ `migrations/versions/`; each plugin owns its own chain under
+ `plugins//migrations/`. New schema = a new migration with an idempotent
+ guard and a real downgrade. Migrations must run clean on strict MySQL 8.
+- **Asset model is the platform contract.** Physical things are an `Asset` plus a
+ plugin subtype row linked by `assetid` (FK, `ON DELETE CASCADE`). Consumables
+ with quantities are standalone tables, not assets.
+- **Ledger pattern**: a cached `quantityonhand` moves in the SAME commit as the
+ signed transaction row it reflects.
+
+## Before you finish a change
+
+Run the three gates (CI runs the same):
+
+```
+python -m pytest tests/ -q
+cd frontend && npx vitest run && npm run build && cd ..
+bash scripts/check-naming-and-style.sh
+```
+
+Commits: short present-tense subject, body says WHY. No AI/tool attribution in
+commit messages, code comments, or docs.