Skip to content

Commands API

New Command

ok_cli.commands.new

Functions

new(name)

Create a new React Native app.

Source code in ok_cli/commands/new/__init__.py
def new(name: str):
    """Create a new React Native app."""
    typer.echo(f"🚀 Creating app '{name}'...")
    try:
        run_copy(
            TEMPLATE_PATH,
            name,
            data={"project_slug": name},
            quiet=True,
        )
        typer.echo(f"✅ App '{name}' created successfully!")
    except Exception as e:
        typer.echo(f"❌ Error creating app: {str(e)}", err=True)
        raise typer.Exit(code=1)

Generate Command

ok_cli.commands.generate

Functions

generate(type, name)

Generate a component, service, or page.

Source code in ok_cli/commands/generate/__init__.py
def generate(type: str, name: str):
    """Generate a component, service, or page."""
    type = type.lower()
    if type not in TEMPLATES:
        typer.echo("❌ Invalid type. Use one of: component, service, page.")
        return

    template_path = TEMPLATES[type]
    if not os.path.exists(template_path):
        typer.echo(f"❌ Template '{type}' not found at {template_path}")
        return

    typer.echo(f"✨ Generating {type}: {name}")
    try:
        run_copy(
            template_path,
            name,
            data={"name": name},
            quiet=True,
        )
        typer.echo(f"✅ {type.capitalize()} '{name}' generated successfully!")
    except Exception as e:
        typer.echo(f"❌ Error generating {type}: {str(e)}", err=True)
        raise typer.Exit(code=1)

Other Commands

ok_cli.commands.add

Functions

add(collection)

Add support for an external library.

Source code in ok_cli/commands/add/__init__.py
4
5
6
7
def add(collection: str):
    """Add support for an external library."""
    typer.echo(f"📦 Installing {collection} via npm...")
    subprocess.run(["npm", "install", collection])

ok_cli.commands.analytics

Functions

analytics()

Toggle analytics (placeholder).

Source code in ok_cli/commands/analytics/__init__.py
3
4
5
def analytics():
    """Toggle analytics (placeholder)."""
    typer.echo("📊 Analytics are not implemented, but could be tracked in the future.")

ok_cli.commands.cache

Functions

cache(clear=typer.Option(False, '--clear', help='Clear cache directory'))

Configure or clear build cache.

Source code in ok_cli/commands/cache/__init__.py
def cache(clear: bool = typer.Option(False, "--clear", help="Clear cache directory")):
    """Configure or clear build cache."""
    if clear:
        if os.path.exists(CACHE_DIR):
            shutil.rmtree(CACHE_DIR)
            typer.echo("🧹 Expo cache cleared.")
        else:
            typer.echo("⚠️ No cache directory found.")
    else:
        typer.echo(f"📂 Cache directory: {CACHE_DIR}")

ok_cli.commands.compilemessages

Functions

compilemessages(locale=typer.Option(None, '--locale', '-l', help='Specifies the locale(s) to process'), exclude=typer.Option(None, '--exclude', '-x', help='Specifies the locale(s) to exclude from processing'), use_fuzzy=typer.Option(False, '--use-fuzzy', '-f', help='Includes fuzzy translations into compiled files (by default lingui compiles strictly, rejecting fuzzy)'), ignore=typer.Option(None, '--ignore', '-i', help='Ignores directories matching the given glob-style pattern (Django gettext option; not used by lingui)'))

Compile .po files to .js/.ts catalogs via lingui compile.

Mimics Django's compilemessages command but uses lingui under the hood.

Source code in ok_cli/commands/compilemessages/__init__.py
def compilemessages(
    locale: Optional[List[str]] = typer.Option(
        None, "--locale", "-l", help="Specifies the locale(s) to process"
    ),
    exclude: Optional[List[str]] = typer.Option(
        None, "--exclude", "-x", help="Specifies the locale(s) to exclude from processing"
    ),
    use_fuzzy: bool = typer.Option(
        False, "--use-fuzzy", "-f", help="Includes fuzzy translations into compiled files "
        "(by default lingui compiles strictly, rejecting fuzzy)"
    ),
    ignore: Optional[List[str]] = typer.Option(
        None, "--ignore", "-i", help="Ignores directories matching the given glob-style pattern "
        "(Django gettext option; not used by lingui)"
    ),
):
    """Compile .po files to .js/.ts catalogs via lingui compile.

    Mimics Django's compilemessages command but uses lingui under the hood.
    """
    cmd = ["npx", "--yes", "@lingui/cli", "compile"]

    if locale:
        for loc in locale:
            cmd.extend(["--locale", loc])

    if not use_fuzzy:
        cmd.append("--strict")

    typer.echo(f"🔍 Running: {' '.join(cmd)}")
    result = subprocess.run(cmd, check=False)
    raise typer.Exit(code=result.returncode)

ok_cli.commands.completion

Functions

completion()

Set up shell autocompletion (for bash/zsh).

