Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 26 additions & 2 deletions CUSTOM_DISTROS.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ goose's architecture is designed for extensibility. Organizations can create "re
|---------------|---------------|------------|
| Preconfigure a model/provider | `config.yaml`, `init-config.yaml`, environment variables | Low |
| Add custom AI providers | `crates/goose/src/providers/declarative/` | Low |
| Bundle custom MCP extensions | `config.yaml` extensions section, `ui/desktop/src/built-in-extensions.json` | Medium |
| Bundle custom MCP extensions | `config.yaml` extensions section, `ui/desktop/src/built-in-extensions.json`, `ui/desktop/src/components/settings/extensions/bundled-extensions.json` | Medium |
| Modify system prompts | `crates/goose/src/prompts/` | Low |
| Customize desktop branding | `ui/desktop/` (icons, names, colors) | Medium |
| Build a new UI (web, mobile) | Integrate with `goose-server` REST API | High |
Expand Down Expand Up @@ -191,7 +191,11 @@ async def query_data_lake(query: str) -> str:
return results
```

2. **Bundle as a built-in extension** by adding to `ui/desktop/src/built-in-extensions.json`:
2. **Bundle as a built-in extension** by adding to either:
- `ui/desktop/src/built-in-extensions.json` (core built-ins surfaced in extension UI)
- `ui/desktop/src/components/settings/extensions/bundled-extensions.json` (bundled extension catalog in Settings)

Example:

```json
{
Expand Down Expand Up @@ -268,6 +272,26 @@ You are an AI assistant called [YourName], created by [YourCompany].
- Component text and labels
- Feature visibility

5. **Align packaging and updater names** when rebranding:
- Update static branding metadata in `ui/desktop/package.json` (`productName`, description) and Linux desktop templates (`ui/desktop/forge.deb.desktop`, `ui/desktop/forge.rpm.desktop`)

- Set build/release environment variables consistently:
- `GITHUB_OWNER` and `GITHUB_REPO` for publisher + updater repository lookup
- `GOOSE_BUNDLE_NAME` for bundle/debug scripts and updater asset naming (defaults to `Goose`)

Example:

```bash
export GITHUB_OWNER="your-org"
export GITHUB_REPO="your-goose-fork"
export GOOSE_BUNDLE_NAME="InsightStream-goose"
```

6. **Use this branding consistency checklist** before release:
- Application metadata (`forge.config.ts`, `package.json`, `index.html`) uses your distro name
- Release artifact names and updater lookup names are consistent
- Desktop launchers (Linux `.desktop` templates) point to the same executable name produced by packaging

### Technical Details

- Electron config: `ui/desktop/forge.config.ts`
Expand Down
8 changes: 4 additions & 4 deletions ui/desktop/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@
"start:test-error": "GOOSE_TEST_ERROR=true electron-forge start",
"package": "electron-forge package",
"make": "electron-forge make",
"bundle:default": "node scripts/prepare-platform-binaries.js && npm run make && (cd out/Goose-darwin-arm64 && ditto -c -k --sequesterRsrc --keepParent Goose.app Goose.zip) || echo 'out/Goose-darwin-arm64 not found; either the binary is not built or you are not on macOS'",
"bundle:alpha": "ALPHA=true node scripts/prepare-platform-binaries.js && ALPHA=true npm run make && (cd out/Goose-darwin-arm64 && ditto -c -k --sequesterRsrc --keepParent Goose.app Goose_alpha.zip) || echo 'out/Goose-darwin-arm64 not found; either the binary is not built or you are not on macOS'",
"bundle:intel": "node scripts/prepare-platform-binaries.js && npm run make -- --arch=x64 && cd out/Goose-darwin-x64 && ditto -c -k --sequesterRsrc --keepParent Goose.app Goose_intel_mac.zip",
"debug": "echo 'run --remote-debugging-port=8315' && lldb out/Goose-darwin-arm64/Goose.app",
"bundle:default": "node scripts/prepare-platform-binaries.js && npm run make && BUNDLE_NAME=\"${GOOSE_BUNDLE_NAME:-Goose}\" && APP_DIR=\"out/${BUNDLE_NAME}-darwin-arm64\" && APP_BUNDLE=\"${APP_DIR}/${BUNDLE_NAME}.app\" && (cd \"$APP_DIR\" && ditto -c -k --sequesterRsrc --keepParent \"${BUNDLE_NAME}.app\" \"${BUNDLE_NAME}.zip\") || echo \"${APP_BUNDLE} not found; either the binary is not built or you are not on macOS\"",
"bundle:alpha": "ALPHA=true node scripts/prepare-platform-binaries.js && ALPHA=true npm run make && BUNDLE_NAME=\"${GOOSE_BUNDLE_NAME:-Goose}\" && APP_DIR=\"out/${BUNDLE_NAME}-darwin-arm64\" && APP_BUNDLE=\"${APP_DIR}/${BUNDLE_NAME}.app\" && (cd \"$APP_DIR\" && ditto -c -k --sequesterRsrc --keepParent \"${BUNDLE_NAME}.app\" \"${BUNDLE_NAME}_alpha.zip\") || echo \"${APP_BUNDLE} not found; either the binary is not built or you are not on macOS\"",
"bundle:intel": "node scripts/prepare-platform-binaries.js && npm run make -- --arch=x64 && BUNDLE_NAME=\"${GOOSE_BUNDLE_NAME:-Goose}\" && APP_DIR=\"out/${BUNDLE_NAME}-darwin-x64\" && APP_BUNDLE=\"${APP_DIR}/${BUNDLE_NAME}.app\" && (cd \"$APP_DIR\" && ditto -c -k --sequesterRsrc --keepParent \"${BUNDLE_NAME}.app\" \"${BUNDLE_NAME}_intel_mac.zip\")",
"debug": "echo 'run --remote-debugging-port=8315' && BUNDLE_NAME=\"${GOOSE_BUNDLE_NAME:-Goose}\" && lldb \"out/${BUNDLE_NAME}-darwin-arm64/${BUNDLE_NAME}.app\"",
"test-e2e": "npm run generate-api && playwright test",
"test-e2e:dev": "npm run generate-api && playwright test --reporter=list --retries=0 --max-failures=1",
"test-e2e:ui": "npm run generate-api && playwright test --ui",
Expand Down
11 changes: 6 additions & 5 deletions ui/desktop/src/utils/githubUpdater.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ interface UpdateCheckResult {
export class GitHubUpdater {
private readonly owner = process.env.GITHUB_OWNER || 'block';
private readonly repo = process.env.GITHUB_REPO || 'goose';
private readonly bundleName = process.env.GOOSE_BUNDLE_NAME || 'Goose';
private readonly apiUrl = `https://api.github.com/repos/${this.owner}/${this.repo}/releases/latest`;

async checkForUpdates(): Promise<UpdateCheckResult> {
Expand Down Expand Up @@ -103,16 +104,16 @@ export class GitHubUpdater {
if (platform === 'darwin') {
// macOS
if (arch === 'arm64') {
assetName = 'Goose.zip';
assetName = `${this.bundleName}.zip`;
} else {
assetName = 'Goose_intel_mac.zip';
assetName = `${this.bundleName}_intel_mac.zip`;
}
} else if (platform === 'win32') {
// Windows - for future support
assetName = 'Goose-win32-x64.zip';
assetName = `${this.bundleName}-win32-x64.zip`;
} else {
// Linux - for future support
assetName = `Goose-linux-${arch}.zip`;
assetName = `${this.bundleName}-linux-${arch}.zip`;
}

log.info(`GitHubUpdater: Looking for asset named: ${assetName}`);
Expand Down Expand Up @@ -254,7 +255,7 @@ export class GitHubUpdater {

// Save to Downloads directory
const downloadsDir = path.join(os.homedir(), 'Downloads');
const fileName = `goose-${latestVersion}.zip`;
const fileName = `${this.bundleName}-${latestVersion}.zip`;
const downloadPath = path.join(downloadsDir, fileName);

log.info(`GitHubUpdater: Writing file to ${downloadPath}...`);
Expand Down
1 change: 1 addition & 0 deletions ui/desktop/vite.main.config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ export default defineConfig({
define: {
'process.env.GITHUB_OWNER': JSON.stringify(process.env.GITHUB_OWNER || 'block'),
'process.env.GITHUB_REPO': JSON.stringify(process.env.GITHUB_REPO || 'goose'),
'process.env.GOOSE_BUNDLE_NAME': JSON.stringify(process.env.GOOSE_BUNDLE_NAME || 'Goose'),
},
});