From 642000641fed60063e7d4b2509c94c9cd54ed95d Mon Sep 17 00:00:00 2001 From: Avngrstark62 Date: Wed, 18 Mar 2026 18:57:08 +0530 Subject: [PATCH 1/7] add bindu onboard cli script --- bindu/cli/__init__.py | 0 bindu/cli/main.py | 13 ++ bindu/cli/onboard.py | 322 ++++++++++++++++++++++++++++++++++++++++++ pyproject.toml | 5 + uv.lock | 94 ++++++++++++ 5 files changed, 434 insertions(+) create mode 100644 bindu/cli/__init__.py create mode 100644 bindu/cli/main.py create mode 100644 bindu/cli/onboard.py diff --git a/bindu/cli/__init__.py b/bindu/cli/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/bindu/cli/main.py b/bindu/cli/main.py new file mode 100644 index 00000000..56606361 --- /dev/null +++ b/bindu/cli/main.py @@ -0,0 +1,13 @@ +import typer + +from bindu.cli import onboard, db, train, canary + +app = typer.Typer(help="Bindu CLI") + +app.add_typer(onboard.app, name="onboard") +app.add_typer(db.app, name="db") +app.add_typer(train.app, name="train") +app.add_typer(canary.app, name="canary") + +def main(): + app() \ No newline at end of file diff --git a/bindu/cli/onboard.py b/bindu/cli/onboard.py new file mode 100644 index 00000000..00d94a6d --- /dev/null +++ b/bindu/cli/onboard.py @@ -0,0 +1,322 @@ +import os +import sys +import shutil +import subprocess +from pathlib import Path +from typing import Optional + +import typer +import questionary +from rich import print +from rich.rule import Rule +from rich.panel import Panel + +app = typer.Typer() + + +def check_python_version() -> None: + """Check if Python >= 3.12 is installed.""" + if sys.version_info < (3, 12): + print(f"[red]❌ Python 3.12+ required. Current: {sys.version_info.major}.{sys.version_info.minor}[/red]") + print("[yellow]Install from: https://www.python.org/downloads/[/yellow]") + raise typer.Exit(1) + + +def check_uv_installed() -> None: + """Check if uv is installed.""" + if shutil.which("uv") is None: + print("[red]❌ uv package manager not found[/red]") + print("[yellow]Install from: https://docs.astral.sh/uv/getting-started/installation/[/yellow]") + raise typer.Exit(1) + + +def snake_case(text: str) -> str: + """Convert text to snake_case.""" + return text.lower().replace("-", "_").replace(" ", "_") + + +def get_system_username() -> str: + """Get system username.""" + return os.environ.get("USER", "bindu_user") + + +def run_command(cmd: list[str], cwd: Optional[str] = None) -> bool: + """Run shell command and return success status.""" + try: + result = subprocess.run(cmd, cwd=cwd, check=True, capture_output=True, text=True) + if result.stdout: + print(result.stdout) + return True + except subprocess.CalledProcessError as e: + print(f"[red]❌ Command failed: {' '.join(cmd)}[/red]") + if e.stderr: + print(f"[red]{e.stderr}[/red]") + return False + + +@app.callback(invoke_without_command=True) +def onboard() -> None: + """ + 🎯 Bindu Agent Onboarding Flow + + Creates a new Bindu agent project with interactive setup. + """ + print(Panel("[bold cyan]🚀 Bindu Agent Onboarding[/bold cyan]", expand=False)) + + # ============= STEP 0: Pre-check ============= + print(Rule("[yellow]Pre-check[/yellow]", style="yellow")) + + check_python_version() + check_uv_installed() + print("[green]✅ Python 3.12+[/green]") + print("[green]✅ uv installed[/green]") + + # ============= STEP 1: Core project inputs ============= + print() + print(Rule("[cyan]Project Setup[/cyan]", style="cyan")) + + project_name = questionary.text( + "📁 Project name?", + default="my-bindu-agent" + ).ask() + + if not project_name: + print("[red]❌ Project name cannot be empty[/red]") + raise typer.Exit(1) + + use_defaults = questionary.confirm( + "🎯 Use default configuration?", + default=True + ).ask() + + # ============= STEP 2: Handle configuration mode ============= + if use_defaults: + print("[cyan]📋 Using default configuration...[/cyan]") + project_slug = snake_case(project_name) + author = get_system_username() + email = "" + github_handle = "" + dockerhub_username = "" + agent_framework = "agno" + skill_names = "" + auth_provider = "n" + observability_provider = "none" + storage_type = "memory" + scheduler_type = "memory" + security_features = "did-only" + enable_paywall = "n" + include_github_actions = "n" + open_source_license = "MIT license" + else: + print() + print(Rule("[yellow]Custom Configuration[/yellow]", style="yellow")) + + author = questionary.text( + "✏️ Author name?", + default=get_system_username() + ).ask() or get_system_username() + + email = questionary.text( + "📧 Email?", + default="" + ).ask() or "" + + github_handle = questionary.text( + "🐙 GitHub handle?", + default="" + ).ask() or "" + + dockerhub_username = questionary.text( + "🐳 DockerHub username?", + default="" + ).ask() or "" + + agent_framework = questionary.select( + "🤖 Agent framework?", + choices=["agno", "langchain", "crew", "fastagent", "openai agent", "google adk agent", "custom"], + default="agno" + ).ask() + + skill_names = questionary.text( + "🧠 Skill names? (comma-separated, or press Enter to skip)", + default="" + ).ask() or "" + + auth_provider = questionary.confirm( + "🔐 Enable authentication?", + default=False + ).ask() + auth_provider = "y" if auth_provider else "n" + + observability_provider = questionary.select( + "📊 Observability provider?", + choices=["none", "phoenix", "jaeger", "langfuse"], + default="none" + ).ask() + + storage_type = questionary.select( + "💾 Storage type?", + choices=["memory", "postgres"], + default="memory" + ).ask() + + scheduler_type = questionary.select( + "⏱️ Scheduler type?", + choices=["memory", "redis"], + default="memory" + ).ask() + + security_features = questionary.select( + "🔒 Security features?", + choices=["did-and-pki", "did-only", "pki-only", "none"], + default="did-only" + ).ask() + + enable_paywall = questionary.confirm( + "💳 Enable paywall?", + default=False + ).ask() + enable_paywall = "y" if enable_paywall else "n" + + include_github_actions = questionary.confirm( + "🐙 Include GitHub Actions?", + default=False + ).ask() + include_github_actions = "y" if include_github_actions else "n" + + open_source_license = questionary.select( + "📜 Open source license?", + choices=[ + "Apache Software License 2.0", + "MIT license", + "BSD license", + "ISC license", + "GNU General Public License v3", + "Not open source" + ], + default="MIT license" + ).ask() + + project_slug = snake_case(project_name) + + # ============= STEP 3: Run cookiecutter (non-interactive) ============= + print() + print(Rule("[green]Creating Project[/green]", style="green")) + + cookiecutter_url = "https://github.com/getbindu/create-bindu-agent.git" + + cookiecutter_args = [ + "uvx", + "cookiecutter", + cookiecutter_url, + "--no-input", + "--overwrite-if-exists", + f"author={author}", + f"email={email}", + f"author_github_handle={github_handle}", + f"dockerhub_username={dockerhub_username}", + f"project_name={project_name}", + f"project_slug={project_slug}", + f"project_description=A Bindu AI agent for intelligent task handling", + f"agent_framework={agent_framework}", + f"skill_names={skill_names}", + f"auth_provider={auth_provider}", + f"observability_provider={observability_provider}", + f"storage_type={storage_type}", + f"scheduler_type={scheduler_type}", + f"security_features={security_features}", + f"enable_paywall={enable_paywall}", + f"include_github_actions={include_github_actions}", + f"open_source_license={open_source_license}", + ] + + print(f"[cyan]🍪 Running cookiecutter...[/cyan]") + if not run_command(cookiecutter_args): + raise typer.Exit(1) + + # ============= STEP 4: Move into project directory ============= + project_dir = Path.cwd() / project_name + if not project_dir.exists(): + print(f"[red]❌ Project directory not created: {project_dir}[/red]") + raise typer.Exit(1) + + print(f"[green]✅ Project created at: {project_dir}[/green]") + + # ============= STEP 5: Create .env file ============= + env_example = project_dir / ".env.example" + env_file = project_dir / ".env" + + if env_example.exists(): + shutil.copy(env_example, env_file) + print(f"[green]✅ .env file created[/green]") + + # ============= STEP 6: Ask environment-related inputs ============= + print() + print(Rule("[yellow]Environment Setup[/yellow]", style="yellow")) + + openrouter_key = questionary.password( + "🔑 OPENROUTER API key? (press Enter to skip)", + default="" + ).ask() or "" + + mem0_key = questionary.password( + "🧠 MEM0 API key? (press Enter to skip)", + default="" + ).ask() or "" + + # Write to .env file + if env_file.exists(): + env_content = env_file.read_text() + + # Update or add OPENROUTER_API_KEY + if "OPENROUTER_API_KEY" in env_content: + env_content = env_content.replace( + [line for line in env_content.split("\n") if line.startswith("OPENROUTER_API_KEY")][0], + f"OPENROUTER_API_KEY={openrouter_key}" + ) + else: + env_content += f"\nOPENROUTER_API_KEY={openrouter_key}" + + # Update or add MEM0_API_KEY + if "MEM0_API_KEY" in env_content: + env_content = env_content.replace( + [line for line in env_content.split("\n") if line.startswith("MEM0_API_KEY")][0], + f"MEM0_API_KEY={mem0_key}" + ) + else: + env_content += f"\nMEM0_API_KEY={mem0_key}" + + env_file.write_text(env_content) + print("[green]✅ Environment variables set[/green]") + + # ============= STEP 7: Install dependencies ============= + print() + print(Rule("[cyan]Installing Dependencies[/cyan]", style="cyan")) + + if not run_command(["uv", "sync"], cwd=str(project_dir)): + raise typer.Exit(1) + + print("[green]✅ Dependencies installed[/green]") + + # ============= STEP 8: Final output ============= + print() + print(Panel( + f"""[green]✅ Project created successfully[/green] + +[bold]📂 Project:[/bold] ./{project_name} + +[bold]👉 To start your agent:[/bold] +[cyan]cd {project_name}[/cyan] +[cyan]uv run python -m {project_slug}.main[/cyan] + +[bold]💡 Next steps:[/bold] + • Edit [cyan].env[/cyan] if needed + • Add skills in [cyan]/{project_slug}/skills[/cyan] + • Run [cyan]uv run python -m {project_slug}.main[/cyan]""", + expand=False, + style="green" + )) + + +if __name__ == "__main__": + app() \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index c9ce32d3..07bb34c8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -57,6 +57,8 @@ dependencies = [ # Security "detect-secrets==1.5.0", "python-dotenv>=1.1.0", + "typer>=0.15.2", + "questionary>=2.1.1", ] [project.optional-dependencies] @@ -157,3 +159,6 @@ fallback-version = "0.3.14" [tool.hatch.build.hooks.vcs] version-file = "bindu/_version.py" + +[project.scripts] +bindu = "bindu.cli.main:main" diff --git a/uv.lock b/uv.lock index a5ee3bfc..6819be46 100644 --- a/uv.lock +++ b/uv.lock @@ -9,6 +9,32 @@ resolution-markers = [ "python_full_version < '3.13'", ] +[[package]] +name = "ag2" +version = "0.11.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "diskcache" }, + { name = "docker" }, + { name = "fast-depends", extra = ["pydantic"] }, + { name = "httpx" }, + { name = "packaging" }, + { name = "pydantic" }, + { name = "python-dotenv" }, + { name = "termcolor" }, + { name = "tiktoken" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/77/20/46159b56f9c6069ea2bc174f3ce3597febc4f4bbf467c2c1e003c84f0da7/ag2-0.11.4.tar.gz", hash = "sha256:1949d27e889a908a258ad4bcda4bfb33770763a2e8f9ea2da13eec342da8f493", size = 3818369, upload-time = "2026-03-17T23:47:50.308Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a6/14/0d226e5fbb02949ae1ded5bcaa695a1ca11bb9535c71b53dfbc6ff2c4b5e/ag2-0.11.4-py3-none-any.whl", hash = "sha256:182805d940271bd9cfea2a40f5dc1f3db351745b07135efdb015a7f0c0681fd4", size = 1080405, upload-time = "2026-03-17T23:47:48.15Z" }, +] + +[package.optional-dependencies] +openai = [ + { name = "openai" }, +] + [[package]] name = "agno" version = "2.5.2" @@ -365,6 +391,7 @@ dependencies = [ { name = "pyperclip" }, { name = "python-dotenv" }, { name = "pyyaml" }, + { name = "questionary" }, { name = "redis" }, { name = "requests" }, { name = "rich" }, @@ -372,6 +399,7 @@ dependencies = [ { name = "sqlalchemy", extra = ["asyncio"] }, { name = "starlette" }, { name = "tenacity" }, + { name = "typer" }, { name = "uvicorn" }, { name = "web3" }, { name = "x402" }, @@ -379,6 +407,7 @@ dependencies = [ [package.optional-dependencies] agents = [ + { name = "ag2", extra = ["openai"] }, { name = "agno" }, { name = "ddgs" }, { name = "duckduckgo-search" }, @@ -431,6 +460,7 @@ dev = [ [package.metadata] requires-dist = [ + { name = "ag2", extras = ["openai"], marker = "extra == 'agents'", specifier = ">=0.11.0" }, { name = "agno", marker = "extra == 'agents'", specifier = ">=2.5.2" }, { name = "aiofiles", specifier = "==24.1.0" }, { name = "aiofiles", marker = "extra == 'core'", specifier = "==24.1.0" }, @@ -478,6 +508,7 @@ requires-dist = [ { name = "python-dotenv", marker = "extra == 'agents'", specifier = ">=1.0.0" }, { name = "pyyaml", specifier = "==6.0.2" }, { name = "pyyaml", marker = "extra == 'core'", specifier = "==6.0.2" }, + { name = "questionary", specifier = ">=2.1.1" }, { name = "redis", specifier = "==7.1.0" }, { name = "requests", specifier = "==2.32.3" }, { name = "requests", marker = "extra == 'core'", specifier = "==2.32.3" }, @@ -490,6 +521,7 @@ requires-dist = [ { name = "starlette", marker = "extra == 'core'", specifier = "==0.48.0" }, { name = "tenacity", specifier = "==9.1.4" }, { name = "tenacity", marker = "extra == 'core'", specifier = "==9.1.4" }, + { name = "typer", specifier = ">=0.15.2" }, { name = "uvicorn", specifier = ">=0.35" }, { name = "uvicorn", marker = "extra == 'core'", specifier = ">=0.35" }, { name = "web3", specifier = "==7.13.0" }, @@ -1144,6 +1176,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4e/5e/4f5fe4b89fde1dc3ed0eb51bd4ce4c0bca406246673d370ea2ad0c58d747/detect_secrets-1.5.0-py3-none-any.whl", hash = "sha256:e24e7b9b5a35048c313e983f76c4bd09dad89f045ff059e354f9943bf45aa060", size = 120341, upload-time = "2024-05-06T17:46:16.628Z" }, ] +[[package]] +name = "diskcache" +version = "5.6.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3f/21/1c1ffc1a039ddcc459db43cc108658f32c57d271d7289a2794e401d0fdb6/diskcache-5.6.3.tar.gz", hash = "sha256:2c3a3fa2743d8535d832ec61c2054a1641f41775aa7c556758a109941e33e4fc", size = 67916, upload-time = "2023-08-31T06:12:00.316Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3f/27/4570e78fc0bf5ea0ca45eb1de3818a23787af9b390c0b0a0033a1b8236f9/diskcache-5.6.3-py3-none-any.whl", hash = "sha256:5e31b2d5fbad117cc363ebaf6b689474db18a1f6438bc82358b024abd4c2ca19", size = 45550, upload-time = "2023-08-31T06:11:58.822Z" }, +] + [[package]] name = "distlib" version = "0.4.0" @@ -1171,6 +1212,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl", hash = "sha256:01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af", size = 331094, upload-time = "2025-09-07T18:57:58.071Z" }, ] +[[package]] +name = "docker" +version = "7.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pywin32", marker = "sys_platform == 'win32'" }, + { name = "requests" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/91/9b/4a2ea29aeba62471211598dac5d96825bb49348fa07e906ea930394a83ce/docker-7.1.0.tar.gz", hash = "sha256:ad8c70e6e3f8926cb8a92619b832b4ea5299e2831c14284663184e200546fa6c", size = 117834, upload-time = "2024-05-23T11:13:57.216Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e3/26/57c6fb270950d476074c087527a558ccb6f4436657314bfb6cdf484114c4/docker-7.1.0-py3-none-any.whl", hash = "sha256:c96b93b7f0a746f9e77d325bcfb87422a3d8bd4f03136ae8a85b37f1898d5fc0", size = 147774, upload-time = "2024-05-23T11:13:55.01Z" }, +] + [[package]] name = "docopt" version = "0.6.2" @@ -1385,6 +1440,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/51/37/b3ea9cd5558ff4cb51957caca2193981c6b0ff30bd0d2630ac62505d99d0/fake_useragent-2.2.0-py3-none-any.whl", hash = "sha256:67f35ca4d847b0d298187443aaf020413746e56acd985a611908c73dba2daa24", size = 161695, upload-time = "2025-04-14T15:32:17.732Z" }, ] +[[package]] +name = "fast-depends" +version = "3.0.8" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f8/6d/787a21ca8043a8fdb737cf28f645e94a46fc30b44a31de54573299156bad/fast_depends-3.0.8.tar.gz", hash = "sha256:896b16f79a512b6ea1df721b0aa1708a192a06f964be6597e01fcf5412559101", size = 18382, upload-time = "2026-03-02T19:54:28.649Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1d/1d/e4843e4eeb65f51447b8c22d200d12d8f94f27c97e77bb7162515cc8d61f/fast_depends-3.0.8-py3-none-any.whl", hash = "sha256:4c52c8a3907bca46d43e70e4364d6d016872d9a3aae4bc0c1c85e72e0a6a21c7", size = 25507, upload-time = "2026-03-02T19:54:27.594Z" }, +] + +[package.optional-dependencies] +pydantic = [ + { name = "pydantic" }, +] + [[package]] name = "fastapi" version = "0.118.3" @@ -3799,6 +3872,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/68/69/77d1a971c4b933e8c79403e99bcbb790463da5e48333cc4fd5d412c63c98/qdrant_client-1.17.1-py3-none-any.whl", hash = "sha256:6cda4064adfeaf211c751f3fbc00edbbdb499850918c7aff4855a9a759d56cbd", size = 389947, upload-time = "2026-03-13T17:13:43.156Z" }, ] +[[package]] +name = "questionary" +version = "2.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "prompt-toolkit" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f6/45/eafb0bba0f9988f6a2520f9ca2df2c82ddfa8d67c95d6625452e97b204a5/questionary-2.1.1.tar.gz", hash = "sha256:3d7e980292bb0107abaa79c68dd3eee3c561b83a0f89ae482860b181c8bd412d", size = 25845, upload-time = "2025-08-28T19:00:20.851Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-py3-none-any.whl", hash = "sha256:a51af13f345f1cdea62347589fbb6df3b290306ab8930713bfae4d475a7d4a59", size = 36753, upload-time = "2025-08-28T19:00:19.56Z" }, +] + [[package]] name = "readme-renderer" version = "44.0" @@ -4287,6 +4372,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d7/c1/eb8f9debc45d3b7918a32ab756658a0904732f75e555402972246b0b8e71/tenacity-9.1.4-py3-none-any.whl", hash = "sha256:6095a360c919085f28c6527de529e76a06ad89b23659fa881ae0649b867a9d55", size = 28926, upload-time = "2026-02-07T10:45:32.24Z" }, ] +[[package]] +name = "termcolor" +version = "3.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/46/79/cf31d7a93a8fdc6aa0fbb665be84426a8c5a557d9240b6239e9e11e35fc5/termcolor-3.3.0.tar.gz", hash = "sha256:348871ca648ec6a9a983a13ab626c0acce02f515b9e1983332b17af7979521c5", size = 14434, upload-time = "2025-12-29T12:55:21.882Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/33/d1/8bb87d21e9aeb323cc03034f5eaf2c8f69841e40e4853c2627edf8111ed3/termcolor-3.3.0-py3-none-any.whl", hash = "sha256:cf642efadaf0a8ebbbf4bc7a31cec2f9b5f21a9f726f4ccbb08192c9c26f43a5", size = 7734, upload-time = "2025-12-29T12:55:20.718Z" }, +] + [[package]] name = "text-unidecode" version = "1.3" From 372dc8a7c5f702e2202f52026d2c82a24358b410 Mon Sep 17 00:00:00 2001 From: Avngrstark62 Date: Wed, 18 Mar 2026 19:12:33 +0530 Subject: [PATCH 2/7] minor fixes in onboard cli --- bindu/cli/main.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/bindu/cli/main.py b/bindu/cli/main.py index 56606361..73fc8780 100644 --- a/bindu/cli/main.py +++ b/bindu/cli/main.py @@ -1,13 +1,10 @@ import typer -from bindu.cli import onboard, db, train, canary +from bindu.cli import onboard app = typer.Typer(help="Bindu CLI") app.add_typer(onboard.app, name="onboard") -app.add_typer(db.app, name="db") -app.add_typer(train.app, name="train") -app.add_typer(canary.app, name="canary") def main(): app() \ No newline at end of file From 0cf062b86cb948cdff1fb4d7cd4d245bbd934f8e Mon Sep 17 00:00:00 2001 From: Avngrstark62 Date: Wed, 18 Mar 2026 19:19:26 +0530 Subject: [PATCH 3/7] minor fixes in onboard cli --- bindu/cli/onboard.py | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/bindu/cli/onboard.py b/bindu/cli/onboard.py index 00d94a6d..4401778c 100644 --- a/bindu/cli/onboard.py +++ b/bindu/cli/onboard.py @@ -303,19 +303,34 @@ def onboard() -> None: print(Panel( f"""[green]✅ Project created successfully[/green] -[bold]📂 Project:[/bold] ./{project_name} - -[bold]👉 To start your agent:[/bold] +[bold]📂 Project:[/bold] ./{project_name}""", + expand=False, + style="green" + )) + + # Ask if user wants to start the agent now + start_now = questionary.confirm( + "🚀 Start the agent now?", + default=False + ).ask() + + if start_now: + print() + print("[cyan]🚀 Starting agent...[/cyan]") + run_command(["uv", "run", "python", "-m", f"{project_slug}.main"], cwd=str(project_dir)) + else: + print() + print(Panel( + f"""[bold]👉 To start your agent:[/bold] [cyan]cd {project_name}[/cyan] [cyan]uv run python -m {project_slug}.main[/cyan] [bold]💡 Next steps:[/bold] • Edit [cyan].env[/cyan] if needed - • Add skills in [cyan]/{project_slug}/skills[/cyan] - • Run [cyan]uv run python -m {project_slug}.main[/cyan]""", - expand=False, - style="green" - )) + • Add skills in [cyan]./{project_slug}/skills[/cyan]""", + expand=False, + style="blue" + )) if __name__ == "__main__": From 2c957d2037ebc23c7276967e3b8ef210f94efb7e Mon Sep 17 00:00:00 2001 From: Avngrstark62 Date: Wed, 18 Mar 2026 19:23:04 +0530 Subject: [PATCH 4/7] minor fixes in onboard cli --- bindu/cli/onboard.py | 28 ++++++---------------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/bindu/cli/onboard.py b/bindu/cli/onboard.py index 4401778c..7b379741 100644 --- a/bindu/cli/onboard.py +++ b/bindu/cli/onboard.py @@ -303,34 +303,18 @@ def onboard() -> None: print(Panel( f"""[green]✅ Project created successfully[/green] -[bold]📂 Project:[/bold] ./{project_name}""", - expand=False, - style="green" - )) - - # Ask if user wants to start the agent now - start_now = questionary.confirm( - "🚀 Start the agent now?", - default=False - ).ask() - - if start_now: - print() - print("[cyan]🚀 Starting agent...[/cyan]") - run_command(["uv", "run", "python", "-m", f"{project_slug}.main"], cwd=str(project_dir)) - else: - print() - print(Panel( - f"""[bold]👉 To start your agent:[/bold] +[bold]📂 Project:[/bold] ./{project_name} + +[bold]👉 To start your agent:[/bold] [cyan]cd {project_name}[/cyan] [cyan]uv run python -m {project_slug}.main[/cyan] [bold]💡 Next steps:[/bold] • Edit [cyan].env[/cyan] if needed • Add skills in [cyan]./{project_slug}/skills[/cyan]""", - expand=False, - style="blue" - )) + expand=False, + style="green" + )) if __name__ == "__main__": From 2281878980a17210a8099d61977f1a787bd53f3a Mon Sep 17 00:00:00 2001 From: Avngrstark62 Date: Wed, 18 Mar 2026 19:26:07 +0530 Subject: [PATCH 5/7] minor fixes in onboard cli --- bindu/cli/onboard.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/bindu/cli/onboard.py b/bindu/cli/onboard.py index 7b379741..6a374537 100644 --- a/bindu/cli/onboard.py +++ b/bindu/cli/onboard.py @@ -93,10 +93,10 @@ def onboard() -> None: if use_defaults: print("[cyan]📋 Using default configuration...[/cyan]") project_slug = snake_case(project_name) - author = get_system_username() - email = "" - github_handle = "" - dockerhub_username = "" + author = "Bindu Sunflower" + email = "bindu.builder@getbindu.com" + github_handle = "bindu-wizard" + dockerhub_username = github_handle agent_framework = "agno" skill_names = "" auth_provider = "n" @@ -105,7 +105,7 @@ def onboard() -> None: scheduler_type = "memory" security_features = "did-only" enable_paywall = "n" - include_github_actions = "n" + include_github_actions = "y" open_source_license = "MIT license" else: print() @@ -113,23 +113,23 @@ def onboard() -> None: author = questionary.text( "✏️ Author name?", - default=get_system_username() - ).ask() or get_system_username() + default="Bindu Sunflower" + ).ask() or "Bindu Sunflower" email = questionary.text( "📧 Email?", - default="" - ).ask() or "" + default="bindu.builder@getbindu.com" + ).ask() or "bindu.builder@getbindu.com" github_handle = questionary.text( "🐙 GitHub handle?", - default="" - ).ask() or "" + default="bindu-wizard" + ).ask() or "bindu-wizard" dockerhub_username = questionary.text( "🐳 DockerHub username?", - default="" - ).ask() or "" + default=github_handle + ).ask() or github_handle agent_framework = questionary.select( "🤖 Agent framework?", @@ -180,7 +180,7 @@ def onboard() -> None: include_github_actions = questionary.confirm( "🐙 Include GitHub Actions?", - default=False + default=True ).ask() include_github_actions = "y" if include_github_actions else "n" From c32dbc5f5565bc203806608826c255522aaffae0 Mon Sep 17 00:00:00 2001 From: Avngrstark62 Date: Wed, 18 Mar 2026 19:36:36 +0530 Subject: [PATCH 6/7] minor fixes in onboard cli --- bindu/cli/onboard.py | 1 + 1 file changed, 1 insertion(+) diff --git a/bindu/cli/onboard.py b/bindu/cli/onboard.py index 6a374537..d27b7f8b 100644 --- a/bindu/cli/onboard.py +++ b/bindu/cli/onboard.py @@ -310,6 +310,7 @@ def onboard() -> None: [cyan]uv run python -m {project_slug}.main[/cyan] [bold]💡 Next steps:[/bold] + • Update [cyan]./{project_slug}/agent_config.json[/cyan] if needed • Edit [cyan].env[/cyan] if needed • Add skills in [cyan]./{project_slug}/skills[/cyan]""", expand=False, From 92bacea0b8bba78ded89f3e658919e282cb5ceeb Mon Sep 17 00:00:00 2001 From: Avngrstark62 Date: Wed, 18 Mar 2026 20:15:05 +0530 Subject: [PATCH 7/7] minor fixes in onboard cli --- bindu/cli/onboard.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/bindu/cli/onboard.py b/bindu/cli/onboard.py index d27b7f8b..ec43a06d 100644 --- a/bindu/cli/onboard.py +++ b/bindu/cli/onboard.py @@ -41,16 +41,13 @@ def get_system_username() -> str: def run_command(cmd: list[str], cwd: Optional[str] = None) -> bool: - """Run shell command and return success status.""" + """Run shell command and return success status with live output.""" try: - result = subprocess.run(cmd, cwd=cwd, check=True, capture_output=True, text=True) - if result.stdout: - print(result.stdout) - return True - except subprocess.CalledProcessError as e: + result = subprocess.run(cmd, cwd=cwd, check=False, text=True) + return result.returncode == 0 + except Exception as e: print(f"[red]❌ Command failed: {' '.join(cmd)}[/red]") - if e.stderr: - print(f"[red]{e.stderr}[/red]") + print(f"[red]{str(e)}[/red]") return False