1"""ll-adapt-skills-for-codex: thin alias for ``ll-adapt --host codex`` (skills + commands).

2

3 The implementation now lives in :mod:`little_loops.adapters.codex` and

4:mod:`little_loops.adapters.core`. This module is kept for backward

5 compatibility; it re-exports the original helper names used by tests and

6 delegates processing to :class:`~little_loops.adapters.codex.CodexEmitter`.

7"""

8

9 from __future__ import annotations

10

11 import argparse

12 import sys

13 from pathlib import Path

14

15 from little_loops.adapters.codex import (

16 CodexEmitter,

17 _extract_skill_short_desc as _extract_short_desc,

18 _insert_skill_fields as _insert_fields,

19 _make_openai_yaml_content as _make_openai_yaml,

20 _synthesized_skill_md,

21 _title_case,

22)

23 from little_loops.adapters.core import process_commands as _core_process_commands

24 from little_loops.adapters.core import process_skills as _core_process_skills

25 from little_loops.session_store import DEFAULT_DB_PATH, cli_event_context

26

27__all__ = ["main_adapt_skills_for_codex"]

28

29

30 def _find_plugin_root() -> Path:

31 from little_loops.skill_expander import _find_plugin_root as _fpr

32

33 return _fpr()

34

35

36# ---------------------------------------------------------------------------

37# Backward-compat process wrappers (original 3/4-arg signatures)

38# ---------------------------------------------------------------------------

39

40

41 def _process_skills(

42 skills_dir: Path, apply: bool, quiet: bool

43) -> tuple[int, int, int]:

44 """Backward-compat wrapper: delegate to core traversal + CodexEmitter."""

45 return _core_process_skills(CodexEmitter(), skills_dir, apply, quiet)

46

47

48 def _process_commands(

49 commands_dir: Path, skills_dir: Path, apply: bool, quiet: bool

50) -> tuple[int, int, int]:

51 """Backward-compat wrapper: delegate to core traversal + CodexEmitter."""

52 return _core_process_commands(CodexEmitter(), commands_dir, skills_dir, apply, quiet)

53

54

55# ---------------------------------------------------------------------------

56# CLI entry point

57# ---------------------------------------------------------------------------

58

59

60 def main_adapt_skills_for_codex() -> int:

61 """Entry point for ll-adapt-skills-for-codex CLI."""

62 with cli_event_context(DEFAULT_DB_PATH, "ll-adapt-skills-for-codex", sys.argv[1:]):

63 parser = argparse.ArgumentParser(

64 prog="ll-adapt-skills-for-codex",

65 description=(

66 "Add Codex Skills API frontmatter to ll skill SKILL.md files and "

67 "bridge commands/*.md into skills/ll-<name>/ entries for Codex CLI. "

68 "Dry-run by default; use --apply to write changes. "

69 "(Thin alias for: ll-adapt --host codex)"

70 ),

71 formatter_class=argparse.RawDescriptionHelpFormatter,

72 epilog="""

73 Examples:

74 ll-adapt-skills-for-codex # Dry-run: preview proposed changes

75 ll-adapt-skills-for-codex --apply # Write skill frontmatter + bridge commands

76 ll-adapt-skills-for-codex --quiet # Suppress per-entry output

77""",

78 )

79 parser.add_argument(

80 "--apply",

81 action="store_true",

82 default=False,

83 help="Write changes to SKILL.md files and create agents/openai.yaml (default: dry-run)",

84 )

85 parser.add_argument(

86 "--quiet",

87 action="store_true",

88 default=False,

89 help="Suppress per-skill output; only print final summary",

90 )

91

92 args = parser.parse_args()

93

94 plugin_root = _find_plugin_root()

95 skills_dir = plugin_root / "skills"

96 commands_dir = plugin_root / "commands"

97

98 if not skills_dir.exists():

99 print(f"ERROR: skills directory not found: {skills_dir}", file=sys.stderr)

100 return 1

101

102 mode = "APPLY" if args.apply else "DRY-RUN"

103 if not args.quiet:

104 print(f"ll-adapt-skills-for-codex [{mode}]")

105 print(f"Skills dir: {skills_dir}")

106 print(f"Commands dir: {commands_dir}")

107 print()

108

109 s_adapted, s_skipped, s_errors = _process_skills(skills_dir, args.apply, args.quiet)

110 c_adapted, c_skipped, c_errors = _process_commands(

111 commands_dir, skills_dir, args.apply, args.quiet

112 )

113

114 adapted = s_adapted + c_adapted

115 skipped = s_skipped + c_skipped

116 errors = s_errors + c_errors

117

118 print(f"\nDone: {adapted} adapted, {skipped} skipped, {errors} errors")

119 return 0 if errors == 0 else 1