Skip to content

feat: add support for GCC cloud environment and update endpoints#2

Open
TheSethRose wants to merge 1 commit intofoeken:mainfrom
TheSethRose:main
Open

feat: add support for GCC cloud environment and update endpoints#2
TheSethRose wants to merge 1 commit intofoeken:mainfrom
TheSethRose:main

Conversation

@TheSethRose
Copy link

Summary

This PR introduces centralized endpoint management with support for multiple Microsoft cloud environments. The main addition is a new GCC (Office 365 US Government) environment option, allowing users to switch between commercial and government clouds.

Changes

  • New endpoints module (src/lib/endpoints.ts) — Centralized configuration for Microsoft cloud endpoints
  • GCC environment support — Users can now use --gcc flag or CLIPPY_CLOUD=gcc to switch to Office 365 US Government
  • Reduced code duplication — Replaced 25+ hardcoded URL strings with endpoint constants across the codebase
  • Enhanced CLI — Added --gcc flag to all commands
  • Configuration file — Added .env.example template
  • Updated documentation — New README section explaining cloud environments and configuration
  • Improved login — New --no-headless option for browser control during authentication

How to Use

Set environment variable:
```bash
export CLIPPY_CLOUD=gcc
clippy calendar
```

Or use CLI flag:
```bash
clippy --gcc login --interactive
clippy --gcc calendar
```

Files Changed

  • `src/lib/endpoints.ts` (new) — Centralized endpoint management
  • `src/cli.ts` — Pre-parse --gcc flag, add CLI option
  • `src/lib/auth.ts` — Use endpoint constants, add headless option
  • `src/lib/owa-client.ts` — Replace 25+ hardcoded URLs
  • `src/commands/login.ts` — Use endpoint constants
  • `src/commands/find.ts` — Use endpoint constants
  • `src/commands/drafts.ts` — Use endpoint constants
  • `.env.example` (new) — Environment variable template
  • `README.md` — Configuration and usage documentation
  • `.gitignore` — Added local env files and .claude/

Testing

  • GCC environment can be selected via `--gcc` flag or `CLIPPY_CLOUD` env var
  • All existing functionality should work on both commercial and GCC clouds
  • `.env.example` provides configuration template

Copilot AI review requested due to automatic review settings February 6, 2026 00:16
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request introduces centralized endpoint management to support multiple Microsoft cloud environments, specifically adding Office 365 US Government (GCC) support. The implementation replaces 25+ hardcoded URLs across the codebase with dynamic endpoint constants that can be switched via the --gcc CLI flag or CLIPPY_CLOUD environment variable.

Changes:

  • Created centralized endpoint configuration module with support for commercial and GCC cloud environments
  • Added --gcc CLI flag and dynamic import pattern to allow environment selection before module initialization
  • Added --no-headless option for browser control during authentication (login command only)

Reviewed changes

Copilot reviewed 9 out of 10 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
src/lib/endpoints.ts New centralized endpoint configuration supporting commercial and GCC cloud environments
src/cli.ts Pre-parses --gcc flag before imports, uses dynamic imports for environment-aware initialization
src/lib/auth.ts Updated to use endpoint constants, added headless parameter support
src/lib/owa-client.ts Replaced 25+ hardcoded URLs with endpoint constants (OUTLOOK_BASE, OUTLOOK_API, GRAPH_BASE)
src/commands/login.ts Uses endpoint constants, added --no-headless option
src/commands/find.ts Updated to use OUTLOOK_API constant
src/commands/drafts.ts Updated to use OUTLOOK_API constant
.env.example New configuration template documenting CLIPPY_CLOUD and CLIPPY_TOKEN variables
.gitignore Added .env.local, .env.*.local patterns and .claude/ directory
README.md Added cloud environment configuration section and updated documentation

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@@ -1,27 +1,36 @@
#!/usr/bin/env bun
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The export {} statement on line 2 appears to be a workaround to make this file a module. However, it's not clear why this is needed since the file already uses ES modules with dynamic imports. Consider adding a comment explaining why this empty export is necessary, or remove it if it's not required.

Suggested change
#!/usr/bin/env bun
#!/usr/bin/env bun
// Ensure TypeScript treats this file as an ES module so that top-level await is allowed.

