diff --git a/docs/docs/cmd/spo/tenant/tenant-homesite-list.mdx b/docs/docs/cmd/spo/tenant/tenant-homesite-list.mdx
new file mode 100644
index 0000000000..aca1da65c8
--- /dev/null
+++ b/docs/docs/cmd/spo/tenant/tenant-homesite-list.mdx
@@ -0,0 +1,95 @@
+import Global from '/docs/cmd/_global.mdx';
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+# spo homesite list
+
+Lists all home sites
+
+## Usage
+
+```sh
+m365 spo tenant homesite list [options]
+```
+
+## Options
+
+
+
+## Examples
+
+List all home sites
+
+```sh
+m365 spo tenant homesite list
+```
+
+## Response
+
+
+
+
+ ```json
+ [
+ {
+ "Audiences": [
+ {
+ "Email": "ColumnSearchable@contoso.onmicrosoft.com",
+ "Id": "978b5280-4f80-47ea-a1db-b0d1d2fb1ba4",
+ "Title": "ColumnSearchable Members"
+ }
+ ],
+ "IsInDraftMode": false,
+ "IsVivaBackendSite": false,
+ "SiteId": "431d7819-4aaf-49a1-b664-b2fe9e609b63",
+ "TargetedLicenseType": 2,
+ "Title": "The Landing",
+ "Url": "https://contoso.sharepoint.com/sites/TheLanding",
+ "VivaConnectionsDefaultStart": true,
+ "WebId": "626c1724-8ac8-45d5-af87-c07c752fab75"
+ }
+ ]
+ ```
+
+
+
+
+ ```text
+ Url Title
+ ----------------------------------------------- -----------
+ https://contoso.sharepoint.com/sites/TheLanding The Landing
+ ```
+
+
+
+
+ ```csv
+ IsInDraftMode,IsVivaBackendSite,SiteId,TargetedLicenseType,Title,Url,VivaConnectionsDefaultStart,WebId
+ 0,0,431d7819-4aaf-49a1-b664-b2fe9e609b63,2,The Landing,https://contoso.sharepoint.com/sites/TheLanding,1,626c1724-8ac8-45d5-af87-c07c752fab75
+ ```
+
+
+
+
+ ```md
+ # spo homesite list
+
+ Date: 11/18/2024
+
+ Property | Value
+ ---------|-------
+ IsInDraftMode | false
+ IsVivaBackendSite | false
+ SiteId | 431d7819-4aaf-49a1-b664-b2fe9e609b63
+ TargetedLicenseType | 2
+ Title | The Landing
+ Url | https://contoso.sharepoint.com/sites/TheLanding
+ VivaConnectionsDefaultStart | true
+ WebId | 626c1724-8ac8-45d5-af87-c07c752fab75
+ ```
+
+
+
+## More information
+
+- SharePoint home sites [Viva Connections set up](https://learn.microsoft.com/en-us/viva/connections/set-up-admin-center)
diff --git a/docs/src/config/sidebars.ts b/docs/src/config/sidebars.ts
index 06ed8558b5..4cc2725043 100644
--- a/docs/src/config/sidebars.ts
+++ b/docs/src/config/sidebars.ts
@@ -3737,6 +3737,11 @@ const sidebars: SidebarsConfig = {
label: 'tenant commandset set',
id: 'cmd/spo/tenant/tenant-commandset-set'
},
+ {
+ type: 'doc',
+ label: 'homesite list',
+ id: 'cmd/spo/tenant/tenant-homesite-list'
+ },
{
type: 'doc',
label: 'tenant recyclebinitem list',
diff --git a/src/m365/spo/commands.ts b/src/m365/spo/commands.ts
index 9ad1de6b0f..f17b2edca2 100644
--- a/src/m365/spo/commands.ts
+++ b/src/m365/spo/commands.ts
@@ -318,6 +318,7 @@ export default {
TENANT_COMMANDSET_LIST: `${prefix} tenant commandset list`,
TENANT_COMMANDSET_REMOVE: `${prefix} tenant commandset remove`,
TENANT_COMMANDSET_SET: `${prefix} tenant commandset set`,
+ TENANT_HOMESITE_LIST: `${prefix} tenant homesite list`,
TENANT_RECYCLEBINITEM_LIST: `${prefix} tenant recyclebinitem list`,
TENANT_RECYCLEBINITEM_REMOVE: `${prefix} tenant recyclebinitem remove`,
TENANT_RECYCLEBINITEM_RESTORE: `${prefix} tenant recyclebinitem restore`,
diff --git a/src/m365/spo/commands/tenant/tenant-homesite-list.spec.ts b/src/m365/spo/commands/tenant/tenant-homesite-list.spec.ts
new file mode 100644
index 0000000000..c046e6d4b7
--- /dev/null
+++ b/src/m365/spo/commands/tenant/tenant-homesite-list.spec.ts
@@ -0,0 +1,123 @@
+import assert from 'assert';
+import sinon from 'sinon';
+import auth from '../../../../Auth.js';
+import { Logger } from '../../../../cli/Logger.js';
+import { CommandError } from '../../../../Command.js';
+import request from '../../../../request.js';
+import { telemetry } from '../../../../telemetry.js';
+import { pid } from '../../../../utils/pid.js';
+import { session } from '../../../../utils/session.js';
+import { sinonUtil } from '../../../../utils/sinonUtil.js';
+import commands from '../../commands.js';
+import command from './tenant-homesite-list.js';
+
+describe(commands.TENANT_HOMESITE_LIST, () => {
+ let log: string[];
+ let logger: Logger;
+ let loggerLogSpy: sinon.SinonSpy;
+ const homeSites = {
+ "value": [
+ {
+ "Audiences": [
+ {
+ "Email": "ColumnSearchable@contoso.onmicrosoft.com",
+ "Id": "978b5280-4f80-47ea-a1db-b0d1d2fb1ba4",
+ "Title": "ColumnSearchable Members"
+ },
+ {
+ "Email": "contosoteam@contoso.onmicrosoft.com",
+ "Id": "21af775d-17b3-4637-94a4-2ba8625277cb",
+ "Title": "Contoso TeamR Members"
+ }
+ ],
+ "IsInDraftMode": false,
+ "IsVivaBackendSite": false,
+ "SiteId": "431d7819-4aaf-49a1-b664-b2fe9e609b63",
+ "TargetedLicenseType": 2,
+ "Title": "The Landing",
+ "Url": "https://contoso.sharepoint.com/sites/TheLanding",
+ "VivaConnectionsDefaultStart": true,
+ "WebId": "626c1724-8ac8-45d5-af87-c07c752fab75"
+ },
+ {
+ "Audiences": [],
+ "IsInDraftMode": false,
+ "IsVivaBackendSite": false,
+ "SiteId": "45d4a135-40e4-4571-8340-61d17fdfd58a",
+ "TargetedLicenseType": 0,
+ "Title": "Contoso Electronics",
+ "Url": "https://contoso.sharepoint.com/sites/contosoportal",
+ "VivaConnectionsDefaultStart": true,
+ "WebId": "9418e2a1-855c-4752-8dd4-48693f43b10a"
+ }
+ ]
+ };
+
+ before(() => {
+ sinon.stub(auth, 'restoreAuth').resolves();
+ sinon.stub(telemetry, 'trackEvent').returns();
+ sinon.stub(pid, 'getProcessName').returns('');
+ sinon.stub(session, 'getId').returns('');
+ auth.connection.active = true;
+ auth.connection.spoUrl = 'https://contoso.sharepoint.com';
+ });
+
+ beforeEach(() => {
+ log = [];
+ logger = {
+ log: async (msg: string) => {
+ log.push(msg);
+ },
+ logRaw: async (msg: string) => {
+ log.push(msg);
+ },
+ logToStderr: async (msg: string) => {
+ log.push(msg);
+ }
+ };
+ loggerLogSpy = sinon.spy(logger, 'log');
+ });
+
+ afterEach(() => {
+ sinonUtil.restore([
+ request.get
+ ]);
+ });
+
+ after(() => {
+ sinon.restore();
+ auth.connection.active = false;
+ auth.connection.spoUrl = undefined;
+ });
+
+ it('has correct name', () => {
+ assert.strictEqual(command.name, commands.TENANT_HOMESITE_LIST);
+ });
+
+ it('has a description', () => {
+ assert.notStrictEqual(command.description, null);
+ });
+
+ it('defines correct properties for the default output', () => {
+ assert.deepStrictEqual(command.defaultProperties(), ['Url', 'Title']);
+ });
+
+ it('lists available home sites', async () => {
+ sinon.stub(request, 'get').callsFake(async (opts) => {
+ if (opts.url === `https://contoso-admin.sharepoint.com/_api/SPO.Tenant/GetTargetedSitesDetails`) {
+ return homeSites;
+ }
+
+ throw opts.url;
+ });
+
+ await command.action(logger, { options: { verbose: true } });
+ assert(loggerLogSpy.calledWith(homeSites.value));
+ });
+
+ it('correctly handles OData error when retrieving available home sites', async () => {
+ sinon.stub(request, 'get').rejects({ error: { 'odata.error': { message: { value: 'An error has occurred' } } } });
+
+ await assert.rejects(command.action(logger, { options: {} } as any), new CommandError('An error has occurred'));
+ });
+});
diff --git a/src/m365/spo/commands/tenant/tenant-homesite-list.ts b/src/m365/spo/commands/tenant/tenant-homesite-list.ts
new file mode 100644
index 0000000000..5595fb3920
--- /dev/null
+++ b/src/m365/spo/commands/tenant/tenant-homesite-list.ts
@@ -0,0 +1,43 @@
+import { Logger } from '../../../../cli/Logger.js';
+import { odata } from '../../../../utils/odata.js';
+import { spo } from '../../../../utils/spo.js';
+import SpoCommand from '../../../base/SpoCommand.js';
+import commands from '../../commands.js';
+import { CliRequestOptions } from "../../../../request.js";
+
+class SpoTenantHomeSiteListCommand extends SpoCommand {
+ public get name(): string {
+ return commands.TENANT_HOMESITE_LIST;
+ }
+
+ public get description(): string {
+ return 'Lists all home sites';
+ }
+
+ public defaultProperties(): string[] | undefined {
+ return ['Url', 'Title'];
+ }
+
+ public async commandAction(logger: Logger): Promise {
+ try {
+ const spoAdminUrl: string = await spo.getSpoAdminUrl(logger, this.verbose);
+ const requestOptions: CliRequestOptions = {
+ url: `${spoAdminUrl}/_api/SPO.Tenant/GetTargetedSitesDetails`,
+ headers: {
+ accept: 'application/json;odata=nometadata'
+ },
+ responseType: 'json'
+ };
+ if (this.verbose) {
+ await logger.logToStderr(`Retrieving all home sites...`);
+ }
+ const res = await odata.getAllItems(requestOptions);
+ await logger.log(res);
+ }
+ catch (err: any) {
+ this.handleRejectedODataJsonPromise(err);
+ }
+ }
+}
+
+export default new SpoTenantHomeSiteListCommand();
\ No newline at end of file