Skip to content

Apply decoupled config strategy to preview sites#2807

Merged
bcotrim merged 15 commits intostu-1350-decoupled-config-devfrom
stu-1350-decoupled-config-dev-v1
Mar 17, 2026
Merged

Apply decoupled config strategy to preview sites#2807
bcotrim merged 15 commits intostu-1350-decoupled-config-devfrom
stu-1350-decoupled-config-dev-v1

Conversation

@bcotrim
Copy link
Copy Markdown
Contributor

@bcotrim bcotrim commented Mar 13, 2026

Related issues

How AI was used in this PR

TBD

Proposed Changes

Extends the decoupled config strategy (implemented for sites in PR #2701) to preview sites:

  • CLI now owns preview site data: Snapshots are stored in ~/.studio/cli.json instead of appdata-v1.json
  • New cli-config.ts: Centralized config management with Zod schema validation and file locking for safe concurrent writes
  • Studio reads via CLI: Renderer calls preview list --format json to fetch snapshots from the CLI config
  • New preview set command: Allows updating snapshot settings (e.g., preview set <hostname> --name "New Name"). Follows the same pattern as site set
  • preview create now supports --name: Optionally name a preview site at creation time
  • Redux store initialization: Moved refreshSnapshots() to store setup (avoiding module-load timing issues in tests)

This maintains consistency with the decoupled strategy: CLI is the source of truth for data, Studio accesses it via CLI commands.

Testing Instructions

  1. Build and test locally: npm run cli:build && npm test
  2. Create a preview site with a name: studio preview create /path/to/site --name "My Preview"
  3. List previews: studio preview list --format json (shows all snapshots)
  4. Rename a preview: studio preview set <hostname> --name "New Name"
  5. Verify in Studio UI: Snapshots load correctly and display the new names
  6. Verify file location: Check that ~/.studio/cli.json contains the snapshots (not appdata)

Pre-merge Checklist

  • All tests pass (typecheck, linter, unit tests)
  • No TypeScript, React, or console errors
  • File locking used for concurrent config access (cli-config.ts)
  • Zod validation for all config reads/writes
  • Tests updated to match new data flow

- CLI stores/reads preview site data from cli.json instead of appdata
- Studio reads preview sites via CLI commands (preview list --format json)
- Added preview set command for updating snapshot settings (--name)
- Added --name option to preview create command
- Moved refreshSnapshots to store initialization with test guard
- Fixed snapshot-slice test mock setup to avoid module-load timing issues
@fredrikekelund
Copy link
Copy Markdown
Contributor

Looks like we should change the base branch here, @bcotrim

@bcotrim bcotrim changed the base branch from trunk to stu-1350-decoupled-config-dev March 16, 2026 16:15
@bcotrim bcotrim force-pushed the stu-1350-decoupled-config-dev-v1 branch from 65b0dd8 to c2c0fde Compare March 16, 2026 17:01
@bcotrim bcotrim force-pushed the stu-1350-decoupled-config-dev-v1 branch from c2c0fde to c758246 Compare March 16, 2026 17:04
@bcotrim bcotrim marked this pull request as ready for review March 16, 2026 19:48
@bcotrim bcotrim requested review from a team and fredrikekelund March 16, 2026 19:48
Copy link
Copy Markdown
Contributor

@fredrikekelund fredrikekelund left a comment

Choose a reason for hiding this comment

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

This looks good to me overall 👍 There's a question of whether we really need the app to interface with the CLI for every preview site operation, but I'm fine with landing this PR first and keeping that discussion going separately.

I haven't tested the changes yet, but I figured I'd share my feedback first. Will finalize my review once I've tested.

event: SITE_EVENTS,
data: { siteId: string }
): Promise< void > {
export async function emitCliEvent( payload: CliEventPayload ): Promise< void > {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Very gooood 👍

export type SiteEvent = z.infer< typeof siteEventSchema >;

export const snapshotEventSchema = z.object( {
event: z.nativeEnum( SNAPSHOT_EVENTS ),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
event: z.nativeEnum( SNAPSHOT_EVENTS ),
event: z.enum( SNAPSHOT_EVENTS ),

nativeEnum is deprecated in zod v4

} );

export const snapshotSocketEventSchema = z.object( {
event: z.nativeEnum( SNAPSHOT_EVENTS ),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
event: z.nativeEnum( SNAPSHOT_EVENTS ),
event: z.enum( SNAPSHOT_EVENTS ),

nativeEnum is deprecated in zod v4

} );
}

window.ipcListener.subscribe( 'snapshot-changed', ( event, snapshotEvent: SnapshotEvent ) => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
window.ipcListener.subscribe( 'snapshot-changed', ( event, snapshotEvent: SnapshotEvent ) => {
window.ipcListener.subscribe( 'snapshot-changed', ( event, snapshotEvent ) => {

The type is already defined in apps/studio/src/ipc-utils.ts

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I still expect the CLI and the app to use a shared config file that they can both read from and write to. I don't think we can get away from that. The language setting and the auth data are two good examples of things that the app shouldn't or couldn't use the CLI to write to the shared config.

With that in mind, I'd argue it's a bit overkill to introduce a CLI command just to update the name of a preview site. It's possible that CLI-only users would also want this ability, it just seems much less important in the CLI than it does in the UI.

I'm not necessarily arguing we need to walk back this change – if it works, then it works. Still, I think there are better arguments for why we need the site set command (it lets us consolidate HTTPS certificate logic in the CLI, it allows us to use only the CLI to talk to the process manager daemon, etc). In this case, we're basically just wrapping a file write operation in another process.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I was also wondering that during development.
What pushed me to make the decision to add name to edit and create preview is the fact that we show that information in the CLI. It seems strange to me to show a name to our users if we don't allow them to set or edit that name.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The performance drawbacks of "barrel files" like this don't come into play much in this context, but I would still argue that we shouldn't use them. I see no good reason for it apart from the vanity of shorter import paths.

Other than that: good idea to split up the config file functions into separate files.

Comment on lines +17 to +39
export async function fetchSnapshots(): Promise< Snapshot[] > {
try {
return await new Promise< Snapshot[] >( ( resolve, reject ) => {
const [ emitter ] = executeCliCommand( [ 'preview', 'list', '--format', 'json' ], {
output: 'capture',
} );

emitter.on( 'data', ( { data } ) => {
const parsed = snapshotListKeyValueSchema.safeParse( data );
if ( parsed.success ) {
resolve( parsed.data.value );
}
} );

emitter.on( 'success', () => resolve( [] ) );
emitter.on( 'failure', ( { error } ) => reject( error ) );
emitter.on( 'error', ( { error } ) => reject( error ) );
} );
} catch ( error ) {
console.error( 'Failed to fetch snapshots from CLI:', error );
return [];
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Similar to what I mentioned in apps/cli/commands/preview/set.ts, it seems like we're adding overhead here without super clear gains. We still need a zod schema to parse the data we receive, so why not just read directly from the shared config file?

We don't necessarily need to walk back this change (it's better to move ahead faster), but I would like to at least raise the question. It goes back to what we discussed in our huddle, @bcotrim, but if the end goal truly is to never have the app read from the shared config file, then I might need some more convincing 😄

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think the value is making Studio dependent only on the CLI, without knowing about the implementation details.
The same reasoning could be applied to operations, if Studio reads and writes from the config file, why not share the code to run the operations and remove the CLI overhead?

Comment on lines +543 to +544
// Re-fetch snapshots from CLI after any successful operation
void refreshSnapshots();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Do we really need this? 🤔 Seems like we wouldn't need such a fine-grained event system if we always just refetch the preview site list anyway.

const existing = state.snapshot.snapshots.find( ( s ) => s.url === snapshot.url );
if ( ! existing ) {
store.dispatch(
snapshotSlice.actions.setSnapshots( {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
snapshotSlice.actions.setSnapshots( {
snapshotSlice.actions.addSnapshot( {

Optional, but I think we might as well add an explicit addSnapshot action.

Comment on lines 306 to 314
store.dispatch(
wpcomApi.util.updateQueryData( 'getSnapshotUsage', undefined, ( data ) => {
// There's a risk that more sites are deleted locally than the count returned by the
// API, because expired sites are preserved locally. Therefore, we need to ensure
// the count is non-negative.
data.siteCount = Math.max( 0, data.siteCount + countDiff );
} )
);

// Wait for changes to take effect on the back-end before invalidating the query
setTimeout( () => {
store.dispatch( wpcomApi.util.invalidateTags( [ 'SnapshotUsage' ] ) );
}, 8000 );
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think it's worth putting this logic in a reusable function. Also, I wouldn't delete the comments.

Comment on lines +91 to +96
const { atomicSiteId, snapshot } = action.payload;
const state = store.getState();
const existing = state.snapshot.snapshots.find( ( s ) => s.atomicSiteId === atomicSiteId );
if ( existing?.url && snapshot.name !== undefined && snapshot.name !== existing.name ) {
await getIpcApi().setSnapshot( existing.url, { name: snapshot.name } );
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This logic doesn't work as intended, because existing.name is already updated by the time this action runs.

…le usage count helper, fix listener state bug
Copy link
Copy Markdown
Contributor

@fredrikekelund fredrikekelund left a comment

Choose a reason for hiding this comment

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

Testing works as expected with the latest changes 👍

@bcotrim bcotrim merged commit ae5be29 into stu-1350-decoupled-config-dev Mar 17, 2026
5 checks passed
@bcotrim bcotrim deleted the stu-1350-decoupled-config-dev-v1 branch March 17, 2026 14:27
bcotrim added a commit that referenced this pull request Mar 23, 2026
* Read site data from CLI instead of appdata (#2701)

* STU-1350: Read site data from CLI instead of appdata

Studio now reads site data via `site list --format json` at startup
and maintains state through CLI events subscriber. Removes direct
appdata reads for site details, simplifies SiteServer create/start
flows, and removes waitForSiteEvent synchronization.

* Fix lint: indentation in index.test.ts

* Fix typecheck: narrow SiteDetails union before accessing url

* Remove dead url branch in SiteServer.create — events subscriber handles it

* Address PR review feedback: shared schemas, keyValuePair output, simplify start/delete

* Move CLI site data to dedicated config file (#2731)

* STU-1350: Read site data from CLI instead of appdata

Studio now reads site data via `site list --format json` at startup
and maintains state through CLI events subscriber. Removes direct
appdata reads for site details, simplifies SiteServer create/start
flows, and removes waitForSiteEvent synchronization.

* Fix lint: indentation in index.test.ts

* STU-1350: Move CLI site data to dedicated cli.json config file

Split site data from appdata-v1.json into a new CLI-owned config at ~/.studio/cli.json.
Studio now reads sites exclusively via `studio site list` and _events. The CLI is the
source of truth for site configuration. Auth tokens, snapshots, locale remain in appdata.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>

* Fix delete test after trunk merge: use saveCliConfig instead of saveAppdata

* Extend require-lock-before-save eslint rule to support cli-config lock/save pairs

* Use shared lockfile constants and extract DEFAULT_CLI_CONFIG

* Fix typecheck: narrow SiteDetails union before accessing url

* Remove dead url branch in SiteServer.create — events subscriber handles it

* Fix lint: remove extra blank line in cli-config.ts

* triggert ci

* Update e2e tests to read site data from cli.json

* Address PR review feedback for cli-config

- Use structuredClone for DEFAULT_CLI_CONFIG deep copy
- Rename daemon-paths.ts to paths.ts, extract STUDIO_CLI_HOME
- Split config schema for version mismatch detection
- Improve readCliConfig error handling with version check
- Rename removeSite to removeSiteFromConfig
- Revert UPDATED event handler to warn for unknown sites

* Fix AI files to import site functions from cli-config instead of appdata

---------

Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>

* Fix AI tools test mocks to use cli-config instead of appdata

* Apply decoupled config strategy to preview sites (#2807)

* Apply decoupled config strategy to preview sites (STU-1350)

- CLI stores/reads preview site data from cli.json instead of appdata
- Studio reads preview sites via CLI commands (preview list --format json)
- Added preview set command for updating snapshot settings (--name)
- Added --name option to preview create command
- Moved refreshSnapshots to store initialization with test guard
- Fixed snapshot-slice test mock setup to avoid module-load timing issues

* Emit snapshot events to Studio via _events for realtime updates

* Move snapshot name generation from cli-config to preview create command

* Split cli-config.ts into folder structure (core, sites, snapshots)

* Rename site-events to cli-events and enrich snapshot events with inline data (STU-1350)

* Fix snapshot update infinite loop and preview set error handling

* Unify CLI event emitter, share event schemas in cli-events, and clean up daemon-client (STU-1350)

* trigger ci

* Fix import order lint errors in core.ts and site-server.ts

* Address PR review: add stdout json output, addSnapshot action, reusable usage count helper, fix listener state bug

* Remove barrel file, replace z.nativeEnum with z.enum, update imports to direct paths

* Fix import order in cli-events.ts and remove unused test imports

* Wire auth and locale to shared.json, AI settings to cli.json (#2821)

* Wire auth and locale to shared.json, AI settings to cli.json

Move auth token reads/writes from appdata to shared-config for Desktop+CLI. Move locale reads/writes to shared-config (Desktop saves, CLI reads). Move aiProvider and anthropicApiKey from shared-config to cli-config (CLI-only). Remove auth and locale fields from appdata schema and types since they're now in separate files. Update all imports and tests accordingly.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>

* Move CLI telemetry stats from appdata to cli-config

* Fix import order lint errors

* Remove CLI appdata dependency and move infrastructure paths to ~/.studio

* Revert server-files and certificate paths to appdata directory

* Watch shared config for auth changes from CLI

* Align shared config watcher with user-data watcher pattern

* trigger ci

* Address PR review feedback: events-based auth, rename types, deduplicate schemas

* Fix prettier formatting in auth test

* Fix shared-config mock in tests to export authTokenSchema

* Use z.literal for config version validation, remove unused re-export, update test mocks

* Extract authTokenSchema to avoid Node.js imports in renderer bundle

* trigger ci

* Fix daemon test to use os.tmpdir() for Windows compatibility

* Make CLI event emission best-effort in auth commands

* Throw on shared config version mismatch instead of silently returning defaults

* Add line break before version mismatch error message

* Handle version mismatch errors through standard Logger flow in auth commands

* Show only display name in AI chat status bar

---------

Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>

* Migrate appdata to ~/.studio/appdata.json with versioned migrations (#2836)

* Migrate appdata to ~/.studio/appdata.json with extensible migration framework

* Move appdata migration from CLI to Studio Desktop

* Rewrite appdata migration to split into shared.json, cli.json, and appdata.json

* trigger ci

* Ensure .studio directory exists before lockfile and fix import order

* Fix readFile mock type to return Buffer instead of string

* Refactor appdata to store only Desktop-specific state with sites as Record<id, AppdataSiteData>

* Address PR feedback: rename to app.json and siteMetadata, use zod parsing in migration

* Fix prettier formatting in user-data test

* Fix e2e migration by respecting E2E_APP_DATA_PATH in getOldAppdataPath

* new migration interface

* studio migrations

* studio migrations

* cli migrations

* Rename appdata references, centralize config paths and lockfile constants

* Isolate e2e config directory to fix test failures

* Move site metadata cleanup to SiteServer, fix typecheck and test failures

* Add APP_CONFIG_LOCKFILE_NAME constant and fix test failures

* Fix lint errors: update AI imports from appdata to cli-config

* trigger ci

* Exclude AI config fields from app.json and enforce shared config locking

* Move getSiteByFolder outside try/finally to prevent unlock without lock

* Wrap saveSharedConfig test calls with lock/unlock to satisfy lint rule

---------

Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
fredrikekelund added a commit that referenced this pull request Mar 23, 2026
* Read site data from CLI instead of appdata (#2701)

* STU-1350: Read site data from CLI instead of appdata

Studio now reads site data via `site list --format json` at startup
and maintains state through CLI events subscriber. Removes direct
appdata reads for site details, simplifies SiteServer create/start
flows, and removes waitForSiteEvent synchronization.

* Fix lint: indentation in index.test.ts

* Fix typecheck: narrow SiteDetails union before accessing url

* Remove dead url branch in SiteServer.create — events subscriber handles it

* Address PR review feedback: shared schemas, keyValuePair output, simplify start/delete

* Move CLI site data to dedicated config file (#2731)

* STU-1350: Read site data from CLI instead of appdata

Studio now reads site data via `site list --format json` at startup
and maintains state through CLI events subscriber. Removes direct
appdata reads for site details, simplifies SiteServer create/start
flows, and removes waitForSiteEvent synchronization.

* Fix lint: indentation in index.test.ts

* STU-1350: Move CLI site data to dedicated cli.json config file

Split site data from appdata-v1.json into a new CLI-owned config at ~/.studio/cli.json.
Studio now reads sites exclusively via `studio site list` and _events. The CLI is the
source of truth for site configuration. Auth tokens, snapshots, locale remain in appdata.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>

* Fix delete test after trunk merge: use saveCliConfig instead of saveAppdata

* Extend require-lock-before-save eslint rule to support cli-config lock/save pairs

* Use shared lockfile constants and extract DEFAULT_CLI_CONFIG

* Fix typecheck: narrow SiteDetails union before accessing url

* Remove dead url branch in SiteServer.create — events subscriber handles it

* Fix lint: remove extra blank line in cli-config.ts

* triggert ci

* Update e2e tests to read site data from cli.json

* Address PR review feedback for cli-config

- Use structuredClone for DEFAULT_CLI_CONFIG deep copy
- Rename daemon-paths.ts to paths.ts, extract STUDIO_CLI_HOME
- Split config schema for version mismatch detection
- Improve readCliConfig error handling with version check
- Rename removeSite to removeSiteFromConfig
- Revert UPDATED event handler to warn for unknown sites

* Fix AI files to import site functions from cli-config instead of appdata

---------

Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>

* Fix AI tools test mocks to use cli-config instead of appdata

* Apply decoupled config strategy to preview sites (#2807)

* Apply decoupled config strategy to preview sites (STU-1350)

- CLI stores/reads preview site data from cli.json instead of appdata
- Studio reads preview sites via CLI commands (preview list --format json)
- Added preview set command for updating snapshot settings (--name)
- Added --name option to preview create command
- Moved refreshSnapshots to store initialization with test guard
- Fixed snapshot-slice test mock setup to avoid module-load timing issues

* Emit snapshot events to Studio via _events for realtime updates

* Move snapshot name generation from cli-config to preview create command

* Split cli-config.ts into folder structure (core, sites, snapshots)

* Rename site-events to cli-events and enrich snapshot events with inline data (STU-1350)

* Fix snapshot update infinite loop and preview set error handling

* Unify CLI event emitter, share event schemas in cli-events, and clean up daemon-client (STU-1350)

* trigger ci

* Fix import order lint errors in core.ts and site-server.ts

* Address PR review: add stdout json output, addSnapshot action, reusable usage count helper, fix listener state bug

* Remove barrel file, replace z.nativeEnum with z.enum, update imports to direct paths

* Fix import order in cli-events.ts and remove unused test imports

* Migrate appdata to ~/.studio/appdata.json with extensible migration framework

* Move appdata migration from CLI to Studio Desktop

* Wire auth and locale to shared.json, AI settings to cli.json (#2821)

* Wire auth and locale to shared.json, AI settings to cli.json

Move auth token reads/writes from appdata to shared-config for Desktop+CLI. Move locale reads/writes to shared-config (Desktop saves, CLI reads). Move aiProvider and anthropicApiKey from shared-config to cli-config (CLI-only). Remove auth and locale fields from appdata schema and types since they're now in separate files. Update all imports and tests accordingly.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>

* Move CLI telemetry stats from appdata to cli-config

* Fix import order lint errors

* Remove CLI appdata dependency and move infrastructure paths to ~/.studio

* Revert server-files and certificate paths to appdata directory

* Watch shared config for auth changes from CLI

* Align shared config watcher with user-data watcher pattern

* trigger ci

* Address PR review feedback: events-based auth, rename types, deduplicate schemas

* Fix prettier formatting in auth test

* Fix shared-config mock in tests to export authTokenSchema

* Use z.literal for config version validation, remove unused re-export, update test mocks

* Extract authTokenSchema to avoid Node.js imports in renderer bundle

* trigger ci

* Fix daemon test to use os.tmpdir() for Windows compatibility

* Make CLI event emission best-effort in auth commands

* Throw on shared config version mismatch instead of silently returning defaults

* Add line break before version mismatch error message

* Handle version mismatch errors through standard Logger flow in auth commands

* Show only display name in AI chat status bar

---------

Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>

* Rewrite appdata migration to split into shared.json, cli.json, and appdata.json

* trigger ci

* Ensure .studio directory exists before lockfile and fix import order

* Fix readFile mock type to return Buffer instead of string

* Refactor appdata to store only Desktop-specific state with sites as Record<id, AppdataSiteData>

* Address PR feedback: rename to app.json and siteMetadata, use zod parsing in migration

* Fix prettier formatting in user-data test

* Fix e2e migration by respecting E2E_APP_DATA_PATH in getOldAppdataPath

* new migration interface

* studio migrations

* studio migrations

* cli migrations

* Rename appdata references, centralize config paths and lockfile constants

* Isolate e2e config directory to fix test failures

* Move site metadata cleanup to SiteServer, fix typecheck and test failures

* HTTPS certificate migration

* Rename file

* Add APP_CONFIG_LOCKFILE_NAME constant and fix test failures

* Fix merge conflict

---------

Co-authored-by: Bernardo Cotrim <bmmcotrim@gmail.com>
Co-authored-by: bcotrim <bernardo.cotrim@a8c.com>
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
fredrikekelund added a commit that referenced this pull request Mar 24, 2026
* Read site data from CLI instead of appdata (#2701)

* STU-1350: Read site data from CLI instead of appdata

Studio now reads site data via `site list --format json` at startup
and maintains state through CLI events subscriber. Removes direct
appdata reads for site details, simplifies SiteServer create/start
flows, and removes waitForSiteEvent synchronization.

* Fix lint: indentation in index.test.ts

* Fix typecheck: narrow SiteDetails union before accessing url

* Remove dead url branch in SiteServer.create — events subscriber handles it

* Address PR review feedback: shared schemas, keyValuePair output, simplify start/delete

* Move CLI site data to dedicated config file (#2731)

* STU-1350: Read site data from CLI instead of appdata

Studio now reads site data via `site list --format json` at startup
and maintains state through CLI events subscriber. Removes direct
appdata reads for site details, simplifies SiteServer create/start
flows, and removes waitForSiteEvent synchronization.

* Fix lint: indentation in index.test.ts

* STU-1350: Move CLI site data to dedicated cli.json config file

Split site data from appdata-v1.json into a new CLI-owned config at ~/.studio/cli.json.
Studio now reads sites exclusively via `studio site list` and _events. The CLI is the
source of truth for site configuration. Auth tokens, snapshots, locale remain in appdata.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>

* Fix delete test after trunk merge: use saveCliConfig instead of saveAppdata

* Extend require-lock-before-save eslint rule to support cli-config lock/save pairs

* Use shared lockfile constants and extract DEFAULT_CLI_CONFIG

* Fix typecheck: narrow SiteDetails union before accessing url

* Remove dead url branch in SiteServer.create — events subscriber handles it

* Fix lint: remove extra blank line in cli-config.ts

* triggert ci

* Update e2e tests to read site data from cli.json

* Address PR review feedback for cli-config

- Use structuredClone for DEFAULT_CLI_CONFIG deep copy
- Rename daemon-paths.ts to paths.ts, extract STUDIO_CLI_HOME
- Split config schema for version mismatch detection
- Improve readCliConfig error handling with version check
- Rename removeSite to removeSiteFromConfig
- Revert UPDATED event handler to warn for unknown sites

* Fix AI files to import site functions from cli-config instead of appdata

---------

Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>

* Fix AI tools test mocks to use cli-config instead of appdata

* Apply decoupled config strategy to preview sites (#2807)

* Apply decoupled config strategy to preview sites (STU-1350)

- CLI stores/reads preview site data from cli.json instead of appdata
- Studio reads preview sites via CLI commands (preview list --format json)
- Added preview set command for updating snapshot settings (--name)
- Added --name option to preview create command
- Moved refreshSnapshots to store initialization with test guard
- Fixed snapshot-slice test mock setup to avoid module-load timing issues

* Emit snapshot events to Studio via _events for realtime updates

* Move snapshot name generation from cli-config to preview create command

* Split cli-config.ts into folder structure (core, sites, snapshots)

* Rename site-events to cli-events and enrich snapshot events with inline data (STU-1350)

* Fix snapshot update infinite loop and preview set error handling

* Unify CLI event emitter, share event schemas in cli-events, and clean up daemon-client (STU-1350)

* trigger ci

* Fix import order lint errors in core.ts and site-server.ts

* Address PR review: add stdout json output, addSnapshot action, reusable usage count helper, fix listener state bug

* Remove barrel file, replace z.nativeEnum with z.enum, update imports to direct paths

* Fix import order in cli-events.ts and remove unused test imports

* Migrate appdata to ~/.studio/appdata.json with extensible migration framework

* Move appdata migration from CLI to Studio Desktop

* Wire auth and locale to shared.json, AI settings to cli.json (#2821)

* Wire auth and locale to shared.json, AI settings to cli.json

Move auth token reads/writes from appdata to shared-config for Desktop+CLI. Move locale reads/writes to shared-config (Desktop saves, CLI reads). Move aiProvider and anthropicApiKey from shared-config to cli-config (CLI-only). Remove auth and locale fields from appdata schema and types since they're now in separate files. Update all imports and tests accordingly.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>

* Move CLI telemetry stats from appdata to cli-config

* Fix import order lint errors

* Remove CLI appdata dependency and move infrastructure paths to ~/.studio

* Revert server-files and certificate paths to appdata directory

* Watch shared config for auth changes from CLI

* Align shared config watcher with user-data watcher pattern

* trigger ci

* Address PR review feedback: events-based auth, rename types, deduplicate schemas

* Fix prettier formatting in auth test

* Fix shared-config mock in tests to export authTokenSchema

* Use z.literal for config version validation, remove unused re-export, update test mocks

* Extract authTokenSchema to avoid Node.js imports in renderer bundle

* trigger ci

* Fix daemon test to use os.tmpdir() for Windows compatibility

* Make CLI event emission best-effort in auth commands

* Throw on shared config version mismatch instead of silently returning defaults

* Add line break before version mismatch error message

* Handle version mismatch errors through standard Logger flow in auth commands

* Show only display name in AI chat status bar

---------

Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>

* Rewrite appdata migration to split into shared.json, cli.json, and appdata.json

* trigger ci

* Ensure .studio directory exists before lockfile and fix import order

* Fix readFile mock type to return Buffer instead of string

* Refactor appdata to store only Desktop-specific state with sites as Record<id, AppdataSiteData>

* Address PR feedback: rename to app.json and siteMetadata, use zod parsing in migration

* Fix prettier formatting in user-data test

* Fix e2e migration by respecting E2E_APP_DATA_PATH in getOldAppdataPath

* new migration interface

* studio migrations

* studio migrations

* cli migrations

* Rename appdata references, centralize config paths and lockfile constants

* Isolate e2e config directory to fix test failures

* Move site metadata cleanup to SiteServer, fix typecheck and test failures

* HTTPS certificate migration

* Rename file

* Initial server-files migration implementation

In this implementation, Studio copies the entire server-files directory to a well-known location. This, by itself, is not enough to make the CLI standalone. We need to actually distribute the wp-files files with the CLI.

* Add APP_CONFIG_LOCKFILE_NAME constant and fix test failures

* Actually move server-files to CLI management

* Fix test

* Fix merge conflict

* Exclude wp-files from app bundle

* Load sites from `SiteServer.getAll()`

* Various fixes

* Fix lint

* Fix

* Improved `updateServerFiles` error handling

* Remove fs-extra

* Abstract GitHub release fetching

* Include wp-files in package.json files

* Fix errors

* Remove outdated wp-now migration

* Fix tests

* Fix issues identified by agentic review

* Setup server-files in middleware

* Address issues raised by AI review

* Fix more review issues

* Set up and update in parallel

* Remove unused code

* Remove unused import

---------

Co-authored-by: Bernardo Cotrim <bmmcotrim@gmail.com>
Co-authored-by: bcotrim <bernardo.cotrim@a8c.com>
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
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