Source code in ok_cli/commands/completion/__init__.py
4
5
6
7
def completion():
    """Set up shell autocompletion (for bash/zsh)."""
    typer.echo("⚙️ Add this to your ~/.bashrc or ~/.zshrc:\n")
    typer.echo('  eval "$(_RN_CLI_COMPLETE=source_bash rn)"')

ok_cli.commands.config

Functions

config(key=None)

Show config (reads from package.json or .env).

Source code in ok_cli/commands/config/__init__.py
def config(key: Optional[str] = None):
    """Show config (reads from package.json or .env)."""
    import json
    try:
        with open("package.json") as f:
            pkg = json.load(f)
        if key:
            typer.echo(pkg.get(key, f"Key '{key}' not found"))
        else:
            typer.echo(json.dumps(pkg, indent=2))
    except FileNotFoundError:
        typer.echo("❌ package.json not found.")

ok_cli.commands.deploy

Functions

deploy()

Deploy app (e.g., using EAS Submit or Expo updates).

Source code in ok_cli/commands/deploy/__init__.py
5
6
7
8
9
def deploy():
    """Deploy app (e.g., using EAS Submit or Expo updates)."""
    typer.echo("🚀 Deploying app (placeholder)...")
    # Replace with real deploy command
    subprocess.run(["echo", "Deploy logic here..."], check=False)

ok_cli.commands.e2e

Functions

e2e()

Run end-to-end tests (e.g., Detox).

Source code in ok_cli/commands/e2e/__init__.py
5
6
7
8
9
def e2e():
    """Run end-to-end tests (e.g., Detox)."""
    typer.echo("🧪 Running E2E tests (Detox not configured yet)...")
    # Customize based on detox or other tooling
    subprocess.run(["echo", "Detox tests would run here."], check=False)

ok_cli.commands.generate

Functions

generate(type, name)

Generate a component, service, or page.

Source code in ok_cli/commands/generate/__init__.py
def generate(type: str, name: str):
    """Generate a component, service, or page."""
    type = type.lower()
    if type not in TEMPLATES:
        typer.echo("❌ Invalid type. Use one of: component, service, page.")
        return

    template_path = TEMPLATES[type]
    if not os.path.exists(template_path):
        typer.echo(f"❌ Template '{type}' not found at {template_path}")
        return

    typer.echo(f"✨ Generating {type}: {name}")
    try:
        run_copy(
            template_path,
            name,
            data={"name": name},
            quiet=True,
        )
        typer.echo(f"✅ {type.capitalize()} '{name}' generated successfully!")
    except Exception as e:
        typer.echo(f"❌ Error generating {type}: {str(e)}", err=True)
        raise typer.Exit(code=1)

ok_cli.commands.lint

Functions

lint(project=None)

Run ESLint on the project.

Source code in ok_cli/commands/lint/__init__.py
def lint(project: Optional[str] = None):
    """Run ESLint on the project."""
    target = project or "."
    typer.echo(f"🔍 Linting {target}")
    subprocess.run(["npx", "eslint", target])

ok_cli.commands.makemessages

Functions

makemessages(locale=typer.Option(None, '--locale', '-l', help='Specifies the locale(s) to process'), exclude=typer.Option(None, '--exclude', '-x', help='Specifies the locale(s) to exclude from processing'), all=typer.Option(False, '--all', '-a', help='Updates message files for all available languages. Note: lingui extracts all catalog locales by default, so this flag is redundant.'), extension=typer.Option(None, '--extension', '-e', help='File extension(s) to examine (Django gettext option; not used by lingui)'), domain=typer.Option('django', '--domain', '-d', help='Domain of the messages files (Django gettext option; not used by lingui)'), symlinks=typer.Option(False, '--symlinks', '-s', help='Follows symlinks to directories (Django gettext option; not used by lingui)'), ignore=typer.Option(None, '--ignore', '-i', help='Ignores files or directories matching glob-style pattern'), no_default_ignore=typer.Option(False, '--no-default-ignore', help='Disables the default values of --ignore (Django gettext option; not used by lingui)'), no_wrap=typer.Option(False, '--no-wrap', help='Disables breaking long message lines (Django gettext option; not used by lingui)'), no_location=typer.Option(False, '--no-location', help='Suppresses #: filename:line comment lines (Django gettext option; not used by lingui)'), add_location=typer.Option(None, '--add-location', help='Controls #: filename:line comment lines: full, file, or never (Django gettext option; not used by lingui, requires gettext >= 0.19)'), no_obsolete=typer.Option(False, '--no-obsolete', help="Removes obsolete message strings from .po files (maps to lingui's --clean flag)"), keep_pot=typer.Option(False, '--keep-pot', help='Prevents deleting temporary .pot files (Django gettext option; not used by lingui)'))

Extract i18n messages from source code via lingui extract.

Mimics Django's makemessages command but uses lingui under the hood. Options specific to Django's xgettext/gettext workflow are accepted but may not affect lingui's behavior.

