Skip to content

[DX-786] Streamline Global Flags#146

Merged
umair-ably merged 8 commits intomainfrom
DX-786-global-commands
Mar 5, 2026
Merged

[DX-786] Streamline Global Flags#146
umair-ably merged 8 commits intomainfrom
DX-786-global-commands

Conversation

@umair-ably
Copy link
Contributor

@umair-ably umair-ably commented Mar 3, 2026

Summary by CodeRabbit

  • New Features

    • CLI now supports environment-first authentication (ABLY_API_KEY, ABLY_TOKEN, ABLY_ACCESS_TOKEN) and account-level endpoint storage.
  • Refactor

    • Global flag architecture reworked: core/product/control flag groups and a client-id flag were introduced; many commands now use the new flag sets.
  • Documentation

    • Help/examples updated to demonstrate environment-variable auth usage.
  • Tests

    • Unit and e2e tests migrated to environment-based auth and updated to align with new flags.

@vercel
Copy link

vercel bot commented Mar 3, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cli-web-cli Ready Ready Preview, Comment Mar 5, 2026 1:17pm

Request Review

@umair-ably umair-ably requested a review from Copilot March 3, 2026 23:25
@coderabbitai
Copy link

coderabbitai bot commented Mar 3, 2026

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 8aadf70d-aef5-48a9-87e6-57cc80bccbe6

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

Prioritizes environment-based authentication (ABLY_TOKEN, ABLY_API_KEY, ABLY_ACCESS_TOKEN), centralizes flag sets in a new flags module, updates base/feature command classes to use composed flag groups, adds endpoint storage to config manager, and adjusts numerous commands and tests to use environment-driven auth and new flags.

Changes

Cohort / File(s) Summary
Flag Infrastructure
src/flags.ts
New exports defining composable flag groups: coreGlobalFlags, hiddenProductApiFlags, hiddenControlApiFlags, clientIdFlag, endpointFlag, plus productApiFlags and controlApiFlags.
Base Command Classes
src/base-command.ts, src/control-base-command.ts, src/spaces-base-command.ts, src/chat-base-command.ts
Switch to composed global flags (coreGlobalFlags, productApiFlags, controlApiFlags), add env-first auth resolution (ABLY_TOKEN / ABLY_API_KEY / ABLY_ACCESS_TOKEN), add applyApiKeyAuth, update auth display/hiding logic and endpoint/control-host resolution.
Config manager & types
src/services/config-manager.ts, test/helpers/mock-config-manager.ts, src/types/cli.ts
Add endpoint?: string to AccountConfig; add getEndpoint and storeEndpoint to ConfigManager and test mock; remove several CLI-auth fields from BaseFlags (access-token, env, host, token).
Account commands
src/commands/accounts/login.ts, src/commands/accounts/switch.ts
Add endpointFlag to login/switch flags; persist endpoint via configManager.storeEndpoint when provided.
Control API base usage
src/control-base-command.ts
Now uses controlApiFlags; access token sourced from ABLY_ACCESS_TOKEN env with preserved account fallback and updated error messaging.
Product API commands (bulk)
src/commands/** (channels/, logs/, bench/, connections/test.ts, apps/, rooms/, spaces/, queues/, version.ts, config/, etc.)
Updated ~40+ command files to spread appropriate composed flag sets (productApiFlags, controlApiFlags, and where applicable clientIdFlag/endpointFlag); examples updated to show environment-variable auth (ABLY_API_KEY / ABLY_ACCESS_TOKEN / ABLY_TOKEN) and removed many inline --api-key / --access-token examples.
Auth/token commands
src/commands/auth/* (issue-ably-token, issue-jwt-token, revoke-token)
Switch static flags to productApiFlags and update examples to env-based token usage.
ClientId additions
src/commands/*/presence/*, src/commands/*/rooms/*, src/commands/spaces/*
Added clientIdFlag to relevant presence/rooms/spaces commands' static flags.
Tests - unit & e2e
test/unit/**, test/e2e/** (many files)
Updated numerous tests to set ABLY_ACCESS_TOKEN / ABLY_API_KEY / ABLY_TOKEN in process/env or spawn env instead of passing --access-token/--api-key flags; updated mocks and assertions accordingly; added/updated getEndpoint mock usage.
Interactive/autocomplete & docs
test/unit/commands/interactive-autocomplete.test.ts, .claude/CLAUDE.md
Updated manifest expectations and docs for new flag architecture (verbose, web-cli-help, product flags) and removed deprecated global flags from test assertions and docs.

Sequence Diagram(s)

sequenceDiagram
  participant CLI as CLI (flags/args)
  participant ENV as Environment (ABLY_* vars)
  participant Config as ConfigManager
  participant Auth as Auth Helper (applyApiKeyAuth / resolve)
  participant Ably as Ably Client

  CLI->>Auth: run command (flags)
  Auth->>ENV: check ABLY_TOKEN / ABLY_API_KEY / ABLY_ACCESS_TOKEN
  alt env credential found
    ENV-->>Auth: return token/apiKey
  else no env credential
    Auth->>Config: ensureAppAndKey / lookup stored apiKey/token
    Config-->>Auth: account/app key or undefined
  end
  Auth->>Auth: validate/parse apiKey (parseApiKey) if needed
  Auth->>Ably: build client options (endpoint from ENV or Config)
  Ably-->>CLI: operate with resolved auth & options
Loading

(Note: rectangle coloring not rendered in sequence syntax; components represent the sequential auth resolution flow.)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I hopped through flags both new and old,

ABLY env whispers bright and bold,
No flags cluttering paths I tread,
Endpoints stored and tests well-fed,
A tiny rabbit cheers the tidy code!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'DX-786 Streamline Global Flags' clearly identifies the primary change: refactoring and streamlining how global flags are organized and applied across commands.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch DX-786-global-commands

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
test/unit/commands/queues/create.test.ts (1)

212-215: ⚠️ Potential issue | 🟡 Minor

Add auth-header assertion for the /apps lookup call.

In Lines 212–215, this mock does not validate Authorization, so a regression on that request could slip through while the test still passes.

Patch to assert Bearer token on the intermediate request
-      nock("https://control.ably.net")
-        .get(`/v1/accounts/${accountId}/apps`)
-        .reply(200, [{ id: appId, accountId, name: "Test App" }]);
+      nock("https://control.ably.net", {
+        reqheaders: {
+          authorization: `Bearer ${customToken}`,
+        },
+      })
+        .get(`/v1/accounts/${accountId}/apps`)
+        .reply(200, [{ id: appId, accountId, name: "Test App" }]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/unit/commands/queues/create.test.ts` around lines 212 - 215, The nock
for the apps lookup does not assert the Authorization header, so add a header
assertion to the existing nock chain for the GET
`/v1/accounts/${accountId}/apps` call (the nock that currently replies 200 with
[{ id: appId, accountId, name: "Test App" }]); specifically, use nock's header
matcher (e.g., .matchHeader('authorization' /* or 'Authorization' */, `Bearer
${token}`) or the test's actual token variable) so the mock validates the same
bearer token used elsewhere in the test before replying.
src/commands/auth/revoke-token.ts (1)

