{"id":51001538,"url":"https://github.com/beyondoss/launch","last_synced_at":"2026-06-20T14:33:29.392Z","repository":{"id":358794459,"uuid":"1169691697","full_name":"beyondoss/launch","owner":"beyondoss","description":"Launch apps from anywhere on https://beyond.dev","archived":false,"fork":false,"pushed_at":"2026-05-03T17:06:51.000Z","size":227,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-19T06:47:05.885Z","etag":null,"topics":["beyond","beyond-dev","launch"],"latest_commit_sha":null,"homepage":"https://crates.io/crates/beyond-launch","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/beyondoss.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-01T03:58:32.000Z","updated_at":"2026-05-08T02:52:15.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/beyondoss/launch","commit_stats":null,"previous_names":["beyondoss/launch"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/beyondoss/launch","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/beyondoss%2Flaunch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/beyondoss%2Flaunch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/beyondoss%2Flaunch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/beyondoss%2Flaunch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/beyondoss","download_url":"https://codeload.github.com/beyondoss/launch/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/beyondoss%2Flaunch/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34573805,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-20T02:00:06.407Z","response_time":98,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["beyond","beyond-dev","launch"],"created_at":"2026-06-20T14:33:28.989Z","updated_at":"2026-06-20T14:33:29.385Z","avatar_url":"https://github.com/beyondoss.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Launch\n\nAnalyzes a project and returns structured JSON describing every deployable service: language, version, framework, package manager, install/build/start/dev commands, env vars, and monorepo structure.\n\n```\n$ launch ./my-app\n{\n  \"services\": [\n    {\n      \"name\": \"api\",\n      \"dir\": \"apps/api\",\n      \"runtimes\": [\n        {\n          \"language\": \"typescript\",\n          \"name\": \"node\",\n          \"version\": \"20.11.1\",\n          \"version_source\": \".nvmrc\",\n          \"package_manager\": { \"name\": \"pnpm\" },\n          \"framework\": \"next\",\n          \"install\": \"pnpm install\",\n          \"build\": \"next build\",\n          \"start\": \"next start\",\n          \"dev\": \"next dev\"\n        }\n      ],\n      \"env\": [\n        { \"key\": \"DATABASE_URL\" },\n        { \"key\": \"PORT\", \"default\": \"3000\" }\n      ],\n      \"detected_by\": [\"apps/api/package.json\"]\n    },\n    {\n      \"name\": \"worker\",\n      \"dir\": \"apps/worker\",\n      \"runtimes\": [{ \"language\": \"python\", \"name\": \"python\", \"version\": \"3.12\" }],\n      \"dockerfile\": \"apps/worker/Dockerfile\",\n      \"oci_stages\": [\n        { \"name\": \"build\", \"manager\": \"apt\", \"distro\": \"bookworm\", \"packages\": [\"build-essential\"] },\n        { \"manager\": \"apk\", \"distro\": \"alpine\", \"packages\": [\"libpq-dev\"] }\n      ],\n      \"system_deps\": [\"libpq-dev\"],\n      \"detected_by\": [\"apps/worker/Dockerfile\"]\n    }\n  ]\n}\n```\n\nMulti-language directories (Rails + React, Django + React, Laravel + Vue) produce a single service with multiple runtimes — the backend runtime first, the JS/TS runtime second.\n\n## Install\n\n```\ncargo install beyond-launch\n```\n\n## Usage\n\n```\nlaunch [PATH] [--format json|json-pretty]\n```\n\n| Argument | Default | Description |\n|----------|---------|-------------|\n| `PATH` | `.` | Repository root |\n| `--format` | `json-pretty` | `json` for compact output |\n\n## Library\n\n```rust\nuse launch::{discover_local, discover_with_fs, MemoryFs};\n\n// Real filesystem\nlet discovery = launch::discover_local(Path::new(\"./my-app\"))?;\n\n// In-memory (tests)\nlet fs = MemoryFs::new(\u0026[\n    (\"package.json\", r#\"{\"scripts\":{\"start\":\"node server.js\"}}\"#),\n    (\".nvmrc\", \"20.11.1\"),\n]);\nlet discovery = launch::discover_with_fs(Path::new(\".\"), signals, \u0026fs)?;\n```\n\n## What it detects\n\n**Service signals** — emit named, deployable services:\n\n| Signal | Files |\n|--------|-------|\n| Fly | `fly.toml` |\n| Vercel | `vercel.json` |\n| Netlify | `netlify.toml` |\n| Heroku | `Procfile` |\n| Railway | `railway.json`, `railway.toml` |\n| Dockerfile / Containerfile | `Dockerfile`, `Dockerfile.*`, `*.Dockerfile`, `Containerfile` variants — all OCI stages with per-stage OS detection and `RUN` package extraction |\n| Docker Compose | `docker-compose.yml`, `compose.yml` |\n\n**Context signals** — describe language, commands, and env vars at a directory:\n\n| Signal | Files |\n|--------|-------|\n| Package | `package.json`, `go.mod`, `Cargo.toml`, `pyproject.toml`, `mix.exs`, `Gemfile`, `composer.json`, `pom.xml` |\n| Framework | `next.config.*`, `astro.config.*`, and 30+ others |\n| DotEnv | `.env`, `.env.*` |\n| StructuredConfig | Zod schemas, Pydantic models, Go struct tags |\n| LibraryCalls | `process.env.X`, `os.Getenv(\"X\")`, etc. |\n\nA directory with a `start` command but no service signal is promoted to a service automatically. That's the common case: a plain project with `package.json` scripts.\n\nTwo distinct package fields appear on Dockerfile services:\n\n| Field | Source | Format | Meaning |\n|-------|--------|---------|---------|\n| `system_deps` | Language signals | apt-canonical | Inferred from app dependencies (`pg` gem → `libpq-dev`) |\n| `oci_stages[].packages` | Dockerfile signal | raw as written | Declared in `RUN apt-get install` / `apk add` / etc. |\n\n`oci_stages` covers all `FROM` blocks — build stages and runtime stages — each with its detected OS (`manager` + `distro`) and installed packages.\n\n**Languages:** JavaScript, TypeScript, Python, Go, Rust, Ruby, PHP, Java/Kotlin, Elixir.\n\n## Custom signals\n\n```rust\nuse launch::{Signal, SignalOutput, FileSystem, DirEntry};\nuse std::path::Path;\n\nstruct MySignal { paths: Vec\u003cPathBuf\u003e }\n\nimpl Signal for MySignal {\n    fn name(\u0026self) -\u003e \u0026'static str { \"my-signal\" }\n\n    fn observe(\u0026mut self, dir: \u0026Path, entry: \u0026DirEntry) {\n        if entry.name == \"my.config\" {\n            self.paths.push(dir.join(\u0026entry.name));\n        }\n    }\n\n    fn generate(\u0026mut self, fs: \u0026dyn FileSystem) -\u003e Result\u003cSignalOutput, LaunchError\u003e {\n        // read self.paths, return services/context/monorepo\n        Ok(SignalOutput::default())\n    }\n}\n\nlet mut signals = launch::signals::default_signals();\nsignals.push(Box::new(MySignal { paths: vec![] }));\nlet discovery = launch::discover_with_fs(root, signals, \u0026fs)?;\n```\n\n## Architecture\n\nSee [ARCHITECTURE.md](ARCHITECTURE.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbeyondoss%2Flaunch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbeyondoss%2Flaunch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbeyondoss%2Flaunch/lists"}