Source code in ok_cli/commands/makemessages/__init__.py
def makemessages(
    locale: Optional[List[str]] = typer.Option(
        None, "--locale", "-l", help="Specifies the locale(s) to process"
    ),
    exclude: Optional[List[str]] = typer.Option(
        None, "--exclude", "-x", help="Specifies the locale(s) to exclude from processing"
    ),
    all: bool = typer.Option(
        False, "--all", "-a", help="Updates message files for all available languages. "
        "Note: lingui extracts all catalog locales by default, so this flag is redundant."
    ),
    extension: Optional[List[str]] = typer.Option(
        None, "--extension", "-e", help="File extension(s) to examine "
        "(Django gettext option; not used by lingui)"
    ),
    domain: str = typer.Option(
        "django", "--domain", "-d", help="Domain of the messages files "
        "(Django gettext option; not used by lingui)"
    ),
    symlinks: bool = typer.Option(
        False, "--symlinks", "-s", help="Follows symlinks to directories "
        "(Django gettext option; not used by lingui)"
    ),
    ignore: Optional[List[str]] = typer.Option(
        None, "--ignore", "-i", help="Ignores files or directories matching glob-style pattern"
    ),
    no_default_ignore: bool = typer.Option(
        False, "--no-default-ignore", help="Disables the default values of --ignore "
        "(Django gettext option; not used by lingui)"
    ),
    no_wrap: bool = typer.Option(
        False, "--no-wrap", help="Disables breaking long message lines "
        "(Django gettext option; not used by lingui)"
    ),
    no_location: bool = typer.Option(
        False, "--no-location", help="Suppresses #: filename:line comment lines "
        "(Django gettext option; not used by lingui)"
    ),
    add_location: Optional[str] = typer.Option(
        None, "--add-location", help="Controls #: filename:line comment lines: full, file, or never "
        "(Django gettext option; not used by lingui, requires gettext >= 0.19)"
    ),
    no_obsolete: bool = typer.Option(
        False, "--no-obsolete", help="Removes obsolete message strings from .po files "
        "(maps to lingui's --clean flag)"
    ),
    keep_pot: bool = typer.Option(
        False, "--keep-pot", help="Prevents deleting temporary .pot files "
        "(Django gettext option; not used by lingui)"
    ),
):
    """Extract i18n messages from source code via lingui extract.

    Mimics Django's makemessages command but uses lingui under the hood.
    Options specific to Django's xgettext/gettext workflow are accepted
    but may not affect lingui's behavior.
    """
    cmd = ["npx", "--yes", "@lingui/cli", "extract"]

    if locale:
        for loc in locale:
            cmd.extend(["--locale", loc])

    if no_obsolete:
        cmd.append("--clean")

    typer.echo(f"🔍 Running: {' '.join(cmd)}")
    result = subprocess.run(cmd, check=False)
    raise typer.Exit(code=result.returncode)

ok_cli.commands.run_task

Functions

run_task(target)

Run a custom script from package.json

Source code in ok_cli/commands/run_task/__init__.py
4
5
6
7
def run_task(target: str):
    """Run a custom script from package.json"""
    typer.echo(f"🚀 Running target: {target}")
    subprocess.run(["npm", "run", target])

ok_cli.commands.run

Functions

run()

Start the Expo dev server.

Source code in ok_cli/commands/run/__init__.py
5
6
7
8
def run():
    """Start the Expo dev server."""
    typer.echo("🏃 Starting Expo server...")
    subprocess.run(["npx", "expo", "start"], check=False)

ok_cli.commands.translatemessages

Functions

translatemessages(ctx)

Translate gettext .po files via gpt-po-translator.

Source code in ok_cli/commands/translatemessages/__init__.py
def translatemessages(ctx: typer.Context):
    """Translate gettext .po files via gpt-po-translator."""
    apply_patches()
    args = list(ctx.args) or ["--help"]
    command = [sys.executable, "-m", "python_gpt_po.main", *args]
    raise typer.Exit(code=subprocess.run(command, check=False).returncode)

ok_cli.commands.test

Functions

test()

Run unit tests (Jest).

Source code in ok_cli/commands/test/__init__.py
5
6
7
8
def test():
    """Run unit tests (Jest)."""
    typer.echo("🧪 Running tests...")
    subprocess.run(["npm", "test"], check=False)

ok_cli.commands.update

Functions

update()

Update all dependencies.

Source code in ok_cli/commands/update/__init__.py
5
6
7
8
9
def update():
    """Update all dependencies."""
    typer.echo("⬆️ Updating dependencies...")
    subprocess.run(["npx", "npm-check-updates", "-u"], check=False)
    subprocess.run(["npm", "install"], check=False)

ok_cli.commands.version

Functions

version()

Show CLI version (from pyproject.toml)

Source code in ok_cli/commands/version/__init__.py
def version():
    """Show CLI version (from pyproject.toml)"""
    pyproject_path = os.path.join(os.path.dirname(__file__), "..", "..", "..", "pyproject.toml")
    try:
        with open(pyproject_path, "rb") as f:
            data = tomllib.load(f)
            cli_version = data["project"]["version"]
            typer.echo(f"🛠️  CLI Version: {cli_version}")
    except Exception as e:
        typer.echo(f"❌ Failed to read version from pyproject.toml: {e}")