重构插件入口与runtime安装流程
This commit is contained in:
@@ -11,9 +11,12 @@ When this skill is invoked:
|
||||
|
||||
See `../../references/studio-docs/director-gates.md` for the full check pattern.
|
||||
|
||||
When a gate is active, spawn the named Codex custom agent that is already
|
||||
defined in `../../.codex/agents/<agent-name>.toml`. Do not recreate the
|
||||
director role by pasting profile text into a generic default agent.
|
||||
Director agent source files live in `../../runtime/agents/`. Before running
|
||||
any `full` review-mode gate, verify the target project has the matching
|
||||
`.codex/agents/<agent-name>.toml` files installed. If they are missing, run
|
||||
`$setup-runtime` for the project first. When a gate is active, spawn the
|
||||
named Codex custom agent; do not recreate the director role by pasting
|
||||
profile text into a generic default agent.
|
||||
|
||||
2. **Check for existing concept work**:
|
||||
- Read `design/gdd/game-concept.md` if it exists (resume, don't restart)
|
||||
@@ -24,13 +27,17 @@ When this skill is invoked:
|
||||
exploration** where the AI acts as a creative facilitator, not a replacement
|
||||
for the human's vision.
|
||||
|
||||
**Use `ask the user in chat`** at key decision points throughout brainstorming:
|
||||
**Use a structured decision prompt when available** at key decision points
|
||||
throughout brainstorming. In Codex, use the current user-input mechanism if
|
||||
it is available in the active mode; otherwise ask the same question directly
|
||||
in chat and wait for the user's reply.
|
||||
- Constrained taste questions (genre preferences, scope, team size)
|
||||
- Concept selection ("Which 2-3 concepts resonate?") after presenting options
|
||||
- Direction choices ("Develop further, explore more, or prototype?")
|
||||
- Pillar ranking after concepts are refined
|
||||
Write full creative analysis in conversation text first, then use
|
||||
`ask the user in chat` to capture the decision with concise labels.
|
||||
the structured prompt or chat question to capture the decision with concise
|
||||
labels.
|
||||
|
||||
Professional studio brainstorming principles to follow:
|
||||
- Withhold judgment — no idea is bad during exploration
|
||||
@@ -55,18 +62,19 @@ conversationally (not as a checklist):
|
||||
**Taste profile**:
|
||||
- What 3 games have you spent the most time with? What kept you coming back?
|
||||
*(Ask this as plain text — the user must be able to type specific game names freely.
|
||||
Do NOT put this in an ask the user in chat with preset options.)*
|
||||
Do NOT put this in a structured prompt with preset options.)*
|
||||
- Are there genres you love? Genres you avoid? Why?
|
||||
- Do you prefer games that challenge you, relax you, tell you stories,
|
||||
or let you express yourself? *(Use `ask the user in chat` for this — constrained choice.)*
|
||||
or let you express yourself? *(Use a structured prompt for this when available — constrained choice.)*
|
||||
|
||||
**Practical constraints** (shape the sandbox before brainstorming).
|
||||
Bundle these into a single multi-tab `ask the user in chat` with these exact tab labels:
|
||||
Bundle these into a single multi-field structured prompt when available:
|
||||
- Tab "Experience" — "What kind of experience do you most want players to have?" (Challenge & Mastery / Story & Discovery / Expression & Creativity / Relaxation & Flow)
|
||||
- Tab "Timeline" — "What's your realistic development timeline?" (Weeks / Months / 1-2 years / Multi-year)
|
||||
- Tab "Dev level" — "Where are you in your dev journey?" (First game / Shipped before / Professional background)
|
||||
|
||||
Use exactly these tab names — do not rename or duplicate them.
|
||||
If the UI supports grouping fields, use exactly these group names. If not,
|
||||
ask the three questions one at a time.
|
||||
|
||||
**Synthesize** the answers into a **Creative Brief** — a 3-5 sentence
|
||||
summary of the person's emotional goals, taste profile, and constraints.
|
||||
@@ -104,12 +112,13 @@ For each concept, present:
|
||||
- **Why It Could Work** (1 sentence on market/audience fit)
|
||||
- **Biggest Risk** (1 sentence on the hardest unanswered question)
|
||||
|
||||
Present all three. Then use `ask the user in chat` to capture the selection.
|
||||
Present all three. Then use a structured prompt or direct chat question to
|
||||
capture the selection.
|
||||
|
||||
**CRITICAL**: This MUST be a plain list call — no tabs, no form fields. Use exactly this structure:
|
||||
**CRITICAL**: This MUST be a plain list choice, not a multi-field form. Use this structure:
|
||||
|
||||
```
|
||||
ask the user in chat(
|
||||
structured decision prompt(
|
||||
prompt: "Which concept resonates with you? You can pick one, combine elements, or ask for fresh directions.",
|
||||
options: [
|
||||
"Concept 1 — [Title]",
|
||||
@@ -121,7 +130,7 @@ ask the user in chat(
|
||||
)
|
||||
```
|
||||
|
||||
Do NOT use a `tabs` field here. The `tabs` form is for multi-field input only — using it here causes an "Invalid tool parameters" error. This is a plain `prompt` + `options` call.
|
||||
Do NOT use a multi-field form here. This is a plain prompt plus options.
|
||||
|
||||
Never pressure toward a choice — let them sit with it.
|
||||
|
||||
@@ -135,7 +144,7 @@ isolation, no amount of content or polish will save the game.
|
||||
|
||||
**30-Second Loop** (moment-to-moment):
|
||||
|
||||
Ask these as `ask the user in chat` calls — derive the options from the chosen concept, don't hardcode them:
|
||||
Ask these as structured prompts when available — derive the options from the chosen concept, don't hardcode them:
|
||||
|
||||
1. **Core action feel** — prompt: "What's the primary feel of the core action?" Generate 3-4 options that fit the concept's genre and tone, plus a free-text escape (`I'll describe it`).
|
||||
|
||||
@@ -184,11 +193,11 @@ Then define **3+ anti-pillars** (what this game is NOT):
|
||||
be cool if..." features that don't serve the core vision
|
||||
- Frame as: "We will NOT do [thing] because it would compromise [pillar]"
|
||||
|
||||
**Pillar confirmation**: After presenting the full pillar set, use `ask the user in chat`:
|
||||
**Pillar confirmation**: After presenting the full pillar set, use a structured prompt:
|
||||
- Prompt: "Do these pillars feel right for your game?"
|
||||
- Options: `[A] Lock these in` / `[B] Rename or reframe one` / `[C] Swap a pillar out` / `[D] Something else`
|
||||
|
||||
If the user selects B, C, or D, make the revision, then use `ask the user in chat` again:
|
||||
If the user selects B, C, or D, make the revision, then use a structured prompt again:
|
||||
- Prompt: "Pillars updated. Ready to lock these in?"
|
||||
- Options: `[A] Lock these in` / `[B] Revise another pillar` / `[C] Something else`
|
||||
|
||||
@@ -207,7 +216,7 @@ Repeat until the user selects [A] Lock these in.
|
||||
- **`art-director`** — gate **AD-CONCEPT-VISUAL** (`../../references/studio-docs/director-gates.md`)
|
||||
Pass: game concept elevator pitch, full pillar set with design tests, target platform (if known), any reference games or visual touchstones the user mentioned.
|
||||
|
||||
Collect both verdicts, then present them together using a two-tab `ask the user in chat`:
|
||||
Collect both verdicts, then present them together using a structured prompt:
|
||||
- Tab **"Pillars"**: present creative-director feedback. Options mirror the standard CD-PILLARS handling — `Lock in as-is` / `Revise [specific pillar]` / `Discuss further`.
|
||||
- Tab **"Visual anchor"**: present the art-director's 2-3 named visual direction options. Options: each named direction (one per option) + `Combine elements across directions` + `Describe my own direction`.
|
||||
|
||||
@@ -236,12 +245,12 @@ who this game is actually for:
|
||||
|
||||
Ground the concept in reality:
|
||||
|
||||
- **Target platform**: Use `ask the user in chat` — "What platforms are you targeting for this game?"
|
||||
- **Target platform**: Use a structured prompt when available — "What platforms are you targeting for this game?"
|
||||
Options: `PC (Steam / Epic)` / `Mobile (iOS / Android)` / `Console` / `Web / Browser` / `Multiple platforms`
|
||||
Record the answer — it directly shapes the engine recommendation and will be passed to `/setup-engine`.
|
||||
Note platform implications if relevant (e.g., mobile means Unity is strongly preferred; console means Godot has limitations; web means Godot exports cleanly).
|
||||
|
||||
- **Engine experience**: Use `ask the user in chat` — "Do you already have an engine you work in?"
|
||||
- **Engine experience**: Use a structured prompt when available — "Do you already have an engine you work in?"
|
||||
Options: `Godot` / `Unity` / `Unreal Engine 5` / `No preference — help me decide`
|
||||
- If they pick an engine → record it as their preference and move on. Do NOT second-guess it.
|
||||
- If "No preference" → tell them: "Run `/setup-engine` after this session — it will walk you through the full decision based on your concept and platform target." Do not make a recommendation here.
|
||||
@@ -290,13 +299,13 @@ Present the assessment to the user. If UNREALISTIC, offer to adjust the MVP defi
|
||||
This section is the seed of the art bible — it captures the "everything must
|
||||
move" decision before it can be forgotten between sessions.
|
||||
|
||||
5. Use `ask the user in chat` for write approval:
|
||||
5. Use a structured prompt or direct chat question for write approval:
|
||||
- Prompt: "Game concept is ready. May I write it to `design/gdd/game-concept.md`?"
|
||||
- Options: `[A] Yes — write it` / `[B] Not yet — revise a section first`
|
||||
|
||||
If [B]: ask which section to revise using `ask the user in chat` with options: `Elevator Pitch` / `Core Fantasy & Unique Hook` / `Pillars` / `Core Loop` / `MVP Definition` / `Scope Tiers` / `Risks` / `Something else — I'll describe`
|
||||
If [B]: ask which section to revise using a structured prompt with options: `Elevator Pitch` / `Core Fantasy & Unique Hook` / `Pillars` / `Core Loop` / `MVP Definition` / `Scope Tiers` / `Risks` / `Something else — I'll describe`
|
||||
|
||||
After revising, show the updated section as a diff or clear before/after, then use `ask the user in chat` — "Ready to write the updated concept document?"
|
||||
After revising, show the updated section as a diff or clear before/after, then ask — "Ready to write the updated concept document?"
|
||||
Options: `[A] Yes — write it` / `[B] Revise another section`
|
||||
Repeat until the user selects [A].
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@ description: "Use when you need the /brainstorm game-production workflow. Guided
|
||||
|
||||
# Brainstorm
|
||||
|
||||
Run the `/brainstorm` Codex Game Studio workflow.
|
||||
Run the Codex Game Studios brainstorm workflow.
|
||||
|
||||
Before acting, read `DETAILS.md` for the full workflow. Apply project guidance from `AGENTS.md`, use `../../standards/` for path-specific standards, and use the pre-defined Codex custom agents in `../../.codex/agents/<agent-name>.toml` when the workflow delegates to a subagent.
|
||||
Before acting, read `DETAILS.md` for the full workflow. Apply project guidance from `AGENTS.md` and use `../../standards/` for path-specific standards.
|
||||
|
||||
Director gates use the bundled custom agents from `../../runtime/agents/`. If the current project does not already have those agents installed in `.codex/agents/`, run `$setup-runtime` first.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "Brainstorm"
|
||||
short_description: "Use when you need the /brainstorm game-production workflow. Guided game concept ideation — from zero idea to a structure"
|
||||
default_prompt: "Run /brainstorm for my game project."
|
||||
short_description: "Shape a game idea into a concept doc"
|
||||
default_prompt: "Use $brainstorm to shape my game concept."
|
||||
|
||||
23
skills/setup-runtime/SKILL.md
Normal file
23
skills/setup-runtime/SKILL.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
name: setup-runtime
|
||||
description: "Use when a user asks to initialize, install, or refresh the Codex Game Studios runtime in a game project. Installs bundled director custom agents into the target project's .codex/agents directory."
|
||||
---
|
||||
|
||||
# Setup Runtime
|
||||
|
||||
Install the Codex Game Studios runtime assets into the current game project.
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Treat the current working directory as the target project unless the user names another path.
|
||||
2. Run `scripts/install_codex_runtime.py <target-project>`.
|
||||
3. Report installed, unchanged, and conflicting agent files.
|
||||
4. If conflicts are reported, do not overwrite them unless the user explicitly asks for `--force`.
|
||||
|
||||
The installer copies runtime agents from the plugin's `runtime/agents/` directory to:
|
||||
|
||||
```text
|
||||
<target-project>/.codex/agents/
|
||||
```
|
||||
|
||||
The runtime currently contains only Codex custom-agent TOML files. It does not install hooks, rules, MCP servers, apps, or project templates.
|
||||
4
skills/setup-runtime/agents/openai.yaml
Normal file
4
skills/setup-runtime/agents/openai.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
interface:
|
||||
display_name: "Setup Runtime"
|
||||
short_description: "Install game-studio agents into a project"
|
||||
default_prompt: "Use $setup-runtime to initialize this game project."
|
||||
159
skills/setup-runtime/scripts/install_codex_runtime.py
Executable file
159
skills/setup-runtime/scripts/install_codex_runtime.py
Executable file
@@ -0,0 +1,159 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Install Codex Game Studios runtime files into a game project.
|
||||
|
||||
Current runtime scope:
|
||||
- Copy bundled Codex custom agents from this plugin's `runtime/agents/`
|
||||
directory into the target project's `.codex/agents/` directory.
|
||||
|
||||
This installer intentionally does not install hooks, rules, MCP servers, apps,
|
||||
or AGENTS.md templates yet.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import filecmp
|
||||
import shutil
|
||||
import sys
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def find_plugin_root(start: Path) -> Path:
|
||||
"""Walk upward until the Codex plugin manifest is found."""
|
||||
for candidate in [start, *start.parents]:
|
||||
if (candidate / ".codex-plugin" / "plugin.json").is_file():
|
||||
return candidate
|
||||
raise FileNotFoundError(
|
||||
f"Could not find .codex-plugin/plugin.json above: {start}"
|
||||
)
|
||||
|
||||
|
||||
PLUGIN_ROOT = find_plugin_root(Path(__file__).resolve())
|
||||
SOURCE_AGENTS_DIR = PLUGIN_ROOT / "runtime" / "agents"
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class InstallResult:
|
||||
installed: list[Path]
|
||||
unchanged: list[Path]
|
||||
conflicts: list[Path]
|
||||
|
||||
|
||||
def relative_to_target(path: Path, target: Path) -> str:
|
||||
try:
|
||||
return str(path.relative_to(target))
|
||||
except ValueError:
|
||||
return str(path)
|
||||
|
||||
|
||||
def discover_agent_files() -> list[Path]:
|
||||
if not SOURCE_AGENTS_DIR.exists():
|
||||
raise FileNotFoundError(f"Source agent directory not found: {SOURCE_AGENTS_DIR}")
|
||||
|
||||
agent_files = sorted(SOURCE_AGENTS_DIR.glob("*.toml"))
|
||||
if not agent_files:
|
||||
raise FileNotFoundError(f"No custom agent TOML files found in: {SOURCE_AGENTS_DIR}")
|
||||
|
||||
return agent_files
|
||||
|
||||
|
||||
def install_agents(target: Path, *, force: bool, dry_run: bool) -> InstallResult:
|
||||
agent_files = discover_agent_files()
|
||||
target_agents_dir = target / ".codex" / "agents"
|
||||
|
||||
planned: list[tuple[Path, Path]] = []
|
||||
unchanged: list[Path] = []
|
||||
conflicts: list[Path] = []
|
||||
|
||||
for source in agent_files:
|
||||
destination = target_agents_dir / source.name
|
||||
|
||||
if source.resolve() == destination.resolve():
|
||||
unchanged.append(destination)
|
||||
continue
|
||||
|
||||
if destination.exists():
|
||||
if filecmp.cmp(source, destination, shallow=False):
|
||||
unchanged.append(destination)
|
||||
continue
|
||||
|
||||
if not force:
|
||||
conflicts.append(destination)
|
||||
continue
|
||||
|
||||
planned.append((source, destination))
|
||||
|
||||
if conflicts and not force:
|
||||
return InstallResult(installed=[], unchanged=unchanged, conflicts=conflicts)
|
||||
|
||||
installed = [destination for _, destination in planned]
|
||||
if not dry_run:
|
||||
target_agents_dir.mkdir(parents=True, exist_ok=True)
|
||||
for source, destination in planned:
|
||||
shutil.copy2(source, destination)
|
||||
|
||||
return InstallResult(installed=installed, unchanged=unchanged, conflicts=conflicts)
|
||||
|
||||
|
||||
def print_path_list(label: str, paths: list[Path], target: Path) -> None:
|
||||
if not paths:
|
||||
return
|
||||
print(f"{label}:")
|
||||
for path in paths:
|
||||
print(f"- {relative_to_target(path, target)}")
|
||||
|
||||
|
||||
def parse_args() -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument(
|
||||
"target",
|
||||
nargs="?",
|
||||
default=".",
|
||||
help="Target game project root. Defaults to the current directory.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--force",
|
||||
action="store_true",
|
||||
help="Overwrite existing agent files when their content differs.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--dry-run",
|
||||
action="store_true",
|
||||
help="Show what would be installed without writing files.",
|
||||
)
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def main() -> int:
|
||||
args = parse_args()
|
||||
target = Path(args.target).expanduser().resolve()
|
||||
|
||||
print("Codex Game Studios runtime installer")
|
||||
print(f"Plugin root: {PLUGIN_ROOT}")
|
||||
print(f"Target project: {target}")
|
||||
print("Runtime scope: custom agents only")
|
||||
|
||||
try:
|
||||
result = install_agents(target, force=args.force, dry_run=args.dry_run)
|
||||
except FileNotFoundError as error:
|
||||
print(f"ERROR: {error}", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
print_path_list("Installed" if not args.dry_run else "Would install", result.installed, target)
|
||||
print_path_list("Unchanged", result.unchanged, target)
|
||||
print_path_list("Conflicts", result.conflicts, target)
|
||||
|
||||
if result.conflicts:
|
||||
print(
|
||||
"ERROR: Existing agent files differ. Re-run with --force to overwrite them.",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return 2
|
||||
|
||||
print("Done.")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
19
skills/using-codex-game-studios/SKILL.md
Normal file
19
skills/using-codex-game-studios/SKILL.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
name: using-codex-game-studios
|
||||
description: "Use when a user asks how the Codex Game Studios plugin is structured, what workflow to run next, how to initialize it, or how it differs from generic development workflow plugins."
|
||||
---
|
||||
|
||||
# Using Codex Game Studios
|
||||
|
||||
Codex Game Studios is a game-production plugin built around plugin-discovered skills, not global `~/.codex/skills` bridge folders.
|
||||
|
||||
## Entry Points
|
||||
|
||||
- Use `$setup-runtime` when a project needs the bundled director agents installed into `.codex/agents/`.
|
||||
- Use `$brainstorm` to turn a rough game idea into `design/gdd/game-concept.md`.
|
||||
- Use `runtime/agents/` as the plugin source of bundled custom agents.
|
||||
- Use `references/` and `standards/` only when the active workflow points to them.
|
||||
|
||||
## Design Rule
|
||||
|
||||
Do not rely on a global `~/.codex/skills/codex-game-studio` bridge. The installed plugin exposes its skills through `.codex-plugin/plugin.json` with `"skills": "./skills/"`, matching the normal Codex plugin layout.
|
||||
4
skills/using-codex-game-studios/agents/openai.yaml
Normal file
4
skills/using-codex-game-studios/agents/openai.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
interface:
|
||||
display_name: "Using Codex Game Studios"
|
||||
short_description: "Understand the game-studio plugin workflow"
|
||||
default_prompt: "Use $using-codex-game-studios to explain this plugin workflow."
|
||||
Reference in New Issue
Block a user