{"id":50406740,"url":"https://github.com/kenm76/combridge","last_synced_at":"2026-05-31T02:00:44.200Z","repository":{"id":360939140,"uuid":"1248239344","full_name":"KenM76/combridge","owner":"KenM76","description":"Generic COM-automation host for Windows desktop apps. One .exe + plugins for SolidWorks, Excel, Word, PowerPoint, Outlook. Roslyn .csx script host. Heavily documented for humans AND LLMs.","archived":false,"fork":false,"pushed_at":"2026-05-28T13:04:02.000Z","size":1183,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-28T15:05:24.755Z","etag":null,"topics":["com-automation","com-interop","csharp","dotnet","excel","llm-friendly","office-automation","outlook","plugin-architecture","powerpoint","roslyn-scripting","solidworks","windows","word"],"latest_commit_sha":null,"homepage":null,"language":"C#","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/KenM76.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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-05-24T11:30:09.000Z","updated_at":"2026-05-28T13:04:06.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/KenM76/combridge","commit_stats":null,"previous_names":["kenm76/combridge"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/KenM76/combridge","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KenM76%2Fcombridge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KenM76%2Fcombridge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KenM76%2Fcombridge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KenM76%2Fcombridge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/KenM76","download_url":"https://codeload.github.com/KenM76/combridge/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KenM76%2Fcombridge/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33716339,"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-05-31T02:00:06.040Z","response_time":95,"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":["com-automation","com-interop","csharp","dotnet","excel","llm-friendly","office-automation","outlook","plugin-architecture","powerpoint","roslyn-scripting","solidworks","windows","word"],"created_at":"2026-05-31T02:00:34.199Z","updated_at":"2026-05-31T02:00:44.194Z","avatar_url":"https://github.com/KenM76.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# combridge\n\nCross-platform desktop-app automation host with a plugin model. Windows\nplugins use COM; macOS plugins use AppleScript. One CLI contract\n(`combridge \u003capp\u003e \u003ccommand\u003e`) for both.\nDrop a plugin DLL into `plugins/\u003cname\u003e/` and the host gives you:\n\n- ROT attach (or new-instance create) for that app's COM server\n- Multi-instance session picker — `list-sessions` + `--session N|pid:NNNN|\u003ctitle\u003e|last` (default: MRU — the window the user was last focused on)\n- A `run-script \u003cfile.csx\u003e` command that compiles a C# script with the\n  plugin's interop assemblies referenced and its globals injected\n- Plus any plugin-specific commands (e.g. SW `active-doc`, Excel `dump-sheet`)\n\nOne exe + many plugins, instead of one exe per app.\n\n\u003e 📁 LLM-optimized references for this project live under [`LLM/`](LLM/).\n\u003e Human readers can use the prose docs (this README and\n\u003e [`PLUGIN_GUIDE.md`](PLUGIN_GUIDE.md)).\n\n## Build\n\n```powershell\ncd \u003crepo-root\u003e          # the directory containing combridge.sln\ndotnet build -c Release\n```\n\nThe host exe lands in `src/ComBridge.Cli/bin/Release/net10.0-windows/combridge.exe`.\nPlugin builds copy themselves into `\u003crepo-root\u003e/plugins/\u003cName\u003e/` next to\nthe published exe (set up via the `CopyToPluginsRoot` MSBuild target in each\nplugin csproj). To deploy, copy `combridge.exe` plus the `plugins/` folder\ntogether.\n\n**Build prerequisites per plugin:** the Excel plugin needs nothing extra\n(its interop comes from NuGet). The SolidWorks plugin needs the SolidWorks\ninterop DLLs — on a normal machine with SolidWorks installed these are\nfound automatically via the Windows registry. If SW is installed somewhere\nnon-standard, set the path one of these ways (first wins):\n\n```powershell\ndotnet build -c Release /p:SolidWorksApiRedist=\"D:\\SW2025\\api\\redist\"   # one-off\n$env:SOLIDWORKS_API_REDIST = \"D:\\SW2025\\api\\redist\"                     # shell/system\n# or copy src/plugins/ComBridge.Plugins.SolidWorks/paths.props.example\n#         to paths.props (same folder) and edit it — persistent, gitignored\n```\n\nIf the DLLs still can't be found, the build fails with a clear\n`error COMBRIDGE001` that lists every location it tried.\n\n## Usage\n\n```text\ncombridge list-plugins\ncombridge \u003cplugin\u003e list-commands\ncombridge \u003cplugin\u003e list-sessions \u003coutputFile\u003e\ncombridge \u003cplugin\u003e [--session \u003csel\u003e] \u003ccommand\u003e [args...] \u003coutputFile\u003e\n```\n\nThe last positional argument is always the output file (use `-` for stdout).\n\n### Flags\n\n| Flag | Meaning |\n|---|---|\n| `--no-create` | Don't launch a new app instance if none is running. |\n| `--session \u003csel\u003e` | Pick a specific running instance. **Without it, the host attaches to the most-recently-focused session** — the window the user was last working in (via desktop Z-order). |\n\n### `--session` selector forms\n\n| Form | Example | Picks |\n|---|---|---|\n| (omitted) | `combridge solidworks active-doc -` | Most-recently-focused session (Z-order MRU) |\n| `last` / `mru` / `recent` | `--session last` | Same as omitting — explicit MRU keyword (defensive against future default changes) |\n| Pure digits | `--session 2` | 1-based index in MRU order: `1` = most recent, `2` = next-most, etc. |\n| `pid:NNNN` | `--session pid:23456` | Win32 process ID — most deterministic |\n| Any other string | `--session \"Bracket\"` | Case-insensitive substring of the active document/workbook title |\n\n### SolidWorks (attach to running session)\n\n```powershell\ncombridge solidworks list-sessions out.txt\ncombridge solidworks active-doc out.txt\ncombridge solidworks --session 2 active-doc out.txt\ncombridge solidworks run-script examples\\sw_active_doc.csx out.txt\n```\n\nGlobals exposed in scripts: `swApp`, `swDoc`, `swPart`, `swAssy`, `swDrawing`,\n`swDocType`. Namespaces auto-imported: `SolidWorks.Interop.sldworks`,\n`SolidWorks.Interop.swconst`, `SolidWorks.Interop.swcommands`.\n\nSolidWorks is **never** silently launched — `AllowCreateNew` is `false` for\nthis plugin. Have SW open before running the bridge.\n\n### Excel (attach or launch)\n\n```powershell\ncombridge excel info out.txt\ncombridge excel list-sessions out.txt\ncombridge excel --session \"Budget.xlsx\" dump-sheet Sheet1 out.tsv\ncombridge excel run-script examples\\excel_dump_active_sheet.csx out.tsv\n```\n\nGlobals: `xlApp`, `xlBook`, `xlSheet`. Excel is launched fresh if no instance\nis running (Office often skips ROT registration until a workbook is open).\nPass `--no-create` to force attach-only.\n\n\u003e **Office 365 caveat:** Excel's shared-instance shim consolidates workbooks\n\u003e back into one process even when a new `EXCEL.EXE` is spawned. Multi-instance\n\u003e Excel is supported in the code paths but rare in live use on default Office\n\u003e 365 installs.\n\n### Word (attach or launch)\n\n```powershell\ncombridge word list-sessions out.txt\ncombridge word info out.txt\ncombridge word --session \"Report.docx\" info out.txt\ncombridge word run-script my_word_script.csx out.txt\n```\n\nGlobals: `wdApp` (`Word._Application`), `wdDoc` (`Word.Document?`).\n\n### PowerPoint (attach or launch)\n\n```powershell\ncombridge powerpoint list-sessions out.txt\ncombridge powerpoint info out.txt\ncombridge powerpoint run-script my_ppt_script.csx out.txt\n```\n\nGlobals: `pptApp` (`PowerPoint._Application`), `pptPres` (`PowerPoint.Presentation?`),\n`pptSlide` (`PowerPoint.Slide?`).\n\n### Outlook (single MAPI session)\n\n```powershell\ncombridge outlook list-sessions out.txt\ncombridge outlook info out.txt\ncombridge outlook run-script my_outlook_script.csx out.txt\n```\n\nGlobals: `olApp` (`Outlook._Application`), `olNs` (`Outlook.NameSpace` —\nthe `\"MAPI\"` namespace, where folders/items live), `olExplorer`\n(`Outlook.Explorer?` — the active window).\n\nOutlook is single-instance by design (one MAPI session per user). The bridge\nuses `GetActiveObject` only — no per-document ROT walking.\n\n## Using ComBridge.Core from a third-party tool\n\nIf you're building a custom CLI/service/GUI that needs ROT attach, session\npicking, or the Roslyn script host — but doesn't fit the CLI or plugin\nshapes (e.g. it orchestrates SolidWorks + SwDocumentMgr in one process, or\nhas its own UX) — reference `ComBridge.Core.dll` directly as a library.\n\nSee [`CONSUMING_CORE.md`](CONSUMING_CORE.md) (humans) or\n[`LLM/consuming.md`](LLM/consuming.md) (LLMs). Short version:\n\n```xml\n\u003cPropertyGroup\u003e\n  \u003cComBridgeRoot\u003e$([System.Environment]::GetEnvironmentVariable('COMBRIDGE_ROOT'))\u003c/ComBridgeRoot\u003e\n  \u003cComBridgeRoot Condition=\"'$(ComBridgeRoot)' == ''\"\u003eD:\\Dev\\combridge\u003c/ComBridgeRoot\u003e\n\u003c/PropertyGroup\u003e\n\u003cItemGroup\u003e\n  \u003cReference Include=\"ComBridge.Core\"\u003e\n    \u003cHintPath\u003e$(ComBridgeRoot)\\src\\ComBridge.Core\\bin\\Release\\net10.0-windows\\ComBridge.Core.dll\u003c/HintPath\u003e\n  \u003c/Reference\u003e\n\u003c/ItemGroup\u003e\n\u003cImport Project=\"$(ComBridgeRoot)\\src\\plugins\\Common.Paths.props\" /\u003e\n```\n\n`LLM/api.md` documents the stable API surface and stability tiers per type.\n\n## Adding your own commands to an existing plugin\n\nYou can add custom named commands to any shipped plugin without forking\nor recompiling it. Drop a `.csx` file into the plugin's `commands/`\nfolder and it becomes an invokable command:\n\n```\nplugins/SolidWorks/commands/my-export.csx     ← create this\n```\n\n```powershell\ncombridge solidworks list-commands\n# →   active-doc      (plugin)    active-doc ...\n#     my-export       (script)    my-export   (.csx: my-export.csx)   ← auto-discovered\n\ncombridge solidworks my-export out.txt\n# runs your .csx against the SW plugin's globals\n```\n\nThe script body uses the plugin's globals (`swApp`, `xlApp`, etc.) just like\n`run-script` does. Built-in commands and the plugin's own typed commands\ntake precedence on name collision — your scripted command can never\naccidentally shadow them.\n\nSee [`LLM/extending.md`](LLM/extending.md) for the full convention,\nincluding \"why not DLL-based sub-plugins\" and the criteria for adding\nthat later if needed.\n\n## Adding a new plugin\n\nSee [`PLUGIN_GUIDE.md`](PLUGIN_GUIDE.md) (humans) or\n[`LLM/plugins.md`](LLM/plugins.md) (LLMs). Short version:\n\n1. New class library that references `ComBridge.Core`\n2. Add the app's interop assemblies (NuGet PIA, or `\u003cReference\u003e` with HintPath)\n3. Implement `IComBridgePlugin` — name, ProgIDs, globals type, commands, optional `DescribeInstance`\n4. Add a `CopyToPluginsRoot` target so the build deploys to `plugins/\u003cName\u003e/`\n5. Drop into the .sln and rebuild\n\n## Layout\n\n```\ncombridge/\n  combridge.sln\n  Directory.Build.props          # shared TFM = net10.0-windows, nullable, etc.\n  .gitignore                     # excludes bin/, obj/, paths.props (live override)\n  README.md                      # this file\n  PLUGIN_GUIDE.md                # author guide for new plugins\n  CONSUMING_CORE.md              # library-mode guide for third-party tools\n  LLM/                           # LLM-optimized docs (dense, structured)\n    README.md                    #   entry index + top-level facts\n    api.md                       #   ComBridge.Core public surface + stability tiers\n    cli.md                       #   CLI grammar + exit codes\n    plugins.md                   #   per-plugin specifics + new-plugin recipe\n    build.md                     #   pitfalls table + csproj boilerplate\n    paths.md                     #   machine-specific path resolution chain\n    consuming.md                 #   library mode for third-party tools\n    symbols.md                   #   symbol → file index\n  src/\n    ComBridge.Core/              # IComBridgePlugin, ROT, Roslyn host, loader, session picker\n    ComBridge.Cli/               # combridge.exe entry + dispatch\n    plugins/\n      Common.Paths.props         #   shared path-resolution + COMBRIDGE001 validation\n      ComBridge.Plugins.SolidWorks/\n        paths.props.example      #     committed template; live paths.props is gitignored\n      ComBridge.Plugins.Excel/\n      ComBridge.Plugins.Word/\n      ComBridge.Plugins.PowerPoint/\n      ComBridge.Plugins.Outlook/\n  plugins/                       # build output — what the exe loads at runtime\n    SolidWorks/\n    Excel/\n    Word/\n    PowerPoint/\n    Outlook/\n  examples/                      # ready-to-run .csx scripts\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkenm76%2Fcombridge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkenm76%2Fcombridge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkenm76%2Fcombridge/lists"}