193-197: ⚠️ Potential issue | 🟠 Major

Do not hardcode the revocation API hostname.

hostname: "rest.ably.io" ignores configured/account-specific endpoints, so this command can target the wrong environment after the endpoint/global-flags refactor.

Suggested fix
-      const response = await this.makeHttpRequest(
+      const response = await this.makeHttpRequest(
+        (this.getClientOptions(flags).restHost as string) || "rest.ably.io",
         keyName,
         secret,
         requestBody,
         flags.debug,
       );
   private makeHttpRequest(
+    hostname: string,
     keyName: string,
     secret: string,
     requestBody: Record<string, unknown>,
     debug: boolean,
   ): Promise<Record<string, unknown> | string | null> {
@@
-        hostname: "rest.ably.io",
+        hostname,

As per coding guidelines, "Use configuration for endpoint URLs (controlHost) instead of hardcoding endpoint URLs, following the pattern: flags.controlHost || config.controlHost || 'control.ably.net'".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/commands/auth/revoke-token.ts` around lines 193 - 197, The request to
revoke tokens currently hardcodes hostname: "rest.ably.io" in the HTTP options,
which breaks account/endpoint overrides; update the request construction in
revoke-token.ts (the object using hostname, method, path, port and path
`/keys/${keyName}/revokeTokens`) to use the configured control host instead of a
literal string by selecting flags.controlHost || config.controlHost ||
'control.ably.net' (or the equivalent controlHost variable used elsewhere) and
pass that value into the hostname field so the command respects configured
endpoints.
src/services/config-manager.ts (1)

361-367: ⚠️ Potential issue | 🟡 Minor

Potential data loss: storeAccount does not preserve the endpoint field.

The storeAccount method preserves apps and currentAppId from the existing account but does not preserve endpoint. If storeEndpoint is called before storeAccount (e.g., during a re-login flow), the stored endpoint will be lost.

🛡️ Proposed fix to preserve endpoint
     // Create or update the account entry
     this.config.accounts[alias] = {
       accessToken,
       ...accountInfo,
       apps: this.config.accounts[alias]?.apps || {},
       currentAppId: this.config.accounts[alias]?.currentAppId,
+      endpoint: this.config.accounts[alias]?.endpoint,
     };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/services/config-manager.ts` around lines 361 - 367, The storeAccount
method overwrites the account entry without preserving the existing endpoint;
update the merge in storeAccount (the assignment to this.config.accounts[alias])
to include the previous endpoint when present (e.g., pull the existing account
object from this.config.accounts[alias] and carry over .endpoint alongside apps
and currentAppId) so storeEndpoint calls done earlier are not lost; reference
the storeAccount method and the this.config.accounts[alias] merge to apply the
change.
🧹 Nitpick comments (5)
test/unit/commands/queues/delete.test.ts (1)

9-12: Use env save/restore in teardown to avoid mutating process-wide baseline state.

Line 11 unconditionally deletes ABLY_ACCESS_TOKEN; restoring the prior value is safer when tests run in shared processes.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/unit/commands/queues/delete.test.ts` around lines 9 - 12, The afterEach
teardown currently unconditionally deletes process.env.ABLY_ACCESS_TOKEN which
mutates global state; change the afterEach in
test/unit/commands/queues/delete.test.ts to save the original value (e.g. const
prevAbly = process.env.ABLY_ACCESS_TOKEN) before tests run and restore it in
afterEach (set process.env.ABLY_ACCESS_TOKEN = prevAbly or delete if it was
undefined), keeping the nock.cleanAll() call; reference the existing afterEach
and the environment key process.env.ABLY_ACCESS_TOKEN when making this change.
test/unit/commands/auth/keys/create.test.ts (1)

18-21: Prefer restoring prior ABLY_ACCESS_TOKEN value in afterEach.

Line 20 can unintentionally erase a pre-existing token for later tests. Save-and-restore keeps suite isolation stronger.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/unit/commands/auth/keys/create.test.ts` around lines 18 - 21, The
afterEach currently deletes process.env.ABLY_ACCESS_TOKEN which can clobber a
pre-existing token; instead capture the original value before tests (e.g., in a
beforeEach or at module scope) and restore it in afterEach; update the afterEach
that references process.env.ABLY_ACCESS_TOKEN to set it back to the saved value
(or delete it only if it was originally undefined) so tests restore the prior
environment state; look for the afterEach block and any related beforeEach where
you can store the originalToken variable to implement this.
test/unit/commands/queues/list.test.ts (1)

7-10: Restore original ABLY_ACCESS_TOKEN value instead of always deleting it.

If the runner starts with ABLY_ACCESS_TOKEN already set, Line 9 permanently clears it for later suites. Prefer save-and-restore to avoid cross-test pollution.

Suggested patch
-import { describe, it, expect, afterEach } from "vitest";
+import { describe, it, expect, beforeEach, afterEach } from "vitest";
 import nock from "nock";
 import { runCommand } from "@oclif/test";
 import { getMockConfigManager } from "../../../helpers/mock-config-manager.js";

 describe("queues:list command", () => {
+  let previousAccessToken: string | undefined;
+
+  beforeEach(() => {
+    previousAccessToken = process.env.ABLY_ACCESS_TOKEN;
+  });
+
   afterEach(() => {
     nock.cleanAll();
-    delete process.env.ABLY_ACCESS_TOKEN;
+    if (previousAccessToken === undefined) {
+      delete process.env.ABLY_ACCESS_TOKEN;
+    } else {
+      process.env.ABLY_ACCESS_TOKEN = previousAccessToken;
+    }
   });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/unit/commands/queues/list.test.ts` around lines 7 - 10, The afterEach
currently deletes process.env.ABLY_ACCESS_TOKEN which can clobber a pre-existing
token; change tests to save the original before mutation (e.g. capture const
originalAblyToken = process.env.ABLY_ACCESS_TOKEN at the top of the test file or
in a beforeEach) and in afterEach restore it instead of unconditionally deleting
(set process.env.ABLY_ACCESS_TOKEN = originalAblyToken or delete it when
originalAblyToken === undefined); keep the existing nock.cleanAll() call intact
and reference the afterEach cleanup block and the ABLY_ACCESS_TOKEN env var when
making the change.
src/commands/logs/connection-lifecycle/subscribe.ts (1)

12-17: Consider adding an environment variable example for consistency.

Other commands in this PR (e.g., channels subscribe, channels presence subscribe) include an example showing ABLY_API_KEY="YOUR_API_KEY" usage. Adding a similar example here would maintain consistency across the CLI documentation.

📝 Suggested example addition
   static override examples = [
     "$ ably logs connection-lifecycle subscribe",
     "$ ably logs connection-lifecycle subscribe --json",
     "$ ably logs connection-lifecycle subscribe --pretty-json",
     "$ ably logs connection-lifecycle subscribe --duration 30",
+    '$ ABLY_API_KEY="YOUR_API_KEY" ably logs connection-lifecycle subscribe',
   ];
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/commands/logs/connection-lifecycle/subscribe.ts` around lines 12 - 17,
Add a consistent environment-variable example to the static override examples
array for this command by inserting an entry like 'ABLY_API_KEY="YOUR_API_KEY" $
ably logs connection-lifecycle subscribe' into the examples list (the static
property named examples in this file/class), ensuring it follows the style and
ordering used by other commands (e.g., channels subscribe) and keeping the
existing variants (--json, --pretty-json, --duration) intact.
test/unit/base/auth-info-display.test.ts (1)

191-212: LGTM! Token display test properly validates ABLY_TOKEN handling.

The test verifies that auth info display shows token information when ABLY_TOKEN is present while hiding account info. The cleanup on line 200 is placed before assertions, which works but could be improved by using a try/finally pattern for more robust cleanup.

💡 Optional: Use try/finally for more robust cleanup
     it("should display app and auth info when ABLY_TOKEN env var is set", async function () {
       // Setup
       shouldHideAccountInfoStub.mockReturnValue(true);
       process.env.ABLY_TOKEN = "test-token-value";

-      // Execute
-      await command.testDisplayAuthInfo({});
-
-      // Cleanup
-      delete process.env.ABLY_TOKEN;
+      try {
+        // Execute
+        await command.testDisplayAuthInfo({});
+      } finally {
+        // Cleanup
+        delete process.env.ABLY_TOKEN;
+      }

       // Verify output includes token info but not account info
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/unit/base/auth-info-display.test.ts` around lines 191 - 212, The test
sets process.env.ABLY_TOKEN and currently deletes it before assertions; change
the test to ensure cleanup always runs by wrapping the execution and assertions
in a try/finally so process.env.ABLY_TOKEN is deleted in the finally block;
locate the test case referencing shouldHideAccountInfoStub,
process.env.ABLY_TOKEN, command.testDisplayAuthInfo, and logStub and move the
delete process.env.ABLY_TOKEN into the finally to guarantee environment cleanup
even if assertions fail.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/base-command.ts`:
- Around line 555-557: Restore the persisted/config-backed fallback when
building controlHost: instead of only using flags["control-host"] ||
process.env.ABLY_CONTROL_HOST, change the expression to prefer CLI flag, then
env var, then the persisted account/config value (e.g.
this.config.get('controlHost') or this.account?.controlHost — whichever API is
used in this class) and finally the default; update both call sites where
controlHost is constructed (the occurrences that use flags["control-host"] ||
process.env.ABLY_CONTROL_HOST) so the control-plane host respects the stored
account configuration.

---

Outside diff comments:
In `@src/commands/auth/revoke-token.ts`:
- Around line 193-197: The request to revoke tokens currently hardcodes
hostname: "rest.ably.io" in the HTTP options, which breaks account/endpoint
overrides; update the request construction in revoke-token.ts (the object using
hostname, method, path, port and path `/keys/${keyName}/revokeTokens`) to use
the configured control host instead of a literal string by selecting
flags.controlHost || config.controlHost || 'control.ably.net' (or the equivalent
controlHost variable used elsewhere) and pass that value into the hostname field
so the command respects configured endpoints.

In `@src/services/config-manager.ts`:
- Around line 361-367: The storeAccount method overwrites the account entry
without preserving the existing endpoint; update the merge in storeAccount (the
assignment to this.config.accounts[alias]) to include the previous endpoint when
present (e.g., pull the existing account object from this.config.accounts[alias]
and carry over .endpoint alongside apps and currentAppId) so storeEndpoint calls
done earlier are not lost; reference the storeAccount method and the
this.config.accounts[alias] merge to apply the change.

In `@test/unit/commands/queues/create.test.ts`:
- Around line 212-215: The nock for the apps lookup does not assert the
Authorization header, so add a header assertion to the existing nock chain for
the GET `/v1/accounts/${accountId}/apps` call (the nock that currently replies
200 with [{ id: appId, accountId, name: "Test App" }]); specifically, use nock's
header matcher (e.g., .matchHeader('authorization' /* or 'Authorization' */,
`Bearer ${token}`) or the test's actual token variable) so the mock validates
the same bearer token used elsewhere in the test before replying.

---

Nitpick comments:
In `@src/commands/logs/connection-lifecycle/subscribe.ts`:
- Around line 12-17: Add a consistent environment-variable example to the static
override examples array for this command by inserting an entry like
'ABLY_API_KEY="YOUR_API_KEY" $ ably logs connection-lifecycle subscribe' into
the examples list (the static property named examples in this file/class),
ensuring it follows the style and ordering used by other commands (e.g.,
channels subscribe) and keeping the existing variants (--json, --pretty-json,
--duration) intact.

In `@test/unit/base/auth-info-display.test.ts`:
- Around line 191-212: The test sets process.env.ABLY_TOKEN and currently
deletes it before assertions; change the test to ensure cleanup always runs by
wrapping the execution and assertions in a try/finally so process.env.ABLY_TOKEN
is deleted in the finally block; locate the test case referencing
shouldHideAccountInfoStub, process.env.ABLY_TOKEN, command.testDisplayAuthInfo,
and logStub and move the delete process.env.ABLY_TOKEN into the finally to
guarantee environment cleanup even if assertions fail.

In `@test/unit/commands/auth/keys/create.test.ts`:
- Around line 18-21: The afterEach currently deletes
process.env.ABLY_ACCESS_TOKEN which can clobber a pre-existing token; instead
capture the original value before tests (e.g., in a beforeEach or at module
scope) and restore it in afterEach; update the afterEach that references
process.env.ABLY_ACCESS_TOKEN to set it back to the saved value (or delete it
only if it was originally undefined) so tests restore the prior environment
state; look for the afterEach block and any related beforeEach where you can
store the originalToken variable to implement this.

In `@test/unit/commands/queues/delete.test.ts`:
- Around line 9-12: The afterEach teardown currently unconditionally deletes
process.env.ABLY_ACCESS_TOKEN which mutates global state; change the afterEach
in test/unit/commands/queues/delete.test.ts to save the original value (e.g.
const prevAbly = process.env.ABLY_ACCESS_TOKEN) before tests run and restore it
in afterEach (set process.env.ABLY_ACCESS_TOKEN = prevAbly or delete if it was
undefined), keeping the nock.cleanAll() call; reference the existing afterEach
and the environment key process.env.ABLY_ACCESS_TOKEN when making this change.

In `@test/unit/commands/queues/list.test.ts`:
- Around line 7-10: The afterEach currently deletes
process.env.ABLY_ACCESS_TOKEN which can clobber a pre-existing token; change
tests to save the original before mutation (e.g. capture const originalAblyToken
= process.env.ABLY_ACCESS_TOKEN at the top of the test file or in a beforeEach)
and in afterEach restore it instead of unconditionally deleting (set
process.env.ABLY_ACCESS_TOKEN = originalAblyToken or delete it when
originalAblyToken === undefined); keep the existing nock.cleanAll() call intact
and reference the afterEach cleanup block and the ABLY_ACCESS_TOKEN env var when
making the change.

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between d5eda59 and a3cc7fa.

📒 Files selected for processing (71)
  • src/base-command.ts
  • src/chat-base-command.ts
  • src/commands/accounts/login.ts
  • src/commands/accounts/switch.ts
  • src/commands/apps/create.ts
  • src/commands/apps/delete.ts
  • src/commands/apps/update.ts
  • src/commands/auth/issue-ably-token.ts
  • src/commands/auth/issue-jwt-token.ts
  • src/commands/auth/revoke-token.ts
  • src/commands/bench/publisher.ts
  • src/commands/bench/subscriber.ts
  • src/commands/channels/batch-publish.ts
  • src/commands/channels/history.ts
  • src/commands/channels/inspect.ts
  • src/commands/channels/list.ts
  • src/commands/channels/occupancy/get.ts
  • src/commands/channels/occupancy/subscribe.ts
  • src/commands/channels/presence/enter.ts
  • src/commands/channels/presence/subscribe.ts
  • src/commands/channels/publish.ts
  • src/commands/channels/subscribe.ts
  • src/commands/config/index.ts
  • src/commands/config/path.ts
  • src/commands/config/show.ts
  • src/commands/connections/test.ts
  • src/commands/logs/channel-lifecycle/subscribe.ts
  • src/commands/logs/connection-lifecycle/history.ts
  • src/commands/logs/connection-lifecycle/subscribe.ts
  • src/commands/logs/history.ts
  • src/commands/logs/push/history.ts
  • src/commands/logs/push/subscribe.ts
  • src/commands/logs/subscribe.ts
  • src/commands/rooms/messages/history.ts
  • src/commands/rooms/messages/reactions/remove.ts
  • src/commands/rooms/messages/reactions/send.ts
  • src/commands/rooms/messages/send.ts
  • src/commands/rooms/messages/subscribe.ts
  • src/commands/rooms/occupancy/get.ts
  • src/commands/rooms/reactions/send.ts
  • src/commands/rooms/typing/keystroke.ts
  • src/commands/rooms/typing/subscribe.ts
  • src/commands/spaces/cursors/set.ts
  • src/commands/version.ts
  • src/control-base-command.ts
  • src/flags.ts
  • src/services/config-manager.ts
  • src/spaces-base-command.ts
  • src/types/cli.ts
  • test/helpers/mock-config-manager.ts
  • test/unit/base/auth-info-display.test.ts
  • test/unit/base/base-command.test.ts
  • test/unit/commands/apps/create.test.ts
  • test/unit/commands/apps/delete.test.ts
  • test/unit/commands/apps/list.test.ts
  • test/unit/commands/apps/update.test.ts
  • test/unit/commands/auth/keys/create.test.ts
  • test/unit/commands/auth/revoke-token.test.ts
  • test/unit/commands/bench/bench.test.ts
  • test/unit/commands/bench/benchmarking.test.ts
  • test/unit/commands/channels/batch-publish.test.ts
  • test/unit/commands/channels/history.test.ts
  • test/unit/commands/channels/list.test.ts
  • test/unit/commands/channels/presence/enter.test.ts
  • test/unit/commands/channels/presence/subscribe.test.ts
  • test/unit/commands/channels/subscribe.test.ts
  • test/unit/commands/interactive-autocomplete.test.ts
  • test/unit/commands/queues/create.test.ts
  • test/unit/commands/queues/delete.test.ts
  • test/unit/commands/queues/list.test.ts
  • test/unit/commands/spaces/spaces.test.ts
💤 Files with no reviewable changes (1)
  • test/unit/commands/bench/bench.test.ts

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

Streamlines Ably CLI global flag handling by centralizing flag definitions and moving authentication inputs from CLI flags to environment variables and stored config (with per-account endpoint support).

Changes:

  • Introduces src/flags.ts to centralize shared flag sets (coreGlobalFlags, productApiFlags, controlApiFlags) and updates commands/base classes to use them.
  • Removes direct CLI flag auth overrides (e.g., --api-key, --access-token, --token) in favor of env vars (ABLY_API_KEY, ABLY_ACCESS_TOKEN, ABLY_TOKEN) + config resolution.
  • Adds per-account endpoint persistence in config and updates unit tests + command examples accordingly.

Reviewed changes

Copilot reviewed 71 out of 71 changed files in this pull request and generated no comments.

Show a summary per file
File Description
test/unit/commands/spaces/spaces.test.ts Updates spaces tests to rely on config/env auth instead of --api-key.
test/unit/commands/queues/list.test.ts Switches access-token test to ABLY_ACCESS_TOKEN env var and cleans env after tests.
test/unit/commands/queues/delete.test.ts Switches access-token test to ABLY_ACCESS_TOKEN env var and cleans env after tests.
test/unit/commands/queues/create.test.ts Switches access-token test to ABLY_ACCESS_TOKEN env var and cleans env after tests.
test/unit/commands/interactive-autocomplete.test.ts Updates autocomplete expectations to reflect the new global/base flag set (e.g., verbose/web-cli-help).
test/unit/commands/channels/subscribe.test.ts Removes --api-key usage; relies on config/env auth.
test/unit/commands/channels/presence/subscribe.test.ts Removes --api-key usage; relies on config/env auth.
test/unit/commands/channels/presence/enter.test.ts Removes --api-key usage; relies on config/env auth.
test/unit/commands/channels/list.test.ts Removes --api-key usage; relies on config/env auth.
test/unit/commands/channels/history.test.ts Removes --api-key usage; relies on config/env auth.
test/unit/commands/channels/batch-publish.test.ts Removes --api-key usage; relies on config/env auth.
test/unit/commands/bench/benchmarking.test.ts Removes --api-key usage; relies on config/env auth.
test/unit/commands/bench/bench.test.ts Removes --api-key usage; relies on config/env auth.
test/unit/commands/auth/revoke-token.test.ts Removes --api-key usage; relies on config/env auth.
test/unit/commands/auth/keys/create.test.ts Switches access-token test to ABLY_ACCESS_TOKEN env var and cleans env after tests.
test/unit/commands/apps/update.test.ts Switches access-token test to ABLY_ACCESS_TOKEN env var and cleans env after tests.
test/unit/commands/apps/list.test.ts Switches access-token test to ABLY_ACCESS_TOKEN env var.
test/unit/commands/apps/delete.test.ts Switches access-token test to ABLY_ACCESS_TOKEN env var and cleans env after tests.
test/unit/commands/apps/create.test.ts Switches access-token test to ABLY_ACCESS_TOKEN env var and cleans env after tests.
test/unit/base/base-command.test.ts Updates base-command tests for endpoint/auth behavior (env + config manager getEndpoint).
test/unit/base/auth-info-display.test.ts Aligns “hide account info” behavior with env-var based auth (ABLY_TOKEN, ABLY_API_KEY, ABLY_ACCESS_TOKEN).
test/helpers/mock-config-manager.ts Adds endpoint storage/retrieval to the mock ConfigManager.
src/types/cli.ts Updates BaseFlags typing to reflect the streamlined/public flag surface.
src/spaces-base-command.ts Uses productApiFlags as the global flag set for Spaces commands.
src/chat-base-command.ts Uses productApiFlags as the global flag set for Chat commands.
src/flags.ts New centralized flag definitions and composites for product vs control API commands.
src/base-command.ts Refactors auth resolution to env-vars/config + introduces shared auth helper (applyApiKeyAuth) + endpoint resolution via env/config.
src/control-base-command.ts Control commands now use controlApiFlags and resolve access token from env/config (no CLI override).
src/services/config-manager.ts Adds per-account endpoint support (getEndpoint/storeEndpoint) to config manager + TOML persistence.
src/commands/version.ts Uses coreGlobalFlags rather than the previous broader global flag set.
src/commands/config/show.ts Uses coreGlobalFlags.
src/commands/config/path.ts Uses coreGlobalFlags.
src/commands/config/index.ts Uses coreGlobalFlags.
src/commands/logs/subscribe.ts Uses productApiFlags for product API command flag surface.
src/commands/logs/history.ts Uses productApiFlags for product API command flag surface.
src/commands/logs/push/subscribe.ts Uses productApiFlags (and custom flags) for product API log subscription.
src/commands/logs/push/history.ts Uses productApiFlags for product API command flag surface.
src/commands/logs/connection-lifecycle/subscribe.ts Uses productApiFlags for product API command flag surface.
src/commands/logs/connection-lifecycle/history.ts Uses productApiFlags for product API command flag surface.
src/commands/logs/channel-lifecycle/subscribe.ts Uses productApiFlags (and custom flags) for product API log subscription.
src/commands/connections/test.ts Uses productApiFlags.
src/commands/channels/subscribe.ts Uses productApiFlags and updates examples to env-var auth.
src/commands/channels/publish.ts Uses productApiFlags and updates examples to env-var auth.
src/commands/channels/presence/subscribe.ts Uses productApiFlags + clientIdFlag and updates examples to env-var auth.
src/commands/channels/presence/enter.ts Uses productApiFlags + clientIdFlag and updates examples to env-var auth.
src/commands/channels/occupancy/subscribe.ts Uses productApiFlags and updates examples to env-var auth.
src/commands/channels/occupancy/get.ts Uses productApiFlags and updates examples to env-var auth.
src/commands/channels/list.ts Uses productApiFlags.
src/commands/channels/inspect.ts Uses productApiFlags plus hidden control flags for mixed product/control behavior.
src/commands/channels/history.ts Uses productApiFlags.
src/commands/channels/batch-publish.ts Uses productApiFlags.
src/commands/bench/subscriber.ts Uses productApiFlags.
src/commands/bench/publisher.ts Uses productApiFlags.
src/commands/auth/revoke-token.ts Uses productApiFlags.
src/commands/auth/issue-jwt-token.ts Uses productApiFlags and updates examples to ABLY_TOKEN=... pattern.
src/commands/auth/issue-ably-token.ts Uses productApiFlags and updates examples to ABLY_TOKEN=... pattern.
src/commands/apps/update.ts Updates examples to ABLY_ACCESS_TOKEN=... pattern.
src/commands/apps/delete.ts Updates examples to ABLY_ACCESS_TOKEN=... pattern.
src/commands/apps/create.ts Updates examples to ABLY_ACCESS_TOKEN=... pattern.
src/commands/accounts/login.ts Adds --endpoint support (stored in account config) and adopts new flag composition.
src/commands/accounts/switch.ts Adds --endpoint support (stored in account config) and adopts new flag composition.
src/commands/spaces/cursors/set.ts Updates examples to ABLY_API_KEY=... pattern.
src/commands/rooms/typing/subscribe.ts Updates examples to ABLY_API_KEY=... pattern.
src/commands/rooms/typing/keystroke.ts Updates examples to ABLY_API_KEY=... pattern.
src/commands/rooms/reactions/send.ts Updates examples to ABLY_API_KEY=... pattern.
src/commands/rooms/occupancy/get.ts Updates examples to ABLY_API_KEY=... pattern.
src/commands/rooms/messages/subscribe.ts Updates examples to ABLY_API_KEY=... pattern.
src/commands/rooms/messages/send.ts Updates examples to ABLY_API_KEY=... pattern.
src/commands/rooms/messages/reactions/send.ts Updates examples to ABLY_API_KEY=... pattern.
src/commands/rooms/messages/reactions/remove.ts Updates examples to ABLY_API_KEY=... pattern.
src/commands/rooms/messages/history.ts Updates examples to ABLY_API_KEY=... pattern.
Comments suppressed due to low confidence (2)

src/commands/logs/channel-lifecycle/subscribe.ts:24

  • productApiFlags already provides json/pretty-json with mutual exclusivity. Overriding json here removes the exclusive constraint from the base flag definition, so --json and --pretty-json can be supplied together. Either rely on the shared json flag from productApiFlags, or add back the exclusive: ["pretty-json"] constraint in this override.
  static override flags = {
    ...productApiFlags,
    json: Flags.boolean({
      default: false,
      description: "Output results as JSON",
    }),

src/commands/logs/push/subscribe.ts:23

  • productApiFlags already defines json/pretty-json as mutually exclusive global flags. Re-defining json here overrides that definition and drops the exclusive constraint, allowing --json and --pretty-json to be passed together. Consider removing this local json flag override, or re-adding the exclusive: ["pretty-json"] constraint so behavior stays consistent.

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

@umair-ably
Copy link
Contributor Author

umair-ably commented Mar 3, 2026

PR description isn't exactly true... the commit message is more accurate:

Replaced monolithic globalFlags (16 flags on every command) with
composable flag groups. Utility commands like ably version now only show
--verbose/--json. Auth flags (--api-key, --access-token, --token) removed
entirely — auth is via ably login or env vars (ABLY_API_KEY, ABLY_TOKEN,
ABLY_ACCESS_TOKEN). Moved --endpoint to login/switch only, stored per-account
in config. Removed --env and --host. Kept --client-id on presence commands.

We already had env vars for access token and api key... I've introduced token since we've removed --token usage. We've not positioned this as the prefered way of auth.

Base automatically changed from stats-command-FTF-262 to main March 4, 2026 14:00
umair-ably and others added 3 commits March 4, 2026 14:02
  DX-786: Replaced monolithic globalFlags (16 flags on every command) with
  composable flag groups. Utility commands like `ably version` now only show
  --verbose/--json. Auth flags (--api-key, --access-token, --token) removed
  entirely — auth is via `ably login` or env vars (ABLY_API_KEY, ABLY_TOKEN,
  ABLY_ACCESS_TOKEN). Moved --endpoint to login/switch only, stored per-account
  in config. Removed --env and --host. Kept --client-id on presence commands.
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

Copilot reviewed 85 out of 86 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (2)

src/commands/logs/push/subscribe.ts:23

  • productApiFlags already defines --json with mutual exclusivity against --pretty-json. Redefining json here overrides that and allows both flags at once, which can lead to ambiguous output formatting. Consider removing this override and relying on productApiFlags, or re-adding exclusive: ["pretty-json"] to the local json flag definition.
    src/commands/logs/channel-lifecycle/subscribe.ts:24
  • productApiFlags already defines --json as mutually exclusive with --pretty-json. This local json redefinition overrides that behavior, so users could pass both flags simultaneously. Consider removing the duplicate json flag or keeping the exclusivity (exclusive: ["pretty-json"]) when overriding.
  static override flags = {
    ...productApiFlags,
    json: Flags.boolean({
      default: false,
      description: "Output results as JSON",
    }),

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

**Auth in tests — use environment variables, NEVER CLI flags:**
```typescript
// ❌ WRONG — --api-key, --token, --access-token are NOT CLI flags
runCommand(["channels", "publish", "my-channel", "hello", "--api-key", key]);
Copy link
Contributor

Choose a reason for hiding this comment

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

@coderabbitai what do you think about using runCommand(["channels", "publish", "my-channel", "hello", "--api-key", key]); vs

runCommand(["channels", "publish", "my-channel", "hello"], {
  env: { ABLY_API_KEY: key },
});

Since ably-cli is mainly a cli tool, its easier to pass access-token directly right? Do you think both options should be provided

Copy link

Choose a reason for hiding this comment

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

@sacOO7, great question — this is essentially a security vs. usability tradeoff, and the PR has made a deliberate architectural call. Here's the reasoning behind each side:


Why flags (--api-key) feel natural for a CLI tool

  • Discoverability — flags appear in --help output, making auth self-documenting
  • Explicit — no need to know about env var conventions upfront
  • Easy for one-off commandsably channels publish my-channel hello --api-key app.key:secret is concise

Why the PR chose env vars only

  1. Security — CLI flags appear in shell history (~/.bash_history, ~/.zsh_history) and in the process list (ps aux), potentially leaking secrets
  2. Cleaner flag surface — removing auth flags from every command reduces noise (previously 16 global flags on every command)
  3. CI/CD alignment — env vars are the standard way secrets are injected in pipelines
  4. Consistencyably login stores credentials once; env vars override for scripting. There's no need for a third mechanism

Should both be supported?

Supporting both would directly conflict with the PR's stated goal:

"Authentication flags (--api-key, --access-token, --token) are removed from command-level flags; auth is handled via ably login or environment variables"

Adding --api-key back as a flag on individual commands would reintroduce the very problem this PR is solving — proliferating auth flags across all commands.

If discoverability is a concern, a middle ground worth considering (without reverting the design) would be to mention env vars in the --help output or in a dedicated ably auth --help section. But supporting both as equivalent CLI options would undermine the security and UX simplification goals of this PR.

@sacOO7
Copy link
Contributor

sacOO7 commented Mar 5, 2026

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Mar 5, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (3)
test/unit/commands/interactive-autocomplete.test.ts (1)

692-701: Misleading comment: verbose, json, and pretty-json are not from productApiFlags.

Line 692's comment states "base flags from productApiFlags," but json, pretty-json, verbose, and web-cli-help are typically from global/base flags, not productApiFlags. The actual productApiFlags (port, tlsPort, tls) are correctly identified in the section starting at line 698.

📝 Suggested comment fix
-      // Check for base flags from productApiFlags
+      // Check for base/global flags
       expect(batchPublish.flags).toHaveProperty("json");
       expect(batchPublish.flags).toHaveProperty("pretty-json");
       expect(batchPublish.flags).toHaveProperty("verbose");
       expect(batchPublish.flags).toHaveProperty("web-cli-help");

-      // Check for product API flags (hidden)
+      // Check for productApiFlags (port, tlsPort, tls)
       expect(batchPublish.flags).toHaveProperty("port");
       expect(batchPublish.flags).toHaveProperty("tlsPort");
       expect(batchPublish.flags).toHaveProperty("tls");
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/unit/commands/interactive-autocomplete.test.ts` around lines 692 - 701,
Update the misleading test comment: change the comment that reads "base flags
from productApiFlags" to accurately state that json, pretty-json, verbose, and
web-cli-help are base/global flags (not from productApiFlags), and keep a
separate comment noting that productApiFlags are the hidden flags checked via
batchPublish.flags for "port", "tlsPort", and "tls"; reference
batchPublish.flags and productApiFlags in the updated comment to make the
distinction clear.
test/e2e/stats/stats.test.ts (1)

68-71: Consider deduplicating the repeated token env object.

A shared constant would reduce repetition and make future auth-env changes safer.

♻️ Proposed refactor
 const E2E_ACCESS_TOKEN = process.env.E2E_ABLY_ACCESS_TOKEN;
+const ACCESS_TOKEN_ENV = { ABLY_ACCESS_TOKEN: E2E_ACCESS_TOKEN! };
...
-          const result = await runCommand(["stats", "account"], {
-            timeoutMs: 60000,
-            env: { ABLY_ACCESS_TOKEN: E2E_ACCESS_TOKEN! },
-          });
+          const result = await runCommand(["stats", "account"], {
+            timeoutMs: 60000,
+            env: ACCESS_TOKEN_ENV,
+          });
...
-              env: { ABLY_ACCESS_TOKEN: E2E_ACCESS_TOKEN! },
+              env: ACCESS_TOKEN_ENV,

Also applies to: 91-95

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/e2e/stats/stats.test.ts` around lines 68 - 71, The test repeats the env
object with ABLY_ACCESS_TOKEN and E2E_ACCESS_TOKEN! in multiple runCommand
calls; extract a single shared constant (e.g., const authEnv = {
ABLY_ACCESS_TOKEN: E2E_ACCESS_TOKEN! }) near the top of the test file and
replace the inline env: { ABLY_ACCESS_TOKEN: E2E_ACCESS_TOKEN! } in each
runCommand invocation (references: runCommand and E2E_ACCESS_TOKEN) so future
auth-env changes are centralized and DRY.
test/unit/commands/channels/list.test.ts (1)

70-70: Add a regression assertion that --api-key is no longer exposed.

You removed --api-key from invocations, but there isn’t a direct assertion guarding the new CLI surface.

Suggested test addition
 describe("flags", () => {
+  it("should not expose --api-key flag", async () => {
+    const { stdout } = await runCommand(
+      ["channels:list", "--help"],
+      import.meta.url,
+    );
+
+    expect(stdout).not.toContain("--api-key");
+  });
+
   it("should accept --limit flag", async () => {

As per coding guidelines "Update or add tests when new features or changes are made, ensuring all tests pass before deeming work complete."

Also applies to: 88-88, 99-99, 108-108, 117-117, 126-126, 139-139, 163-163, 184-184

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/unit/commands/channels/list.test.ts` at line 70, Add a regression
assertion in the channels:list unit tests to verify the CLI no longer exposes
the deprecated --api-key flag: after calling runCommand(["channels:list"],
import.meta.url) assert that stdout (or the command help/output captured) does
not include the string "--api-key" (e.g.,
expect(stdout).not.toContain("--api-key")). Update the corresponding test cases
that call runCommand (references: the test file
test/unit/commands/channels/list.test.ts and the runCommand invocations around
lines referenced in the review) so each invocation includes this negative
assertion to guard the new CLI surface.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/base-command.ts`:
- Around line 588-594: The code currently constructs a truncatedToken from
process.env.ABLY_TOKEN (tokenFromEnv / truncatedToken) and prints it; remove any
creation or display of truncatedToken and stop exposing token fragments in auth
info output. Instead, change the auth-info branch that checks tokenFromEnv to
not include token material—use a non-sensitive indicator (e.g., "token: present"
or "token: redacted") or a boolean flag, and remove references to truncatedToken
and tokenFromEnv from any logging/return values in the same function/logic that
builds auth info.

In `@src/commands/channels/publish.ts`:
- Around line 38-39: Remove the clientIdFlag spread from the flags for the
channels publish command: locate the flags array/assignment where
...productApiFlags and ...clientIdFlag are spread (the channels publish command
definition) and delete the ...clientIdFlag entry so --client-id is not available
on publish; leave all other flags (e.g., productApiFlags) unchanged.

In `@src/services/config-manager.ts`:
- Around line 377-387: storeEndpoint writes accounts[alias].endpoint but
storeAccount later overwrites the entire account object and drops endpoint;
update storeAccount to preserve any existing endpoint (e.g., read const
existingEndpoint = this.config.accounts[alias]?.endpoint and include endpoint:
existingEndpoint when reconstructing the account) or merge the incoming account
data with the existing account instead of replacing it wholesale so stored
endpoints are not lost.

---

Nitpick comments:
In `@test/e2e/stats/stats.test.ts`:
- Around line 68-71: The test repeats the env object with ABLY_ACCESS_TOKEN and
E2E_ACCESS_TOKEN! in multiple runCommand calls; extract a single shared constant
(e.g., const authEnv = { ABLY_ACCESS_TOKEN: E2E_ACCESS_TOKEN! }) near the top of
the test file and replace the inline env: { ABLY_ACCESS_TOKEN: E2E_ACCESS_TOKEN!
} in each runCommand invocation (references: runCommand and E2E_ACCESS_TOKEN) so
future auth-env changes are centralized and DRY.

In `@test/unit/commands/channels/list.test.ts`:
- Line 70: Add a regression assertion in the channels:list unit tests to verify
the CLI no longer exposes the deprecated --api-key flag: after calling
runCommand(["channels:list"], import.meta.url) assert that stdout (or the
command help/output captured) does not include the string "--api-key" (e.g.,
expect(stdout).not.toContain("--api-key")). Update the corresponding test cases
that call runCommand (references: the test file
test/unit/commands/channels/list.test.ts and the runCommand invocations around
lines referenced in the review) so each invocation includes this negative
assertion to guard the new CLI surface.

In `@test/unit/commands/interactive-autocomplete.test.ts`:
- Around line 692-701: Update the misleading test comment: change the comment
that reads "base flags from productApiFlags" to accurately state that json,
pretty-json, verbose, and web-cli-help are base/global flags (not from
productApiFlags), and keep a separate comment noting that productApiFlags are
the hidden flags checked via batchPublish.flags for "port", "tlsPort", and
"tls"; reference batchPublish.flags and productApiFlags in the updated comment
to make the distinction clear.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 1d8dd185-b64b-4a20-8c13-605fce878e69

📥 Commits

Reviewing files that changed from the base of the PR and between a3cc7fa and 65d9590.

📒 Files selected for processing (86)
  • .claude/CLAUDE.md
  • README.md
  • src/base-command.ts
  • src/chat-base-command.ts
  • src/commands/accounts/login.ts
  • src/commands/accounts/switch.ts
  • src/commands/apps/create.ts
  • src/commands/apps/delete.ts
  • src/commands/apps/update.ts
  • src/commands/auth/issue-ably-token.ts
  • src/commands/auth/issue-jwt-token.ts
  • src/commands/auth/revoke-token.ts
  • src/commands/bench/publisher.ts
  • src/commands/bench/subscriber.ts
  • src/commands/channels/batch-publish.ts
  • src/commands/channels/history.ts
  • src/commands/channels/inspect.ts
  • src/commands/channels/list.ts
  • src/commands/channels/occupancy/get.ts
  • src/commands/channels/occupancy/subscribe.ts
  • src/commands/channels/presence/enter.ts
  • src/commands/channels/presence/subscribe.ts
  • src/commands/channels/publish.ts
  • src/commands/channels/subscribe.ts
  • src/commands/config/index.ts
  • src/commands/config/path.ts
  • src/commands/config/show.ts
  • src/commands/connections/test.ts
  • src/commands/logs/channel-lifecycle/subscribe.ts
  • src/commands/logs/connection-lifecycle/history.ts
  • src/commands/logs/connection-lifecycle/subscribe.ts
  • src/commands/logs/history.ts
  • src/commands/logs/push/history.ts
  • src/commands/logs/push/subscribe.ts
  • src/commands/logs/subscribe.ts
  • src/commands/rooms/messages/history.ts
  • src/commands/rooms/messages/reactions/remove.ts
  • src/commands/rooms/messages/reactions/send.ts
  • src/commands/rooms/messages/send.ts
  • src/commands/rooms/messages/subscribe.ts
  • src/commands/rooms/occupancy/get.ts
  • src/commands/rooms/presence/enter.ts
  • src/commands/rooms/presence/subscribe.ts
  • src/commands/rooms/reactions/send.ts
  • src/commands/rooms/typing/keystroke.ts
  • src/commands/rooms/typing/subscribe.ts
  • src/commands/spaces/cursors/get-all.ts
  • src/commands/spaces/cursors/set.ts
  • src/commands/spaces/cursors/subscribe.ts
  • src/commands/spaces/locations/set.ts
  • src/commands/spaces/locations/subscribe.ts
  • src/commands/spaces/locks/acquire.ts
  • src/commands/spaces/locks/subscribe.ts
  • src/commands/spaces/members/enter.ts
  • src/commands/spaces/members/subscribe.ts
  • src/commands/version.ts
  • src/control-base-command.ts
  • src/flags.ts
  • src/services/config-manager.ts
  • src/spaces-base-command.ts
  • src/types/cli.ts
  • test/e2e/bench/bench.test.ts
  • test/e2e/connections/connections.test.ts
  • test/e2e/stats/stats.test.ts
  • test/helpers/mock-config-manager.ts
  • test/unit/base/auth-info-display.test.ts
  • test/unit/base/base-command.test.ts
  • test/unit/commands/apps/create.test.ts
  • test/unit/commands/apps/delete.test.ts
  • test/unit/commands/apps/list.test.ts
  • test/unit/commands/apps/update.test.ts
  • test/unit/commands/auth/keys/create.test.ts
  • test/unit/commands/auth/revoke-token.test.ts
  • test/unit/commands/bench/bench.test.ts
  • test/unit/commands/bench/benchmarking.test.ts
  • test/unit/commands/channels/batch-publish.test.ts
  • test/unit/commands/channels/history.test.ts
  • test/unit/commands/channels/list.test.ts
  • test/unit/commands/channels/presence/enter.test.ts
  • test/unit/commands/channels/presence/subscribe.test.ts
  • test/unit/commands/channels/subscribe.test.ts
  • test/unit/commands/interactive-autocomplete.test.ts
  • test/unit/commands/queues/create.test.ts
  • test/unit/commands/queues/delete.test.ts
  • test/unit/commands/queues/list.test.ts
  • test/unit/commands/spaces/spaces.test.ts
💤 Files with no reviewable changes (1)
  • test/unit/commands/bench/bench.test.ts
✅ Files skipped from review due to trivial changes (1)
  • src/commands/rooms/messages/reactions/send.ts
🚧 Files skipped from review as they are similar to previous changes (40)
  • test/unit/commands/channels/presence/subscribe.test.ts
  • src/commands/apps/delete.ts
  • src/commands/logs/push/subscribe.ts
  • test/unit/commands/queues/create.test.ts
  • src/commands/rooms/messages/reactions/remove.ts
  • src/commands/bench/subscriber.ts
  • src/commands/channels/occupancy/subscribe.ts
  • src/commands/rooms/reactions/send.ts
  • src/commands/auth/revoke-token.ts
  • test/unit/commands/bench/benchmarking.test.ts
  • test/unit/commands/channels/subscribe.test.ts
  • src/commands/logs/connection-lifecycle/subscribe.ts
  • src/commands/spaces/cursors/set.ts
  • src/commands/config/show.ts
  • src/commands/channels/presence/subscribe.ts
  • src/commands/apps/update.ts
  • src/commands/connections/test.ts
  • src/commands/logs/subscribe.ts
  • src/commands/accounts/login.ts
  • src/commands/channels/occupancy/get.ts
  • test/unit/commands/apps/delete.test.ts
  • src/commands/rooms/typing/keystroke.ts
  • src/commands/rooms/occupancy/get.ts
  • test/unit/commands/apps/update.test.ts
  • src/commands/apps/create.ts
  • src/commands/logs/push/history.ts
  • test/unit/commands/apps/create.test.ts
  • src/chat-base-command.ts
  • test/unit/commands/auth/keys/create.test.ts
  • src/commands/accounts/switch.ts
  • src/commands/config/index.ts
  • src/commands/rooms/messages/subscribe.ts
  • test/unit/commands/queues/list.test.ts
  • test/helpers/mock-config-manager.ts
  • test/unit/commands/queues/delete.test.ts
  • test/unit/commands/apps/list.test.ts
  • src/commands/bench/publisher.ts
  • src/commands/channels/list.ts
  • src/commands/version.ts
  • src/commands/rooms/messages/history.ts

Copy link
Contributor

@sacOO7 sacOO7 left a comment

Choose a reason for hiding this comment

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

BTW, while checking the flow for ably login =>

  1. It opens the browser and prompts for an access-token.
  2. After entering the access token, there doesn’t seem to be a way to log out.

So, I had a few questions:

  1. Can we add logout command that revokes the Control API access token?
  2. Would it make sense to group both login and logout under an auth command? For example:
    • ably auth login
    • ably auth logout
  3. If we decide to keep login and logout as top-level commands, perhaps login could appear as the first command and logout as the last in ably --help?

@umair-ably
Copy link
Contributor Author

BTW, while checking the flow for ably login =>

  1. It opens the browser and prompts for an access-token.
  2. After entering the access token, there doesn’t seem to be a way to log out.

So, I had a few questions:

  1. Can we add logout command that revokes the Control API access token?

  2. Would it make sense to group both login and logout under an auth command? For example:

    • ably auth login
    • ably auth logout
  3. If we decide to keep login and logout as top-level commands, perhaps login could appear as the first command and logout as the last in ably --help?

@sacOO7

  1. ably accounts logout already exists. It removes the stored access token and all app configurations for the account from local config.
  2. Currently logout only clears local config but doesn't revoke the Control API access token on the server. This is beyond the scope of this PR - also there's a new OAuth flow coming soon that will change how this would work. We can address this later.
  3. The auth topic already exists but serves a different purpose. accounts is CLI session management (login, logout, switch, list, current), while auth is Ably product-level auth operations (creating tokens, revoking tokens, managing API keys). These are intentionally separate concerns. accounts login authenticates you to the CLI, auth commands manage auth credentials for your Ably apps. Merging them would conflate the two.
  4. oclif sorts command topics alphabetically, so accounts already appears first. We could aliases and what not but not worth it right now imo... we can revisit later.

@umair-ably umair-ably requested a review from sacOO7 March 5, 2026 13:38
@sacOO7
Copy link
Contributor

sacOO7 commented Mar 5, 2026

I think overall ably --help command order should be reviewed/updated. Maybe we can ask claude/other LLM

Copy link
Contributor

@sacOO7 sacOO7 left a comment

Choose a reason for hiding this comment

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

LGMT ( PS. seems I missed out on login/logout)

@umair-ably umair-ably merged commit bf46338 into main Mar 5, 2026
10 checks passed
@umair-ably umair-ably deleted the DX-786-global-commands branch March 5, 2026 13:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

4 participants