Keychron Keyboards Hardware Design
Work with Keychron's source-available CAD hardware design files (STEP/DXF/PDF) for keyboards and mice, including scripting, inventory management, and 3D printing workflows.
- Skill ID
- reason-machines/trending-skills/keychron-keyboards-hardware-design
- Publisher
- reason-machines
- Repository
- trending-skills
- Installs
- 0
- Files
- 1
- Synced
- Sep 23, 2026
Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.
reason-machines/trending-skills/keychron-keyboards-hardware-designInstalls these files- SKILL.md
What this skill tells the agent
Keychron Keyboards Hardware Design
Skill by ara.so — Daily 2026 Skills collection.
What This Project Is
Keychron's Keychron-Keyboards-Hardware-Design repository provides production-grade industrial design files for Keychron keyboards and mice. These are real CAD files — not approximations — covering cases, plates, stabilizers, encoders, keycaps, and full assembly models.
Formats included:
.stp/.step— STEP (ISO 10303) 3D solid models, importable in FreeCAD, Fusion 360, SolidWorks, CATIA, etc..dxf— 2D Drawing Exchange Format, used for plates and cutouts in laser cutting or CNC workflows.dwg— AutoCAD native drawing format.pdf— Dimensioned engineering drawings for reference
Series covered: | Series | Notable Models | |---|---| | Q Series | Q1–Q12, Q0 Plus, Q60, Q65 | | Q Pro Series | Q1 Pro–Q14 Pro | | Q HE Series | Q1 HE, Q3 HE, Q5 HE, Q6 HE | | K Pro Series | K1 Pro–K17 Pro | | K Max Series | K1 Max–K17 Max | | K HE Series | K2 HE–K10 HE | | L Series | L1, L3 | | V Max Series | V1 Max–V10 Max | | P HE Series | P1 HE | | Mice | M1–M7, G1, G2 |
License: Source-available. Personal, educational, and non-commercial use only. Commercial use is strictly prohibited.
Getting the Files
Clone the full repository
git clone https://github.com/Keychron/Keychron-Keyboards-Hardware-Design.git
cd Keychron-Keyboards-Hardware-DesignSparse checkout (single model, saves bandwidth)
git clone --filter=blob:none --sparse https://github.com/Keychron/Keychron-Keyboards-Hardware-Design.git
cd Keychron-Keyboards-Hardware-Design
git sparse-checkout set "Q-Series/Q1"Sparse checkout for a full series
git sparse-checkout set "K-Pro-Series"Directory Layout
Q-Series/
Q1/
Q1-Case.stp
Q1-Plate.stp
Q1-Encoder.stp
Q1-Stabilizer.stp
Q1-Full-Model.stp
Q1-OSA-Keycap.stp
Q-Pro-Series/
Q1 Pro/
Q1-Pro-Case.stp
Q1-Pro-Plate.dxf
...
K-Pro-Series/
K6 Pro/
K8 Pro/
K8-Pro-Keycap.stp
V-Max-Series/
V1 Max/
K-Max-Series/
K8 Max/
K8-Max-Keycap.stp
K-HE-Series/
K2 HE/
K2-HE-Cherry-Keycap.stp
K2-HE-OSA-Keycap.stp
Mice/
M1/
M1-Shell.stp
M1-Full-Model.stp
Keycap Profiles/
OSA Profile/
KSA Profile/
docs/
file-format-guide.md
getting-started.md
3d-printing-guide.md
repo-inventory.md
license-faq.mdPython Scripts for Working With the Repository
Inventory all design files
"""
inventory.py — Scan the repo and produce a structured inventory of all design files.
"""
import os
import json
from pathlib import Path
from collections import defaultdict
REPO_ROOT = Path(__file__).parent # adjust if running from elsewhere
SUPPORTED_EXTENSIONS = {".stp", ".step", ".dxf", ".dwg", ".pdf"}
def build_inventory(root: Path) -> dict:
inventory = defaultdict(lambda: defaultdict(list))
for path in sorted(root.rglob("*")):
if path.suffix.lower() in SUPPORTED_EXTENSIONS:
# Series = top-level folder; model = second-level folder
parts = path.relative_to(root).parts
series = parts[0] if len(parts) > 0 else "Unknown"
model = parts[1] if len(parts) > 1 else "Root"
inventory[series][model].append({
"file": path.name,
"format": path.suffix.lower().lstrip(".").upper(),
"size_kb": round(path.stat().st_size / 1024, 1),
"path": str(path.relative_to(root)),
})
return inventory
def print_summary(inventory: dict):
total_files = 0
for series, models in inventory.items():
series_count = sum(len(files) for files in models.values())
total_files += series_count
print(f"\n{series} ({len(models)} models, {series_count} files)")
for model, files in models.items():
formats = sorted({f["format"] for f in files})
print(f" {model}: {len(files)} files [{', '.join(formats)}]")
print(f"\nTotal: {total_files} design files across {len(inventory)} series")
if __name__ == "__main__":
inv = build_inventory(REPO_ROOT)
print_summary(inv)
# Optional: dump to JSON
with open("inventory.json", "w") as f:
json.dump(inv, f, indent=2)
print("\nInventory saved to inventory.json")Run it:
python inventory.pyFind all plate files (DXF) for laser cutting
"""
find_plates.py — List all DXF plate files suitable for laser cutting or CNC.
"""
from pathlib import Path
REPO_ROOT = Path(".")
def find_plates(root: Path):
results = []
for path in sorted(root.rglob("*.dxf")):
name_lower = path.name.lower()
if "plate" in name_lower:
results.append(path)
return results
if __name__ == "__main__":
plates = find_plates(REPO_ROOT)
print(f"Found {len(plates)} plate DXF files:\n")
for p in plates:
print(f" {p}")Search for a specific model's files
"""
find_model.py — Find all files for a given keyboard model.
Usage:
python find_model.py "Q8"
python find_model.py "K8 Pro"
python find_model.py "M3"
"""
import sys
from pathlib import Path
REPO_ROOT = Path(".")
def find_model_files(root: Path, query: str):
query_lower = query.lower().replace(" ", "")
matches = []
for path in sorted(root.rglob("*")):
if path.is_file():
# Check folder name or filename
normalized = str(path).lower().replace(" ", "").replace("-", "")
if query_lower.replace("-", "") in normalized:
matches.append(path)
return matches
if __name__ == "__main__":
query = " ".join(sys.argv[1:]) if len(sys.argv) > 1 else "Q8"
results = find_model_files(REPO_ROOT, query)
if not results:
print(f"No files found matching '{query}'")
else:
print(f"Files matching '{query}':\n")
for r in results:
print(f" {r}")Export an inventory CSV for spreadsheet use
"""
export_csv.py — Export a CSV of all design files with metadata.
"""
import csv
from pathlib import Path
REPO_ROOT = Path(".")
OUTPUT = Path("keychron_inventory.csv")
SUPPORTED_EXTENSIONS = {".stp", ".step", ".dxf", ".dwg", ".pdf"}
def export_csv(root: Path, output: Path):
rows = []
for path in sorted(root.rglob("*")):
if path.suffix.lower() in SUPPORTED_EXTENSIONS:
parts = path.relative_to(root).parts
series = parts[0] if len(parts) > 0 else ""
model = parts[1] if len(parts) > 1 else ""
component = _infer_component(path.name)
rows.append({
"series": series,
"model": model,
"component": component,
"filename": path.name,
"format": path.suffix.lower().lstrip(".").upper(),
"size_kb": round(path.stat().st_size / 1024, 1),
"relative_path": str(path.relative_to(root)),
})
with open(output, "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=rows[0].keys())
writer.writeheader()
writer.writerows(rows)
print(f"Exported {len(rows)} rows to {output}")
def _infer_component(filename: str) -> str:
name = filename.lower()
for keyword in ["case", "plate", "encoder", "stabilizer", "keycap",
"full-model", "full_model", "shell", "knob"]:
if keyword.replace("-", "") in name.replace("-", "").replace("_", ""):
return keyword.replace("-", " ").title()
return "Other"
if __name__ == "__main__":
export_csv(REPO_ROOT, OUTPUT)Validate repo file naming conventions
"""
validate_naming.py — Check that files follow Keychron naming conventions.
Expected pattern: <ModelName>-<Component>.<ext>
Example: Q8-Plate.stp, K8-Pro-Case.dxf
"""
import re
from pathlib import Path
REPO_ROOT = Path(".")More from reason-machines
Use this skill in a project
Open any RiverX project, search the Skills panel for reason-machines/trending-skills/keychron-keyboards-hardware-design, and install it in one click.
