q00/ouroboros/welcome

Trust tier 2
  • community
LLM review pending
Source check pending

Checking that the SKILL.md file is still in the repository.

First-touch experience for new Ouroboros users

Install

npx vskill@latest install q00/ouroboros/welcome

SKILL.md

/ouroboros:welcome

Interactive onboarding for new Ouroboros users.

Usage

/ouroboros:welcome # First-time or update onboarding
/ouroboros:welcome --skip # Skip welcome, mark as shown
/ouroboros:welcome --force # Force re-run welcome even if shown

Instructions

Ask every question with the active runtime's ask_user capability, in the user's language. The Korean labels below are the canonical wording.

Python Runtime (Required)

Define this resolver in the same shell before any snippet below. It accepts only Python 3.12 or newer (python3, then python, then uv) and preserves arguments and stdin. Quote every argument passed to ouroboros_python.

<!-- ouroboros-python-resolver:start -->

bash
ouroboros_python() {
if command -v python3 >/dev/null 2>&1 &&
(unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python3 -c 'import sys; raise SystemExit(sys.version_info < (3, 12))') >/dev/null 2>&1
then
(unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python3 "$@")
return
fi
if command -v python >/dev/null 2>&1 &&
(unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python -c 'import sys; raise SystemExit(sys.version_info < (3, 12))') >/dev/null 2>&1
then
(unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command python "$@")
return
fi
if command -v uv >/dev/null 2>&1; then
(unset PYTHONHOME PYTHONPATH PYTHONPLATLIBDIR PYTHONEXECUTABLE __PYVENV_LAUNCHER__; command uv run --no-project --quiet --python '>=3.12' python "$@")
return
fi
printf '%s\n' 'Ouroboros skills require Python >= 3.12 or uv on PATH.' >&2
return 127
}

<!-- ouroboros-python-resolver:end -->

Pre-Check: Already Completed?

Run the resolver, this section's blocks, and the migration check below in one shell call, then print the result with printf 'completed=%s setup=%s codex=%s migration=%s\n' "$WELCOME_COMPLETED" "${SETUP_READY:-}" "${CODEX_READY:-}" "${LEGACY_CODEX_MODEL_MIGRATION_REQUIRED:-}".

Read the completion marker (legacy welcomeShown: true also counts):

bash
WELCOME_COMPLETED=$(ouroboros_python - <<'PY'
import json, os
try:
prefs = json.load(open(os.path.expanduser('~/.ouroboros/prefs.json'), encoding='utf-8'))
except Exception:
prefs = {}
if not isinstance(prefs, dict):
prefs = {}
print(prefs.get('welcomeCompleted') or ('legacy-welcomeShown' if prefs.get('welcomeShown') else ''))
PY
)

Before honoring that completion marker, determine whether setup is ready for the active runtime. A previously completed welcome must never hide the setup gate from a user who chose 나중에 or whose setup was later removed.

Claude Code is ready when ~/.ouroboros/config.yaml has orchestrator.runtime_backend in {claude, claude_mcp} and llm.backend: claude. The marketplace plugin owns its MCP registration, so host-owned ~/.claude/mcp.json is never part of readiness:

bash
if ouroboros_python - "$HOME/.ouroboros/config.yaml" <<'PY'
import sys
from pathlib import Path
try:
import yaml
except ModuleNotFoundError:
yaml = None
def scalar(raw: str) -> str:
return raw.strip().split(" #", 1)[0].strip().rstrip(",}").strip().strip("'\"")
def load_yaml(path: str) -> dict:
source = Path(path).read_text(encoding="utf-8")
if yaml is not None:
loaded = yaml.safe_load(source) or {}
return loaded if isinstance(loaded, dict) else {}
parsed: dict[str, dict[str, str]] = {}
section = None
for line in source.splitlines():
if not line.strip() or line.lstrip().startswith("#"):
continue
key, separator, value = line.strip().partition(":")
if not separator:
continue
key = key.strip("'\"")
if not line[0].isspace():
section = key
parsed[section] = {}
flow = value.strip().split(" #", 1)[0].strip()
if flow.startswith("{") and flow.endswith("}"):
for part in flow[1:-1].split(","):
field, separator, field_value = part.partition(":")
if separator:
parsed[section][field.strip().strip("'\"")] = scalar(field_value)
elif section is not None:
parsed[section][key] = scalar(value)
return parsed
try:
config = load_yaml(sys.argv[1])
except (OSError, ValueError):
raise SystemExit(1)
orchestrator, llm = config.get("orchestrator"), config.get("llm")
ready = (
isinstance(orchestrator, dict)
and orchestrator.get("runtime_backend") in {"claude", "claude_mcp"}
and isinstance(llm, dict)
and llm.get("backend") == "claude"
)
raise SystemExit(0 if ready else 1)
PY
then
SETUP_READY="true"
fi

If SETUP_READY is not true, check Codex. It is ready when both backends are codex, the Codex CLI (OUROBOROS_CODEX_CLI_PATH, else orchestrator.codex_cli_path, else codex on PATH) is runnable, and mcp_servers\.ouroboros in $CODEX_HOME/config.toml (any TOML key spelling) has a runnable command or a non-blank url:

bash
CODEX_HOME_DIR="${CODEX_HOME:-$HOME/.codex}"
case "$CODEX_HOME_DIR" in
"~") CODEX_HOME_DIR="$HOME" ;;
"~/"*) CODEX_HOME_DIR="$HOME/${CODEX_HOME_DIR#"~/"}" ;;
esac
if ouroboros_python - "$HOME/.ouroboros/config.yaml" "$CODEX_HOME_DIR/config.toml" <<'PY'
import os
import shutil
import sys
import tomllib
from pathlib import Path
try:
import yaml
except ModuleNotFoundError:
yaml = None
def scalar(raw: str) -> str:
return raw.strip().split(" #", 1)[0].strip().rstrip(",}").strip().strip("'\"")
def load_yaml(path: str) -> dict:
source = Path(path).read_text(encoding="utf-8")
if yaml is not None:
loaded = yaml.safe_load(source) or {}
return loaded if isinstance(loaded, dict) else {}
parsed: dict[str, dict[str, str]] = {}
section = None
for line in source.splitlines():
if not line.strip() or line.lstrip().startswith("#"):
continue
key, separator, value = line.strip().partition(":")
if not separator:
continue
key = key.strip("'\"")
if not line[0].isspace():
section = key
parsed[section] = {}
flow = value.strip().split(" #", 1)[0].strip()
if flow.startswith("{") and flow.endswith("}"):
for part in flow[1:-1].split(","):
field, separator, field_value = part.partition(":")
if separator:
parsed[section][field.strip().strip("'\"")] = scalar(field_value)
elif section is not None:
parsed[section][key] = scalar(value)
return parsed
def runnable(candidate: str) -> bool:
value = candidate.strip()
if not value:
return False
if "/" not in value:
return shutil.which(value) is not None
path = Path(value).expanduser()
return path.is_file() and os.access(path, os.X_OK)
def mcp_ready(entry: object) -> bool:
if not isinstance(entry, dict):
return False
command, url = entry.get("command"), entry.get("url")
if isinstance(command, str) and command.strip():
return runnable(command)
return isinstance(url, str) and bool(url.strip())
try:
config = load_yaml(sys.argv[1])
codex_config = tomllib.loads(Path(sys.argv[2]).read_text(encoding="utf-8"))
except (OSError, ValueError):
raise SystemExit(1)
orchestrator, llm = config.get("orchestrator"), config.get("llm")
servers = codex_config.get("mcp_servers")
cli_path = os.environ.get("OUROBOROS_CODEX_CLI_PATH")
if not cli_path and isinstance(orchestrator, dict):
cli_path = orchestrator.get("codex_cli_path")
if not isinstance(cli_path, str) or not cli_path.strip():
cli_path = "codex"
ready = (
isinstance(orchestrator, dict)
and orchestrator.get("runtime_backend") == "codex"
and isinstance(llm, dict)
and llm.get("backend") == "codex"
and runnable(cli_path)
and mcp_ready(servers.get("ouroboros") if isinstance(servers, dict) else None)
)
raise SystemExit(0 if ready else 1)
PY
then
CODEX_READY="true"
fi
Legacy Codex Model Migration

Older configurations saved gpt-5 into all four stage-model fields. That is now an explicit pin that stops Codex App/CLI model changes from taking effect. Never rewrite a possible user pin silently. When Codex is ready, detect that exact legacy shape (or an interrupted migration) once:

bash
if ouroboros_python - "$HOME/.ouroboros/config.yaml" "$HOME/.ouroboros/prefs.json" <<'PY'
from __future__ import annotations
import json
import sys
from pathlib import Path
config_path, prefs_path = map(Path, sys.argv[1:])
def yaml_mapping(source: str) -> dict[str, dict[str, str]]:
parsed: dict[str, dict[str, str]] = {}
section: str | None = None
for raw_line in source.splitlines():
if not raw_line.strip() or raw_line.lstrip().startswith("#"):
continue
indent = len(raw_line) - len(raw_line.lstrip())
key, separator, raw_value = raw_line.strip().partition(":")
if not separator:
continue
value = raw_value.strip().split(" #", 1)[0].strip().strip("'\"")
if indent == 0:
section = key.strip("'\"")
parsed.setdefault(section, {})
elif section is not None:
parsed[section][key.strip("'\"")] = value
return parsed
try:
config = yaml_mapping(config_path.read_text(encoding="utf-8"))
except OSError:
raise SystemExit(1)
try:
prefs = json.loads(prefs_path.read_text(encoding="utf-8"))
except (OSError, ValueError):
prefs = {}
if not isinstance(prefs, dict):
prefs = {}
stage_values = (
config.get("clarification", {}).get("default_model"),
config.get("execution", {}).get("default_model"),
config.get("evaluation", {}).get("semantic_model"),
config.get("resilience", {}).get("reflect_model"),
)
legacy_gpt5 = all(value == "gpt-5" for value in stage_values)
partial_automatic_migration = (
any(value == "gpt-5" for value in stage_values)
and any(value == "default" for value in stage_values)
and all(value in {"gpt-5", "default"} for value in stage_values)
)
handled = prefs.get("codexModelMigration") in {"automatic-v1", "kept-gpt-5-v1"}
raise SystemExit(0 if (legacy_gpt5 or partial_automatic_migration) and not handled else 1)
PY
then
LEGACY_CODEX_MODEL_MIGRATION_REQUIRED="true"
fi

If CODEX_READY and LEGACY_CODEX_MODEL_MIGRATION_REQUIRED are both true, ask "현재 설정은 모든 단계에서 gpt-5를 고정해 두고 있어요. Codex에서 선택한 모델을 자동으로 사용하도록 바꿀까요?" (header 모델 설정) with these options:

  • Codex 선택으로 전환하기 (권장): App이나 CLI에서 바꾼 모델을 모든 단계가 자동으로 따라가요.

Atomically rewrite the four pins:

bash
ouroboros_python - "$HOME/.ouroboros/config.yaml" <<'PY'
from __future__ import annotations
import os
import sys
import tempfile
from pathlib import Path

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewNot runA model review is scheduled for the next rescan.

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

7-day trend score
0

Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/q00/ouroboros/welcome/badge)](https://verified-skill.com/skills/q00/ouroboros/welcome)

Something wrong with this skill or its page? Tell us.