Copilot uses AI. Check for mistakes.
const playwrightResult = await extractTokenViaPlaywright();
const playwrightResult = await extractTokenViaPlaywright({
headless: headless !== undefined ? headless : true,
fallbackToVisible: headless !== false,
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic for fallbackToVisible could be clearer. The expression headless !== false is confusing. Consider using fallbackToVisible: headless !== false with a comment explaining the logic, or more explicitly: fallbackToVisible: (headless === undefined || headless === true). This makes it clearer that fallback only happens when the user hasn't explicitly requested non-headless mode.

Suggested change
fallbackToVisible: headless !== false,
// Allow fallback to visible mode unless the user explicitly requested non-headless
fallbackToVisible: headless === undefined || headless === true,

Copilot uses AI. Check for mistakes.
Comment on lines +10 to +12
.option('--no-headless', 'Show the browser window (don\'t run headless)')
.option('--check', 'Only check if session is valid, do not save')
.action(async (options: { token?: string; interactive?: boolean; check?: boolean }) => {
.action(async (options: { token?: string; interactive?: boolean; headless?: boolean; check?: boolean }) => {
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The --no-headless option was only added to the login command, but other commands like calendar, mail, send, etc. also support the --interactive flag and call resolveAuth. For consistency, all commands that support --interactive should also support --no-headless and pass the headless parameter to resolveAuth. Otherwise, users cannot control browser visibility when using interactive auth with other commands.

Copilot uses AI. Check for mistakes.
--json # Output as JSON (for scripting)
--token <token> # Use a specific token
-i, --interactive # Force interactive browser login
--no-headless # Show the browser window during login (don't run headless)
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation states "All commands support: --no-headless" but this option was only added to the login command. This creates a discrepancy between the documentation and the implementation. Either update the documentation to clarify that --no-headless only works with the login command, or add the option to all commands that support --interactive.

Copilot uses AI. Check for mistakes.
program.addCommand(sendCommand);
program.addCommand(draftsCommand);

if (CLOUD_ENV === 'gcc') {
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The GCC cloud notification message is logged every time the CLI runs in GCC mode, including when displaying help or running any command. While this provides visibility, it could be verbose. Consider whether this message should only appear for authentication-related operations (login, refresh, etc.) or if the current behavior is intentional for cloud environment awareness.

Suggested change
if (CLOUD_ENV === 'gcc') {
const authCommands = ['login', 'refresh', 'keepalive'];
if (CLOUD_ENV === 'gcc' && authCommands.includes(process.argv[2] ?? '')) {

Copilot uses AI. Check for mistakes.
Comment on lines +33 to +39
| `CLIPPY_CLOUD` | `commercial`, `gcc` | `commercial` | Microsoft cloud environment |
| `CLIPPY_TOKEN` | Bearer token string | — | Skip browser login with a token directly |

### Cloud Environments

- **`commercial`** — Standard Microsoft 365 (`outlook.office.com`)
- **`gcc`** — Office 365 US Government (`outlook.office365.us`)
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code accepts both 'gcc' and 'us' as values for CLIPPY_CLOUD (line 12 in endpoints.ts), but the documentation only mentions 'gcc' and 'commercial'. Either document the 'us' alias in the README and .env.example, or remove the alias to keep the API surface simpler and more predictable.

Suggested change
| `CLIPPY_CLOUD` | `commercial`, `gcc` | `commercial` | Microsoft cloud environment |
| `CLIPPY_TOKEN` | Bearer token string || Skip browser login with a token directly |
### Cloud Environments
- **`commercial`** — Standard Microsoft 365 (`outlook.office.com`)
- **`gcc`** — Office 365 US Government (`outlook.office365.us`)
| `CLIPPY_CLOUD` | `commercial`, `gcc` (`us` alias) | `commercial` | Microsoft cloud environment |
| `CLIPPY_TOKEN` | Bearer token string || Skip browser login with a token directly |
### Cloud Environments
- **`commercial`** — Standard Microsoft 365 (`outlook.office.com`)
- **`gcc`** (`us` alias) — Office 365 US Government (`outlook.office365.us`)

Copilot uses AI. Check for mistakes.
Comment on lines +22 to +26
gcc: {
outlookBase: 'https://outlook.office365.us',
loginBase: 'https://login.microsoftonline.com',
graphBase: 'https://graph.microsoft.com',
},
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The GCC configuration uses the same Graph API and Login endpoints as commercial. While this is correct for Office 365 GCC (Government Community Cloud), the code should include a comment explaining this to avoid confusion. GCC High and DoD environments would need different endpoints (graph.microsoft.us and login.microsoftonline.us), so documenting why these are the same would help future maintainers understand the distinction.

Copilot uses AI. Check for mistakes.
Comment on lines +39 to +40
- **`gcc`** — Office 365 US Government (`outlook.office365.us`)

Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation should clarify that this is specifically Office 365 GCC (Government Community Cloud), not GCC High or DoD, which would require different endpoints. Consider adding a note like "Note: This is for Office 365 GCC only. GCC High and DoD environments are not currently supported." This helps users understand the scope of government cloud support.

Suggested change
- **`gcc`** — Office 365 US Government (`outlook.office365.us`)
- **`gcc`** — Office 365 GCC (US Government Community Cloud) (`outlook.office365.us`)
> Note: The `gcc` option targets the Office 365 GCC (Government Community Cloud) environment only. GCC High and DoD environments are not currently supported and require different endpoints.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants