بنقرة واحدة
compile
Compile a natural language script into a Python generator function for the mekara scripting runtime.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Compile a natural language script into a Python generator function for the mekara scripting runtime.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Merges completed work back to main through a protected-branch pull request workflow.
Set up a new git worktree and install dependencies.
Merges completed work back to main through a protected-branch pull request workflow.
Set up a new git worktree and install dependencies.
Prepares a Python package for PyPI release by updating the version, building, and verifying the distribution.
Prepare a release by updating the version, building, and verifying the distribution.
| name | compile |
| description | Compile a natural language script into a Python generator function for the mekara scripting runtime. |
You are compiling a natural language script into a Python generator function for the mekara scripting runtime.
$ARGUMENTS
The source script is at $ARGUMENTS.
Use the runtime and API guidance below when translating the natural language source into a Python generator script.
Generate a Python file that:
auto, call_script, and llm from mekara.scripting.runtimeexecute (all scripts use the same standard entry point name). This function:
request: str parameter - the mekara runtime always passes this argument, even if the script doesn't use ityield auto(...) for deterministic automationyield llm(...) for anything requiring LLM judgmentyield call_script(...) when the script explicitly instructs invoking another script (for example, "Run /finish <request>.")The compiled file is always named mekara.py and lives inside the same skill folder as SKILL.md (e.g., .agents/skills/finish/mekara.py, or nested: .agents/skills/git/finish/mekara.py).
auto Primitiveauto supports two forms and requires a context parameter that explains WHY the step runs:
Shell commands - pass a string with context:
yield auto("git status", context="Check working tree status")
yield auto(f"git worktree add -b mekara/{branch} ../{branch}", context="Create worktree for new branch")
Python functions - pass a callable with kwargs dict and context:
yield auto(my_function, {"arg1": value1, "arg2": value2}, context="Process input data")
yield auto(process_file, {"path": filepath, "mode": "read"}, context="Read configuration file")
Note: auto only supports keyword arguments, not positional args. For functions like print that take positional args, define a wrapper:
def _print_message(message: str) -> None:
print(message)
# Then use:
yield auto(_print_message, {"message": "Hello!"}, context="Display greeting to user")
allow_failure ParameterWhen a non-zero exit code is part of the information a command returns rather than an error signal, use allow_failure=True. The generator receives the ShellResult with success, exit_code, and output fields:
# git ls-remote --exit-code exits 0 if remote exists, 2 if not
result = yield auto("git ls-remote --exit-code origin", context="Check if remote is configured", allow_failure=True)
has_remote = result.exit_code == 0
# git show-ref --verify --quiet exits 0 if branch exists, 1 if not
result = yield auto("git show-ref --verify --quiet refs/heads/main", context="Check if main branch exists", allow_failure=True)
branch_exists = result.exit_code == 0
# git merge-base --is-ancestor exits 0 if A is ancestor of B, 1 if not
result = yield auto(f"git merge-base --is-ancestor {commit_a} {commit_b}", context="Check ancestry", allow_failure=True)
is_ancestor = result.exit_code == 0
Without allow_failure=True, any non-zero exit halts execution and hands control to the LLM as an error.
context ParameterThe context parameter is required for all auto steps. It should be the verbatim text from the source script that explains what the step does. This context is shown to the LLM when:
Good context (verbatim from source):
# Source: "2. Install dependencies after merging"
yield auto("poetry install", context="Install dependencies after merging")
# Source: "3. Install documentation dependencies with `pnpm --dir docs/ i --frozen-lockfile`. (Note: this must run after installing Python dependencies.)"
yield auto(f"cd ../{branch} && pnpm --dir docs/ i --frozen-lockfile", context="Install documentation dependencies with `pnpm --dir docs/ i --frozen-lockfile`. (Note: this must run after installing Python dependencies.)")
Bad context (paraphrased, truncated, or invented):
# Don't invent or paraphrase - use the original text
yield auto("poetry install", context="Run poetry") # Too terse
yield auto("poetry install", context="Installing Python packages using Poetry package manager") # Invented
# DON'T truncate - include ALL text from the source, including parenthetical notes
# Source has: "...with `pnpm --dir docs/ i --frozen-lockfile`. (Note: this must run...)"
yield auto(..., context="Install docs dependencies") # WRONG - truncated the Note
yield auto(..., context="Install documentation dependencies with `pnpm --dir docs/ i --frozen-lockfile`") # WRONG - still missing the Note
Verbatim means COMPLETE: Copy the entire step text, including parenthetical notes, explanatory clauses, and any additional context. If the source says "Do X. (Note: Y happens because Z.)", the context must include the full sentence with the parenthetical. This rule applies equally to llm prompts—if the source says "Whether the repo is public or private (default to private)", the LLM prompt must include "(default to private)", not just "Whether the repo is public or private".
Break long lines using Python string concatenation: If pre-commit checks are complaining about the 100-character line limit, then use Python's implicit string concatenation to break long strings across multiple lines without adding whitespace to the string content:
# Good - strings concatenated, newlines explicit with \n
yield llm(
"Identify the CI job names from the workflows on the docs branch "
"(in ../docs/.github/workflows/). These will be used as required "
"status checks.\n\n"
"**Important:** If a workflow uses a matrix strategy, the status "
"check name will be `<job-name> (<matrix-value>)`."
)
# Bad - line too long
yield llm(
"""Identify the CI job names from the workflows on the docs branch (in ../docs/.github/workflows/). These will be used as required status checks."""
)
Watch for indented continuation paragraphs: In markdown, an indented paragraph following a numbered step is part of that step. For example:
13. Run `cleanup-command` to finish.
If this succeeds, you'll see errors because the directory no longer exists.
This is expected - stop and tell the user you're done.
Both paragraphs belong to step 13. The context must include the indented continuation text, not just the first line.
When you need to reuse multiple auto steps together (e.g., a sequence of shell commands), extract them into a helper generator function and call it with yield from:
from typing import Generator
from mekara.scripting.runtime import Auto, ShellResult, auto, llm
def _verify_and_merge(pr_number: str) -> Generator[Auto, ShellResult, None]:
"""Helper that yields multiple auto steps."""
result = yield auto(f"gh pr view {pr_number} --json state", context="Check PR state")
if json.loads(result.output)["state"] != "MERGED":
raise RuntimeError("PR not merged")
# In execute():
yield from _verify_and_merge(pr_number) # Delegates all yielded steps
Typing: Helper generators must be typed as Generator[Auto, ShellResult, None]:
Auto = what we yield (the auto step)ShellResult = what yield returns (so pyright knows result.output exists)None = what the generator returns when doneImport Auto and ShellResult from mekara.scripting.runtime.
Do NOT wrap helper generators in auto():
# WRONG
yield auto(_verify_and_merge, {"pr_number": pr_number}, context="...")
auto returns:
ShellResult for shell commands: success, exit_code, outputCallResult for Python functions: success, value, error, outputllm returns:
LlmResult: success, outputs (dict of named values)call_script returns:
ScriptCallResult: success, exceptionWhen an llm step needs to produce a value for later steps, specify expected outputs:
result = yield llm(
"Generate a branch name based on the request",
expects={"branch": "short kebab-case branch name (2-3 words)"}
)
branch = result.outputs["branch"]
yield auto(f"git checkout -b {branch}", context="Create new branch")
The expects dict maps output keys to descriptions. The mekara runtime:
Use auto for:
llmauto with a Python function that raises an error on failure. Errors automatically fall back to the LLM to handle and consult the user.Use llm for:
Use call_script for:
/script-name..." (e.g., "Run /finish to create the PR")/script-name command" (e.g., "by running the /merge-main command")/script-name reference with action words like "run", "running"call_script parameters:
yield call_script("script-name", request="optional request text")
yield call_script("script-name", working_dir=Path("/different/directory")) # Override working dir
By default, nested scripts inherit the parent's working directory. Use working_dir to override this when the nested script needs to run in a different directory (e.g., a different worktree).
When a later step needs a value from a command's output (e.g., "use <pr-number> from the previous step"):
Do: Parse the value from output using simple Python string operations:
# gh pr create outputs the PR URL, e.g., "https://github.com/owner/repo/pull/22"
pr_result = yield auto("gh pr create --base main --fill", context="Create pull request")
pr_url = pr_result.output.strip()
pr_number = pr_url.rstrip('/').split('/')[-1] # Extract "22" from URL
yield auto(f"gh pr merge {pr_number} --auto --squash", context="Enable auto-merge on PR")
Don't: Add flags to commands hoping to get structured output:
# WRONG - gh pr create doesn't support --json
pr_result = yield auto("gh pr create --base main --fill --json number,url", context="...")
If you're unsure whether a command supports a flag, use the command exactly as written in the source and parse its natural output.
When unsure about output format, test it:
--dry-run if available, or create a test case)command 2>/dev/null to see only stdout)# gh pr create outputs only the PR URL to stdout)llm just because parsing seems uncertain - that's lazy. Test first, then write deterministic parsing code.When a step checks a condition to decide whether to execute subsequent steps, use auto with a Python function that returns a boolean, then use an if statement:
def _check_pr_merged(pr_state_str: str) -> bool:
"""Check if the PR has been merged.
Returns True if the PR state is not MERGED (needs intervention).
"""
import json
pr_data = json.loads(pr_state_str)
return pr_data["state"] != "MERGED"
# In the script:
# gh pr view outputs JSON like: {"state":"MERGED"}
pr_state_str = auto(f"gh pr view {pr_number} --json state")
verify_result = yield auto(
_check_pr_merged,
{"pr_state_str": pr_state_str},
context="Once checks pass, the PR should auto-merge. Verify the PR state with `gh pr view <pr-number> --json state` to confirm it merged. If the PR state is unexpected, wait to confirm next steps with the user instead of continuing.",
)
if verify_result.value:
yield llm("The PR state is unexpected. Check the status and confirm next steps with the user.")
This pattern is efficient: when the check passes (no action needed), execution continues without invoking the LLM. Only invoke the LLM when there's actual work to do.
When parts of the original script instructions are intentionally omitted from the compiled output (e.g., exception handling that falls back to the LLM, or context only visible during LLM interactions), mark them with a comment:
# Original instruction includes: "If X happens, do Y"
# This exception is handled by the LLM when the command fails
yield auto("command", context="Run the command")
This preserves the original context for future reference while explaining why it's not in the compiled code.
.agents/skills/<name>/mekara.py, co-located with the source SKILL.md.execute(request: str) entry point expected by the mekara runtime.Read the source script.
Analyze each step to determine if it's auto or llm.
Generate the Python code following the format above.
Check if the compiled script already exists - use Read to examine the existing .agents/skills/<name>/mekara.py file (if it exists) before writing. This avoids failed write attempts and allows you to identify exactly what changed between the source and compiled versions. Only write/edit if changes are needed.
Verify wording matches exactly - before finalizing edits, spot-check that the source .md and compiled .py contain identical wording in contexts, prompts, and helper text. Don't just assume changes are correct—read back what you edited to catch truncation, paraphrasing, or wording drift.
Write the output to .agents/skills/<name>/mekara.py.
If any changes to the workflow were made during compilation (e.g., adding merge conflict handling, clarifying ambiguous steps), update the original source script in .agents/skills/ to match.
Report what was compiled and wait for user feedback. Do not proceed to the commit until the user has explicitly given the go-ahead. Do not call mcp__mekara__continue -- this is for natural-language script completion, not for continuing to the next step of a natural language script.
Commit both the source .md file and the compiled .py file together - when updating a mekara script, always commit the source and compiled versions in the same commit to keep them synchronized.
llm for "tell the user X" when X is fully known (no synthesis of information needed) - use auto with a print function insteadllm call - separate the LLM judgment (e.g., "generate branch name") from the deterministic action (e.g., git checkout -b {branch_name})auto, even if a previous step required llm to determine a value used in Xgh pr create --base main --fill, use exactly that command. Don't add flags like --json that aren't in the original. Not all CLI tools support all flags (e.g., gh pr create doesn't support --json even though other gh commands do).gh pr checks --watch", just run the command—don't add a helper function to print "Waiting for CI..." first.auto step with a Python function instead. For example, check if a repo exists with gh repo view rather than asking the LLM.auto steps - in the expects dict, only extract values that will be used in subsequent auto steps. Don't extract values that are only used in other LLM steps, since the LLM already has access to the full conversation history and can infer that information.auto() to execute shell commands. The auto() primitive handles execution, output capture, and error handling.commit_subject and workflow_descriptions to build a commit message for git commit, just have the LLM run git commit directly with the full message. (git add -A and git push can still be auto in this scenario.)auto steps - when the same LLM-generated values are needed in multiple subsequent auto steps, have the LLM produce them via expects, then use them in the auto steps. For example, if step 9 creates a PR with a title/body and step 10 needs those same values for a merge command, have the LLM produce pr_title and pr_body just once, then use them in both gh pr create and gh pr merge auto steps. This is different from "unnecessary indirection" because the values are genuinely reused.auto steps - if a specific file's contents will be needed by a subsequent LLM step, read it with cat so that the LLM won't have to spend an extra cycle making the read action.main and docs), define a parameterized function (e.g., with a branch parameter) rather than copy-pasting the auto steps and changing one value. When there are multiple shell commands to execute, do NOT use subprocess.run and do NOT duplicate code—use a helper generator function with yield from instead (see "Helper Generator Functions" above).null. Simply running a jq command without consuming the output is an anti-pattern that doesn't do anything.Source (start.md):
1. Parse the user's request to generate a branch name
2. Create worktree with `git worktree add -b mekara/<branch> ../<branch>`
3. Install Python dependencies with `poetry install --with dev`
4. Tell the user the final instructions
Output (.agents/skills/start/mekara.py - for a nested skill like .agents/skills/git/finish/SKILL.md the output is .agents/skills/git/finish/mekara.py):
"""Auto-generated script. Source: .agents/skills/start/SKILL.md"""
from mekara.scripting.runtime import auto, call_script, llm
def execute(request: str):
"""Script entry point."""
result = yield llm(
"Parse the user's request and generate a suitable branch name (2-3 words)",
expects={"branch": "short kebab-case branch name"}
)
branch = result.outputs["branch"]
yield auto(f"git worktree add -b mekara/{branch} ../{branch}", context="Create worktree")
yield auto("poetry install --with dev", context="Install Python dependencies")
yield llm("Tell the user the final instructions for starting work")
yield call_script("finish", request="Summarize the changes")