diff --git a/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts b/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts
index 5e87af4fc..dfeffb0cb 100644
--- a/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts
+++ b/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts
@@ -335,6 +335,8 @@ import { UserFields } from './contributions/user-fields';
 import { UpdateIndexes } from './contributions/update-indexes';
 import { InterfaceScale } from './contributions/interface-scale';
 import { OpenHandler } from '@theia/core/lib/browser/opener-service';
+import { NewCloudSketch } from './contributions/new-cloud-sketch';
+import { SketchbookCompositeWidget } from './widgets/sketchbook/sketchbook-composite-widget';
 
 const registerArduinoThemes = () => {
   const themes: MonacoThemeJson[] = [
@@ -751,6 +753,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
   Contribution.configure(bind, DeleteSketch);
   Contribution.configure(bind, UpdateIndexes);
   Contribution.configure(bind, InterfaceScale);
+  Contribution.configure(bind, NewCloudSketch);
 
   bindContributionProvider(bind, StartupTaskProvider);
   bind(StartupTaskProvider).toService(BoardsServiceProvider); // to reuse the boards config in another window
@@ -905,6 +908,11 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
     id: 'arduino-sketchbook-widget',
     createWidget: () => container.get(SketchbookWidget),
   }));
+  bind(SketchbookCompositeWidget).toSelf();
+  bind<WidgetFactory>(WidgetFactory).toDynamicValue((ctx) => ({
+    id: 'sketchbook-composite-widget',
+    createWidget: () => ctx.container.get(SketchbookCompositeWidget),
+  }));
 
   bind(CloudSketchbookWidget).toSelf();
   rebind(SketchbookWidget).toService(CloudSketchbookWidget);
diff --git a/arduino-ide-extension/src/browser/contributions/close.ts b/arduino-ide-extension/src/browser/contributions/close.ts
index 033d02edd..61885d49c 100644
--- a/arduino-ide-extension/src/browser/contributions/close.ts
+++ b/arduino-ide-extension/src/browser/contributions/close.ts
@@ -65,7 +65,7 @@ export class Close extends SketchContribution {
     registry.registerMenuAction(ArduinoMenus.FILE__SKETCH_GROUP, {
       commandId: Close.Commands.CLOSE.id,
       label: nls.localize('vscode/editor.contribution/close', 'Close'),
-      order: '5',
+      order: '6',
     });
   }
 
diff --git a/arduino-ide-extension/src/browser/contributions/new-cloud-sketch.ts b/arduino-ide-extension/src/browser/contributions/new-cloud-sketch.ts
new file mode 100644
index 000000000..d7fb671bd
--- /dev/null
+++ b/arduino-ide-extension/src/browser/contributions/new-cloud-sketch.ts
@@ -0,0 +1,247 @@
+import { MenuModelRegistry } from '@theia/core/lib/common/menu';
+import { KeybindingRegistry } from '@theia/core/lib/browser/keybinding';
+import { CompositeTreeNode } from '@theia/core/lib/browser/tree';
+import { DisposableCollection } from '@theia/core/lib/common/disposable';
+import { nls } from '@theia/core/lib/common/nls';
+import { inject, injectable } from '@theia/core/shared/inversify';
+import { MainMenuManager } from '../../common/main-menu-manager';
+import type { AuthenticationSession } from '../../node/auth/types';
+import { AuthenticationClientService } from '../auth/authentication-client-service';
+import { CreateApi } from '../create/create-api';
+import { CreateUri } from '../create/create-uri';
+import { Create } from '../create/typings';
+import { ArduinoMenus } from '../menu/arduino-menus';
+import { WorkspaceInputDialog } from '../theia/workspace/workspace-input-dialog';
+import { CloudSketchbookTree } from '../widgets/cloud-sketchbook/cloud-sketchbook-tree';
+import { CloudSketchbookTreeModel } from '../widgets/cloud-sketchbook/cloud-sketchbook-tree-model';
+import { CloudSketchbookTreeWidget } from '../widgets/cloud-sketchbook/cloud-sketchbook-tree-widget';
+import { SketchbookCommands } from '../widgets/sketchbook/sketchbook-commands';
+import { SketchbookWidget } from '../widgets/sketchbook/sketchbook-widget';
+import { SketchbookWidgetContribution } from '../widgets/sketchbook/sketchbook-widget-contribution';
+import { Command, CommandRegistry, Contribution, URI } from './contribution';
+
+@injectable()
+export class NewCloudSketch extends Contribution {
+  @inject(CreateApi)
+  private readonly createApi: CreateApi;
+  @inject(SketchbookWidgetContribution)
+  private readonly widgetContribution: SketchbookWidgetContribution;
+  @inject(AuthenticationClientService)
+  private readonly authenticationService: AuthenticationClientService;
+  @inject(MainMenuManager)
+  private readonly mainMenuManager: MainMenuManager;
+
+  private readonly toDispose = new DisposableCollection();
+  private _session: AuthenticationSession | undefined;
+  private _enabled: boolean;
+
+  override onReady(): void {
+    this.toDispose.pushAll([
+      this.authenticationService.onSessionDidChange((session) => {
+        const oldSession = this._session;
+        this._session = session;
+        if (!!oldSession !== !!this._session) {
+          this.mainMenuManager.update();
+        }
+      }),
+      this.preferences.onPreferenceChanged(({ preferenceName, newValue }) => {
+        if (preferenceName === 'arduino.cloud.enabled') {
+          const oldEnabled = this._enabled;
+          this._enabled = Boolean(newValue);
+          if (this._enabled !== oldEnabled) {
+            this.mainMenuManager.update();
+          }
+        }
+      }),
+    ]);
+    this._enabled = this.preferences['arduino.cloud.enabled'];
+    this._session = this.authenticationService.session;
+    if (this._session) {
+      this.mainMenuManager.update();
+    }
+  }
+
+  onStop(): void {
+    this.toDispose.dispose();
+  }
+
+  override registerCommands(registry: CommandRegistry): void {
+    registry.registerCommand(NewCloudSketch.Commands.NEW_CLOUD_SKETCH, {
+      execute: () => this.createNewSketch(),
+      isEnabled: () => !!this._session,
+      isVisible: () => this._enabled,
+    });
+  }
+
+  override registerMenus(registry: MenuModelRegistry): void {
+    registry.registerMenuAction(ArduinoMenus.FILE__SKETCH_GROUP, {
+      commandId: NewCloudSketch.Commands.NEW_CLOUD_SKETCH.id,
+      label: nls.localize('arduino/cloudSketch/new', 'New Remote Sketch'),
+      order: '1',
+    });
+  }
+
+  override registerKeybindings(registry: KeybindingRegistry): void {
+    registry.registerKeybinding({
+      command: NewCloudSketch.Commands.NEW_CLOUD_SKETCH.id,
+      keybinding: 'CtrlCmd+Alt+N',
+    });
+  }
+
+  private async createNewSketch(
+    initialValue?: string | undefined
+  ): Promise<URI | undefined> {
+    const widget = await this.widgetContribution.widget;
+    const treeModel = this.treeModelFrom(widget);
+    if (!treeModel) {
+      return undefined;
+    }
+    const rootNode = CompositeTreeNode.is(treeModel.root)
+      ? treeModel.root
+      : undefined;
+    if (!rootNode) {
+      return undefined;
+    }
+
+    const newSketchName = await this.newSketchName(rootNode, initialValue);
+    if (!newSketchName) {
+      return undefined;
+    }
+    let result: Create.Sketch | undefined | 'conflict';
+    try {
+      result = await this.createApi.createSketch(newSketchName);
+    } catch (err) {
+      if (isConflict(err)) {
+        result = 'conflict';
+      } else {
+        throw err;
+      }
+    } finally {
+      if (result) {
+        await treeModel.refresh();
+      }
+    }
+
+    if (result === 'conflict') {
+      return this.createNewSketch(newSketchName);
+    }
+
+    if (result) {
+      return this.open(treeModel, result);
+    }
+    return undefined;
+  }
+
+  private async open(
+    treeModel: CloudSketchbookTreeModel,
+    newSketch: Create.Sketch
+  ): Promise<URI | undefined> {
+    const id = CreateUri.toUri(newSketch).path.toString();
+    const node = treeModel.getNode(id);
+    if (!node) {
+      throw new Error(
+        `Could not find remote sketchbook tree node with Tree node ID: ${id}.`
+      );
+    }
+    if (!CloudSketchbookTree.CloudSketchDirNode.is(node)) {
+      throw new Error(
+        `Remote sketchbook tree node expected to represent a directory but it did not. Tree node ID: ${id}.`
+      );
+    }
+    try {
+      await treeModel.sketchbookTree().pull({ node });
+    } catch (err) {
+      if (isNotFound(err)) {
+        await treeModel.refresh();
+        this.messageService.error(
+          nls.localize(
+            'arduino/newCloudSketch/notFound',
+            "Could not pull the remote sketch '{0}'. It does not exist.",
+            newSketch.name
+          )
+        );
+        return undefined;
+      }
+      throw err;
+    }
+    return this.commandService.executeCommand(
+      SketchbookCommands.OPEN_NEW_WINDOW.id,
+      { node }
+    );
+  }
+
+  private treeModelFrom(
+    widget: SketchbookWidget
+  ): CloudSketchbookTreeModel | undefined {
+    const treeWidget = widget.getTreeWidget();
+    if (treeWidget instanceof CloudSketchbookTreeWidget) {
+      const model = treeWidget.model;
+      if (model instanceof CloudSketchbookTreeModel) {
+        return model;
+      }
+    }
+    return undefined;
+  }
+
+  private async newSketchName(
+    rootNode: CompositeTreeNode,
+    initialValue?: string | undefined
+  ): Promise<string | undefined> {
+    const existingNames = rootNode.children
+      .filter(CloudSketchbookTree.CloudSketchDirNode.is)
+      .map(({ fileStat }) => fileStat.name);
+    return new WorkspaceInputDialog(
+      {
+        title: nls.localize(
+          'arduino/newCloudSketch/newSketchTitle',
+          'Name of a new Remote Sketch'
+        ),
+        parentUri: CreateUri.root,
+        initialValue,
+        validate: (input) => {
+          if (existingNames.includes(input)) {
+            return nls.localize(
+              'arduino/newCloudSketch/sketchAlreadyExists',
+              "Remote sketch '{0}' already exists.",
+              input
+            );
+          }
+          // This is how https://create.arduino.cc/editor/ works when renaming a sketch.
+          if (/^[0-9a-zA-Z_]{1,36}$/.test(input)) {
+            return '';
+          }
+          return nls.localize(
+            'arduino/newCloudSketch/invalidSketchName',
+            'The name must consist of basic letters, numbers, or underscores. The maximum length is 36 characters.'
+          );
+        },
+      },
+      this.labelProvider
+    ).open();
+  }
+}
+export namespace NewCloudSketch {
+  export namespace Commands {
+    export const NEW_CLOUD_SKETCH: Command = {
+      id: 'arduino-new-cloud-sketch',
+    };
+  }
+}
+
+function isConflict(err: unknown): boolean {
+  return isErrorWithStatusOf(err, 409);
+}
+function isNotFound(err: unknown): boolean {
+  return isErrorWithStatusOf(err, 404);
+}
+function isErrorWithStatusOf(
+  err: unknown,
+  status: number
+): err is Error & { status: number } {
+  if (err instanceof Error) {
+    // eslint-disable-next-line @typescript-eslint/no-explicit-any
+    const object = err as any;
+    return 'status' in object && object.status === status;
+  }
+  return false;
+}
diff --git a/arduino-ide-extension/src/browser/contributions/new-sketch.ts b/arduino-ide-extension/src/browser/contributions/new-sketch.ts
index bebc67767..c625fd802 100644
--- a/arduino-ide-extension/src/browser/contributions/new-sketch.ts
+++ b/arduino-ide-extension/src/browser/contributions/new-sketch.ts
@@ -21,7 +21,7 @@ export class NewSketch extends SketchContribution {
   override registerMenus(registry: MenuModelRegistry): void {
     registry.registerMenuAction(ArduinoMenus.FILE__SKETCH_GROUP, {
       commandId: NewSketch.Commands.NEW_SKETCH.id,
-      label: nls.localize('arduino/sketch/new', 'New'),
+      label: nls.localize('arduino/sketch/new', 'New Sketch'),
       order: '0',
     });
   }
diff --git a/arduino-ide-extension/src/browser/contributions/open-sketch.ts b/arduino-ide-extension/src/browser/contributions/open-sketch.ts
index e7e3f77de..5e41001c3 100644
--- a/arduino-ide-extension/src/browser/contributions/open-sketch.ts
+++ b/arduino-ide-extension/src/browser/contributions/open-sketch.ts
@@ -54,7 +54,7 @@ export class OpenSketch extends SketchContribution {
     registry.registerMenuAction(ArduinoMenus.FILE__SKETCH_GROUP, {
       commandId: OpenSketch.Commands.OPEN_SKETCH.id,
       label: nls.localize('vscode/workspaceActions/openFileFolder', 'Open...'),
-      order: '1',
+      order: '2',
     });
   }
 
diff --git a/arduino-ide-extension/src/browser/contributions/save-sketch.ts b/arduino-ide-extension/src/browser/contributions/save-sketch.ts
index 62a6b0f86..5d88433ed 100644
--- a/arduino-ide-extension/src/browser/contributions/save-sketch.ts
+++ b/arduino-ide-extension/src/browser/contributions/save-sketch.ts
@@ -24,7 +24,7 @@ export class SaveSketch extends SketchContribution {
     registry.registerMenuAction(ArduinoMenus.FILE__SKETCH_GROUP, {
       commandId: SaveSketch.Commands.SAVE_SKETCH.id,
       label: nls.localize('vscode/fileCommands/save', 'Save'),
-      order: '6',
+      order: '7',
     });
   }
 
diff --git a/arduino-ide-extension/src/browser/create/create-uri.ts b/arduino-ide-extension/src/browser/create/create-uri.ts
index 1d60ffff2..658a65ac1 100644
--- a/arduino-ide-extension/src/browser/create/create-uri.ts
+++ b/arduino-ide-extension/src/browser/create/create-uri.ts
@@ -7,7 +7,9 @@ export namespace CreateUri {
   export const scheme = 'arduino-create';
   export const root = toUri(posix.sep);
 
-  export function toUri(posixPathOrResource: string | Create.Resource): URI {
+  export function toUri(
+    posixPathOrResource: string | Create.Resource | Create.Sketch
+  ): URI {
     const posixPath =
       typeof posixPathOrResource === 'string'
         ? posixPathOrResource
diff --git a/arduino-ide-extension/src/browser/local-cache/local-cache-fs-provider.ts b/arduino-ide-extension/src/browser/local-cache/local-cache-fs-provider.ts
index 96264378a..5a9a77c71 100644
--- a/arduino-ide-extension/src/browser/local-cache/local-cache-fs-provider.ts
+++ b/arduino-ide-extension/src/browser/local-cache/local-cache-fs-provider.ts
@@ -34,7 +34,6 @@ export class LocalCacheFsProvider
   @inject(AuthenticationClientService)
   protected readonly authenticationService: AuthenticationClientService;
 
-  // TODO: do we need this? Cannot we `await` on the `init` call from `registerFileSystemProviders`?
   readonly ready = new Deferred<void>();
 
   private _localCacheRoot: URI;
@@ -153,7 +152,7 @@ export class LocalCacheFsProvider
     return uri;
   }
 
-  private toUri(session: AuthenticationSession): URI {
+  toUri(session: AuthenticationSession): URI {
     // Hack: instead of getting the UUID only, we get `auth0|UUID` after the authentication. `|` cannot be part of filesystem path or filename.
     return this._localCacheRoot.resolve(session.id.split('|')[1]);
   }
diff --git a/arduino-ide-extension/src/browser/style/dialogs.css b/arduino-ide-extension/src/browser/style/dialogs.css
index 4d56484e8..668c389b2 100644
--- a/arduino-ide-extension/src/browser/style/dialogs.css
+++ b/arduino-ide-extension/src/browser/style/dialogs.css
@@ -80,10 +80,8 @@
     opacity: .4;
 }
 
-
 @media only screen and (max-height: 560px) {
     .p-Widget.dialogOverlay .dialogBlock {
         max-height: 400px;
     }
 }
-    
\ No newline at end of file
diff --git a/arduino-ide-extension/src/browser/style/sketchbook.css b/arduino-ide-extension/src/browser/style/sketchbook.css
index dcba8d0d2..87143e60c 100644
--- a/arduino-ide-extension/src/browser/style/sketchbook.css
+++ b/arduino-ide-extension/src/browser/style/sketchbook.css
@@ -33,6 +33,22 @@
   height: 100%;
 }
 
+.sketchbook-trees-container .create-new {
+  min-height: 58px;
+  height: 58px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+/*
+By default, theia-button has a left-margin. IDE2 does not need the left margin
+for the _New Remote? Sketch_. Otherwise, the button does not fit the default
+widget width.
+*/
+.sketchbook-trees-container .create-new .theia-button {
+  margin-left: unset;
+}
+
 .sketchbook-tree__opts {
   background-color: var(--theia-foreground);
   -webkit-mask: url(./sketchbook-opts-icon.svg);
diff --git a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-composite-widget.tsx b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-composite-widget.tsx
index 5e0016922..d00ed0545 100644
--- a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-composite-widget.tsx
+++ b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-composite-widget.tsx
@@ -1,78 +1,78 @@
 import * as React from '@theia/core/shared/react';
 import * as ReactDOM from '@theia/core/shared/react-dom';
-import { inject, injectable } from '@theia/core/shared/inversify';
-import { Widget } from '@theia/core/shared/@phosphor/widgets';
-import { Message, MessageLoop } from '@theia/core/shared/@phosphor/messaging';
-import { Disposable } from '@theia/core/lib/common/disposable';
-import { BaseWidget } from '@theia/core/lib/browser/widgets/widget';
+import {
+  inject,
+  injectable,
+  postConstruct,
+} from '@theia/core/shared/inversify';
 import { UserStatus } from './cloud-user-status';
+import { nls } from '@theia/core/lib/common/nls';
 import { CloudSketchbookTreeWidget } from './cloud-sketchbook-tree-widget';
 import { AuthenticationClientService } from '../../auth/authentication-client-service';
 import { CloudSketchbookTreeModel } from './cloud-sketchbook-tree-model';
-import { nls } from '@theia/core/lib/common';
+import { BaseSketchbookCompositeWidget } from '../sketchbook/sketchbook-composite-widget';
+import { CreateNew } from '../sketchbook/create-new';
+import { AuthenticationSession } from '../../../node/auth/types';
 
 @injectable()
-export class CloudSketchbookCompositeWidget extends BaseWidget {
+export class CloudSketchbookCompositeWidget extends BaseSketchbookCompositeWidget<CloudSketchbookTreeWidget> {
   @inject(AuthenticationClientService)
-  protected readonly authenticationService: AuthenticationClientService;
-
+  private readonly authenticationService: AuthenticationClientService;
   @inject(CloudSketchbookTreeWidget)
-  protected readonly cloudSketchbookTreeWidget: CloudSketchbookTreeWidget;
-
-  private compositeNode: HTMLElement;
-  private cloudUserStatusNode: HTMLElement;
+  private readonly cloudSketchbookTreeWidget: CloudSketchbookTreeWidget;
+  private _session: AuthenticationSession | undefined;
 
   constructor() {
     super();
-    this.compositeNode = document.createElement('div');
-    this.compositeNode.classList.add('composite-node');
-    this.cloudUserStatusNode = document.createElement('div');
-    this.cloudUserStatusNode.classList.add('cloud-status-node');
-    this.compositeNode.appendChild(this.cloudUserStatusNode);
-    this.node.appendChild(this.compositeNode);
+    this.id = 'cloud-sketchbook-composite-widget';
     this.title.caption = nls.localize(
       'arduino/cloud/remoteSketchbook',
       'Remote Sketchbook'
     );
     this.title.iconClass = 'cloud-sketchbook-tree-icon';
-    this.title.closable = false;
-    this.id = 'cloud-sketchbook-composite-widget';
-  }
-
-  public getTreeWidget(): CloudSketchbookTreeWidget {
-    return this.cloudSketchbookTreeWidget;
   }
 
-  protected override onAfterAttach(message: Message): void {
-    super.onAfterAttach(message);
-    Widget.attach(this.cloudSketchbookTreeWidget, this.compositeNode);
-    ReactDOM.render(
-      <UserStatus
-        model={this.cloudSketchbookTreeWidget.model as CloudSketchbookTreeModel}
-        authenticationService={this.authenticationService}
-      />,
-      this.cloudUserStatusNode
-    );
-    this.toDisposeOnDetach.push(
-      Disposable.create(() => Widget.detach(this.cloudSketchbookTreeWidget))
+  @postConstruct()
+  protected init(): void {
+    this.toDispose.push(
+      this.authenticationService.onSessionDidChange((session) => {
+        const oldSession = this._session;
+        this._session = session;
+        if (!!oldSession !== !!this._session) {
+          this.updateFooter();
+        }
+      })
     );
   }
 
-  protected override onActivateRequest(msg: Message): void {
-    super.onActivateRequest(msg);
-
-    /* 
-      Sending a resize message is needed because otherwise the cloudSketchbookTreeWidget
-      would render empty
-    */
-    this.onResize(Widget.ResizeMessage.UnknownSize);
+  get treeWidget(): CloudSketchbookTreeWidget {
+    return this.cloudSketchbookTreeWidget;
   }
 
-  protected override onResize(message: Widget.ResizeMessage): void {
-    super.onResize(message);
-    MessageLoop.sendMessage(
-      this.cloudSketchbookTreeWidget,
-      Widget.ResizeMessage.UnknownSize
+  protected renderFooter(footerNode: HTMLElement): void {
+    ReactDOM.render(
+      <>
+        {this._session && (
+          <CreateNew
+            label={nls.localize(
+              'arduino/sketchbook/newRemoteSketch',
+              'New Remote Sketch'
+            )}
+            onClick={this.onDidClickCreateNew}
+          />
+        )}
+        <UserStatus
+          model={
+            this.cloudSketchbookTreeWidget.model as CloudSketchbookTreeModel
+          }
+          authenticationService={this.authenticationService}
+        />
+      </>,
+      footerNode
     );
   }
+
+  private onDidClickCreateNew: () => void = () => {
+    this.commandService.executeCommand('arduino-new-cloud-sketch');
+  };
 }
diff --git a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-tree-model.ts b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-tree-model.ts
index d76c7497f..666ac1ba8 100644
--- a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-tree-model.ts
+++ b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-tree-model.ts
@@ -1,20 +1,26 @@
-import { inject, injectable, postConstruct } from '@theia/core/shared/inversify';
-import { TreeNode } from '@theia/core/lib/browser/tree';
+import {
+  inject,
+  injectable,
+  postConstruct,
+} from '@theia/core/shared/inversify';
+import { CompositeTreeNode, TreeNode } from '@theia/core/lib/browser/tree';
 import { posixSegments, splitSketchPath } from '../../create/create-paths';
 import { CreateApi } from '../../create/create-api';
 import { CloudSketchbookTree } from './cloud-sketchbook-tree';
 import { AuthenticationClientService } from '../../auth/authentication-client-service';
 import { SketchbookTreeModel } from '../sketchbook/sketchbook-tree-model';
-import { ArduinoPreferences } from '../../arduino-preferences';
 import { WorkspaceNode } from '@theia/navigator/lib/browser/navigator-tree';
 import { CreateUri } from '../../create/create-uri';
-import { FileStat } from '@theia/filesystem/lib/common/files';
-import { LocalCacheFsProvider } from '../../local-cache/local-cache-fs-provider';
-import { FileService } from '@theia/filesystem/lib/browser/file-service';
+import { FileChangesEvent, FileStat } from '@theia/filesystem/lib/common/files';
+import {
+  LocalCacheFsProvider,
+  LocalCacheUri,
+} from '../../local-cache/local-cache-fs-provider';
 import URI from '@theia/core/lib/common/uri';
 import { SketchCache } from './cloud-sketch-cache';
 import { Create } from '../../create/typings';
-import { nls } from '@theia/core/lib/common';
+import { nls } from '@theia/core/lib/common/nls';
+import { Deferred } from '@theia/core/lib/common/promise-util';
 
 export function sketchBaseDir(sketch: Create.Sketch): FileStat {
   // extract the sketch path
@@ -52,26 +58,16 @@ export function sketchesToFileStats(sketches: Create.Sketch[]): FileStat[] {
 
 @injectable()
 export class CloudSketchbookTreeModel extends SketchbookTreeModel {
-  @inject(FileService)
-  protected override readonly fileService: FileService;
-
-  @inject(AuthenticationClientService)
-  protected readonly authenticationService: AuthenticationClientService;
-
   @inject(CreateApi)
-  protected readonly createApi: CreateApi;
-
-  @inject(CloudSketchbookTree)
-  protected readonly cloudSketchbookTree: CloudSketchbookTree;
-
-  @inject(ArduinoPreferences)
-  protected override readonly arduinoPreferences: ArduinoPreferences;
-
+  private readonly createApi: CreateApi;
+  @inject(AuthenticationClientService)
+  private readonly authenticationService: AuthenticationClientService;
   @inject(LocalCacheFsProvider)
-  protected readonly localCacheFsProvider: LocalCacheFsProvider;
-
+  private readonly localCacheFsProvider: LocalCacheFsProvider;
   @inject(SketchCache)
-  protected readonly sketchCache: SketchCache;
+  private readonly sketchCache: SketchCache;
+
+  private _localCacheFsProviderReady: Deferred<void> | undefined;
 
   @postConstruct()
   protected override init(): void {
@@ -81,6 +77,50 @@ export class CloudSketchbookTreeModel extends SketchbookTreeModel {
     );
   }
 
+  override *getNodesByUri(uri: URI): IterableIterator<TreeNode> {
+    if (uri.scheme === LocalCacheUri.scheme) {
+      const workspace = this.root;
+      const { session } = this.authenticationService;
+      if (session && WorkspaceNode.is(workspace)) {
+        const currentUri = this.localCacheFsProvider.to(uri);
+        if (currentUri) {
+          const rootPath = this.localCacheFsProvider
+            .toUri(session)
+            .path.toString();
+          const currentPath = currentUri.path.toString();
+          if (rootPath === currentPath) {
+            return workspace;
+          }
+          if (currentPath.startsWith(rootPath)) {
+            const id = currentPath.substring(rootPath.length);
+            const node = this.getNode(id);
+            if (node) {
+              yield node;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  protected override isRootAffected(changes: FileChangesEvent): boolean {
+    return changes.changes
+      .map(({ resource }) => resource)
+      .some(
+        (uri) => uri.parent.toString().startsWith(LocalCacheUri.root.toString()) // all files under the root might affect the tree
+      );
+  }
+
+  override async refresh(
+    parent?: Readonly<CompositeTreeNode>
+  ): Promise<CompositeTreeNode | undefined> {
+    if (parent) {
+      return super.refresh(parent);
+    }
+    await this.updateRoot();
+    return super.refresh();
+  }
+
   override async createRoot(): Promise<TreeNode | undefined> {
     const { session } = this.authenticationService;
     if (!session) {
@@ -89,7 +129,10 @@ export class CloudSketchbookTreeModel extends SketchbookTreeModel {
     }
     this.createApi.init(this.authenticationService, this.arduinoPreferences);
     this.sketchCache.init();
-    const sketches = await this.createApi.sketches();
+    const [sketches] = await Promise.all([
+      this.createApi.sketches(),
+      this.ensureLocalFsProviderReady(),
+    ]);
     const rootFileStats = sketchesToFileStats(sketches);
     if (this.workspaceService.opened) {
       const workspaceNode = WorkspaceNode.createRoot(
@@ -108,7 +151,9 @@ export class CloudSketchbookTreeModel extends SketchbookTreeModel {
     return this.tree as CloudSketchbookTree;
   }
 
-  protected override recursivelyFindSketchRoot(node: TreeNode): any {
+  protected override recursivelyFindSketchRoot(
+    node: TreeNode
+  ): TreeNode | false {
     if (node && CloudSketchbookTree.CloudSketchDirNode.is(node)) {
       return node;
     }
@@ -122,13 +167,25 @@ export class CloudSketchbookTreeModel extends SketchbookTreeModel {
   }
 
   override async revealFile(uri: URI): Promise<TreeNode | undefined> {
+    await this.localCacheFsProvider.ready.promise;
     // we use remote uris as keys for the tree
     // convert local URIs
-    const remoteuri = this.localCacheFsProvider.from(uri);
-    if (remoteuri) {
-      return super.revealFile(remoteuri);
+    const remoteUri = this.localCacheFsProvider.from(uri);
+    if (remoteUri) {
+      return super.revealFile(remoteUri);
     } else {
       return super.revealFile(uri);
     }
   }
+
+  private async ensureLocalFsProviderReady(): Promise<void> {
+    if (this._localCacheFsProviderReady) {
+      return this._localCacheFsProviderReady.promise;
+    }
+    this._localCacheFsProviderReady = new Deferred();
+    this.fileService
+      .access(LocalCacheUri.root)
+      .then(() => this._localCacheFsProviderReady?.resolve());
+    return this._localCacheFsProviderReady.promise;
+  }
 }
diff --git a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-tree-widget.tsx b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-tree-widget.tsx
index 7bb0abc73..b160842e4 100644
--- a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-tree-widget.tsx
+++ b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-tree-widget.tsx
@@ -1,5 +1,5 @@
 import * as React from '@theia/core/shared/react';
-import { inject, injectable, postConstruct } from '@theia/core/shared/inversify';
+import { inject, injectable } from '@theia/core/shared/inversify';
 import { TreeModel } from '@theia/core/lib/browser/tree/tree-model';
 import { CloudSketchbookTreeModel } from './cloud-sketchbook-tree-model';
 import { AuthenticationClientService } from '../../auth/authentication-client-service';
@@ -27,12 +27,6 @@ export class CloudSketchbookTreeWidget extends SketchbookTreeWidget {
   @inject(CloudSketchbookTree)
   protected readonly cloudSketchbookTree: CloudSketchbookTree;
 
-  @postConstruct()
-  protected override async init(): Promise<void> {
-    await super.init();
-    this.addClass('tree-container'); // Adds `height: 100%` to the tree. Otherwise you cannot see it.
-  }
-
   protected override renderTree(model: TreeModel): React.ReactNode {
     if (this.shouldShowWelcomeView()) return this.renderViewWelcome();
     if (this.shouldShowEmptyView()) return this.renderEmptyView();
diff --git a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-tree.ts b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-tree.ts
index 7204df632..7f4b44115 100644
--- a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-tree.ts
+++ b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-tree.ts
@@ -136,7 +136,7 @@ export class CloudSketchbookTree extends SketchbookTree {
         return;
       }
     }
-    this.runWithState(node, 'pulling', async (node) => {
+    return this.runWithState(node, 'pulling', async (node) => {
       const commandsCopy = node.commands;
       node.commands = [];
 
@@ -196,7 +196,7 @@ export class CloudSketchbookTree extends SketchbookTree {
         return;
       }
     }
-    this.runWithState(node, 'pushing', async (node) => {
+    return this.runWithState(node, 'pushing', async (node) => {
       if (!CloudSketchbookTree.CloudSketchTreeNode.isSynced(node)) {
         throw new Error(
           nls.localize(
@@ -269,7 +269,7 @@ export class CloudSketchbookTree extends SketchbookTree {
         return prev;
       }
 
-      // do not map "do_not_sync" files/directoris and their descendants
+      // do not map "do_not_sync" files/directories and their descendants
       const segments = path[1].split(posix.sep) || [];
       if (
         segments.some((segment) => Create.do_not_sync_files.includes(segment))
diff --git a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-widget.ts b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-widget.ts
index 22239a227..6e112eefa 100644
--- a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-widget.ts
+++ b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-widget.ts
@@ -2,6 +2,7 @@ import { inject, injectable, postConstruct } from '@theia/core/shared/inversify'
 import { CloudSketchbookCompositeWidget } from './cloud-sketchbook-composite-widget';
 import { SketchbookWidget } from '../sketchbook/sketchbook-widget';
 import { ArduinoPreferences } from '../../arduino-preferences';
+import { BaseSketchbookCompositeWidget } from '../sketchbook/sketchbook-composite-widget';
 
 @injectable()
 export class CloudSketchbookWidget extends SketchbookWidget {
@@ -19,8 +20,8 @@ export class CloudSketchbookWidget extends SketchbookWidget {
   override getTreeWidget(): any {
     const widget: any = this.sketchbookTreesContainer.selectedWidgets().next();
 
-    if (widget && typeof widget.getTreeWidget !== 'undefined') {
-      return (widget as CloudSketchbookCompositeWidget).getTreeWidget();
+    if (widget instanceof BaseSketchbookCompositeWidget) {
+      return widget.treeWidget;
     }
     return widget;
   }
@@ -30,7 +31,7 @@ export class CloudSketchbookWidget extends SketchbookWidget {
       this.sketchbookTreesContainer.activateWidget(this.widget);
     } else {
       this.sketchbookTreesContainer.activateWidget(
-        this.localSketchbookTreeWidget
+        this.sketchbookCompositeWidget
       );
     }
     this.setDocumentMode();
diff --git a/arduino-ide-extension/src/browser/widgets/sketchbook/create-new.tsx b/arduino-ide-extension/src/browser/widgets/sketchbook/create-new.tsx
new file mode 100644
index 000000000..d70d5b9a4
--- /dev/null
+++ b/arduino-ide-extension/src/browser/widgets/sketchbook/create-new.tsx
@@ -0,0 +1,20 @@
+import * as React from '@theia/core/shared/react';
+
+export class CreateNew extends React.Component<CreateNew.Props> {
+  override render(): React.ReactNode {
+    return (
+      <div className="create-new">
+        <button className="theia-button secondary" onClick={this.props.onClick}>
+          {this.props.label}
+        </button>
+      </div>
+    );
+  }
+}
+
+export namespace CreateNew {
+  export interface Props {
+    readonly label: string;
+    readonly onClick: () => void;
+  }
+}
diff --git a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-composite-widget.tsx b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-composite-widget.tsx
new file mode 100644
index 000000000..cdec965e6
--- /dev/null
+++ b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-composite-widget.tsx
@@ -0,0 +1,93 @@
+import * as React from '@theia/core/shared/react';
+import * as ReactDOM from '@theia/core/shared/react-dom';
+import { inject, injectable } from '@theia/core/shared/inversify';
+import { nls } from '@theia/core/lib/common/nls';
+import { Widget } from '@theia/core/shared/@phosphor/widgets';
+import { Message, MessageLoop } from '@theia/core/shared/@phosphor/messaging';
+import { Disposable } from '@theia/core/lib/common/disposable';
+import { BaseWidget } from '@theia/core/lib/browser/widgets/widget';
+import { CommandService } from '@theia/core/lib/common/command';
+import { SketchbookTreeWidget } from './sketchbook-tree-widget';
+import { CreateNew } from '../sketchbook/create-new';
+
+@injectable()
+export abstract class BaseSketchbookCompositeWidget<
+  TW extends SketchbookTreeWidget
+> extends BaseWidget {
+  @inject(CommandService)
+  protected readonly commandService: CommandService;
+
+  private readonly compositeNode: HTMLElement;
+  private readonly footerNode: HTMLElement;
+
+  constructor() {
+    super();
+    this.compositeNode = document.createElement('div');
+    this.compositeNode.classList.add('composite-node');
+    this.footerNode = document.createElement('div');
+    this.footerNode.classList.add('footer-node');
+    this.compositeNode.appendChild(this.footerNode);
+    this.node.appendChild(this.compositeNode);
+    this.title.closable = false;
+  }
+
+  abstract get treeWidget(): TW;
+  protected abstract renderFooter(footerNode: HTMLElement): void;
+  protected updateFooter(): void {
+    this.renderFooter(this.footerNode);
+  }
+
+  protected override onAfterAttach(message: Message): void {
+    super.onAfterAttach(message);
+    Widget.attach(this.treeWidget, this.compositeNode);
+    this.renderFooter(this.footerNode);
+    this.toDisposeOnDetach.push(
+      Disposable.create(() => Widget.detach(this.treeWidget))
+    );
+  }
+
+  protected override onActivateRequest(message: Message): void {
+    super.onActivateRequest(message);
+    // Sending a resize message is needed because otherwise the tree widget would render empty
+    this.onResize(Widget.ResizeMessage.UnknownSize);
+  }
+
+  protected override onResize(message: Widget.ResizeMessage): void {
+    super.onResize(message);
+    MessageLoop.sendMessage(this.treeWidget, Widget.ResizeMessage.UnknownSize);
+  }
+}
+
+@injectable()
+export class SketchbookCompositeWidget extends BaseSketchbookCompositeWidget<SketchbookTreeWidget> {
+  @inject(SketchbookTreeWidget)
+  private readonly sketchbookTreeWidget: SketchbookTreeWidget;
+
+  constructor() {
+    super();
+    this.id = 'sketchbook-composite-widget';
+    this.title.caption = nls.localize(
+      'arduino/sketch/titleLocalSketchbook',
+      'Local Sketchbook'
+    );
+    this.title.iconClass = 'sketchbook-tree-icon';
+  }
+
+  get treeWidget(): SketchbookTreeWidget {
+    return this.sketchbookTreeWidget;
+  }
+
+  protected renderFooter(footerNode: HTMLElement): void {
+    ReactDOM.render(
+      <CreateNew
+        label={nls.localize('arduino/sketchbook/newSketch', 'New Sketch')}
+        onClick={this.onDidClickCreateNew}
+      />,
+      footerNode
+    );
+  }
+
+  private onDidClickCreateNew: () => void = () => {
+    this.commandService.executeCommand('arduino-new-sketch');
+  };
+}
diff --git a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-tree-widget.tsx b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-tree-widget.tsx
index bb1a69914..599cac893 100644
--- a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-tree-widget.tsx
+++ b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-tree-widget.tsx
@@ -59,6 +59,7 @@ export class SketchbookTreeWidget extends FileTreeWidget {
       'Local Sketchbook'
     );
     this.title.closable = false;
+    this.addClass('tree-container'); // Adds `height: 100%` to the tree. Otherwise you cannot see it.
   }
 
   @postConstruct()
diff --git a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget.tsx b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget.tsx
index 0b7b920a1..eb0059590 100644
--- a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget.tsx
+++ b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget.tsx
@@ -11,15 +11,21 @@ import { Disposable } from '@theia/core/lib/common/disposable';
 import { BaseWidget } from '@theia/core/lib/browser/widgets/widget';
 import { SketchbookTreeWidget } from './sketchbook-tree-widget';
 import { nls } from '@theia/core/lib/common';
-import { CloudSketchbookCompositeWidget } from '../cloud-sketchbook/cloud-sketchbook-composite-widget';
 import { URI } from '../../contributions/contribution';
+import {
+  BaseSketchbookCompositeWidget,
+  SketchbookCompositeWidget,
+} from './sketchbook-composite-widget';
 
 @injectable()
 export class SketchbookWidget extends BaseWidget {
-  static LABEL = nls.localize('arduino/sketch/titleSketchbook', 'Sketchbook');
+  static readonly LABEL = nls.localize(
+    'arduino/sketch/titleSketchbook',
+    'Sketchbook'
+  );
 
-  @inject(SketchbookTreeWidget)
-  protected readonly localSketchbookTreeWidget: SketchbookTreeWidget;
+  @inject(SketchbookCompositeWidget)
+  protected readonly sketchbookCompositeWidget: SketchbookCompositeWidget;
 
   protected readonly sketchbookTreesContainer: DockPanel;
 
@@ -36,7 +42,7 @@ export class SketchbookWidget extends BaseWidget {
 
   @postConstruct()
   protected init(): void {
-    this.sketchbookTreesContainer.addWidget(this.localSketchbookTreeWidget);
+    this.sketchbookTreesContainer.addWidget(this.sketchbookCompositeWidget);
   }
 
   protected override onAfterAttach(message: Message): void {
@@ -48,7 +54,7 @@ export class SketchbookWidget extends BaseWidget {
   }
 
   getTreeWidget(): SketchbookTreeWidget {
-    return this.localSketchbookTreeWidget;
+    return this.sketchbookCompositeWidget.treeWidget;
   }
 
   activeTreeWidgetId(): string | undefined {
@@ -80,8 +86,8 @@ export class SketchbookWidget extends BaseWidget {
       if (widget instanceof SketchbookTreeWidget) {
         return widget;
       }
-      if (widget instanceof CloudSketchbookCompositeWidget) {
-        return widget.getTreeWidget();
+      if (widget instanceof BaseSketchbookCompositeWidget) {
+        return widget.treeWidget;
       }
       return undefined;
     };
diff --git a/arduino-ide-extension/src/electron-browser/theia/core/electron-main-menu-factory.ts b/arduino-ide-extension/src/electron-browser/theia/core/electron-main-menu-factory.ts
index 98f8b76e0..842518062 100644
--- a/arduino-ide-extension/src/electron-browser/theia/core/electron-main-menu-factory.ts
+++ b/arduino-ide-extension/src/electron-browser/theia/core/electron-main-menu-factory.ts
@@ -2,8 +2,10 @@ import { inject, injectable } from '@theia/core/shared/inversify';
 import * as remote from '@theia/core/electron-shared/@electron/remote';
 import { isOSX } from '@theia/core/lib/common/os';
 import {
+  ActionMenuNode,
   CompositeMenuNode,
   MAIN_MENU_BAR,
+  MenuNode,
   MenuPath,
 } from '@theia/core/lib/common/menu';
 import {
@@ -134,7 +136,7 @@ export class ElectronMainMenuFactory extends TheiaElectronMainMenuFactory {
   }
 
   protected override handleElectronDefault(
-    menuNode: CompositeMenuNode,
+    menuNode: MenuNode,
     args: any[] = [],
     options?: ElectronMenuOptions
   ): Electron.MenuItemConstructorOptions[] {
@@ -149,4 +151,119 @@ export class ElectronMainMenuFactory extends TheiaElectronMainMenuFactory {
     }
     return [];
   }
+
+  // Copied from 1.25.0 Theia as is to customize the enablement of the menu items.
+  // Source: https://github.com/eclipse-theia/theia/blob/ca417a31e402bd35717d3314bf6254049d1dae44/packages/core/src/electron-browser/menu/electron-main-menu-factory.ts#L125-L220
+  // See https://github.com/arduino/arduino-ide/issues/1533
+  protected override fillMenuTemplate(
+    items: Electron.MenuItemConstructorOptions[],
+    menuModel: CompositeMenuNode,
+    args: any[] = [],
+    options?: ElectronMenuOptions
+  ): Electron.MenuItemConstructorOptions[] {
+    const showDisabled =
+      options?.showDisabled === undefined ? true : options?.showDisabled;
+    for (const menu of menuModel.children) {
+      if (menu instanceof CompositeMenuNode) {
+        if (menu.children.length > 0) {
+          // do not render empty nodes
+
+          if (menu.isSubmenu) {
+            // submenu node
+
+            const submenu = this.fillMenuTemplate([], menu, args, options);
+            if (submenu.length === 0) {
+              continue;
+            }
+
+            items.push({
+              label: menu.label,
+              submenu,
+            });
+          } else {
+            // group node
+
+            // process children
+            const submenu = this.fillMenuTemplate([], menu, args, options);
+            if (submenu.length === 0) {
+              continue;
+            }
+
+            if (items.length > 0) {
+              // do not put a separator above the first group
+
+              items.push({
+                type: 'separator',
+              });
+            }
+
+            // render children
+            items.push(...submenu);
+          }
+        }
+      } else if (menu instanceof ActionMenuNode) {
+        const node =
+          menu.altNode && this.context.altPressed ? menu.altNode : menu;
+        const commandId = node.action.commandId;
+
+        // That is only a sanity check at application startup.
+        if (!this.commandRegistry.getCommand(commandId)) {
+          console.debug(
+            `Skipping menu item with missing command: "${commandId}".`
+          );
+          continue;
+        }
+
+        if (
+          !this.commandRegistry.isVisible(commandId, ...args) ||
+          (!!node.action.when &&
+            !this.contextKeyService.match(node.action.when))
+        ) {
+          continue;
+        }
+
+        // We should omit rendering context-menu items which are disabled.
+        if (
+          !showDisabled &&
+          !this.commandRegistry.isEnabled(commandId, ...args)
+        ) {
+          continue;
+        }
+
+        const bindings =
+          this.keybindingRegistry.getKeybindingsForCommand(commandId);
+
+        const accelerator = bindings[0] && this.acceleratorFor(bindings[0]);
+
+        const menuItem: Electron.MenuItemConstructorOptions = {
+          id: node.id,
+          label: node.label,
+          type: this.commandRegistry.getToggledHandler(commandId, ...args)
+            ? 'checkbox'
+            : 'normal',
+          checked: this.commandRegistry.isToggled(commandId, ...args),
+          enabled: this.commandRegistry.isEnabled(commandId, ...args), // Unlike Theia https://github.com/eclipse-theia/theia/blob/ca417a31e402bd35717d3314bf6254049d1dae44/packages/core/src/electron-browser/menu/electron-main-menu-factory.ts#L197
+          visible: true,
+          accelerator,
+          click: () => this.execute(commandId, args),
+        };
+
+        if (isOSX) {
+          const role = this.roleFor(node.id);
+          if (role) {
+            menuItem.role = role;
+            delete menuItem.click;
+          }
+        }
+        items.push(menuItem);
+
+        if (this.commandRegistry.getToggledHandler(commandId, ...args)) {
+          this._toggledCommands.add(commandId);
+        }
+      } else {
+        items.push(...this.handleElectronDefault(menu, args, options));
+      }
+    }
+    return items;
+  }
 }
diff --git a/i18n/en.json b/i18n/en.json
index 3f64fd926..418a5ae80 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -119,6 +119,9 @@
       "syncEditSketches": "Sync and edit your Arduino Cloud Sketches",
       "visitArduinoCloud": "Visit Arduino Cloud to create Cloud Sketches."
     },
+    "cloudSketch": {
+      "new": "New Remote Sketch"
+    },
     "common": {
       "all": "All",
       "contributed": "Contributed",
@@ -299,6 +302,12 @@
       "unableToCloseWebSocket": "Unable to close websocket",
       "unableToConnectToWebSocket": "Unable to connect to websocket"
     },
+    "newCloudSketch": {
+      "invalidSketchName": "The name must consist of basic letters, numbers, or underscores. The maximum length is 36 characters.",
+      "newSketchTitle": "Name of a new Remote Sketch",
+      "notFound": "Could not pull the remote sketch '{0}'. It does not exist.",
+      "sketchAlreadyExists": "Remote sketch '{0}' already exists."
+    },
     "portProtocol": {
       "network": "Network",
       "serial": "Serial"
@@ -388,7 +397,7 @@
       "exportBinary": "Export Compiled Binary",
       "moving": "Moving",
       "movingMsg": "The file \"{0}\" needs to be inside a sketch folder named \"{1}\".\nCreate this folder, move the file, and continue?",
-      "new": "New",
+      "new": "New Sketch",
       "openFolder": "Open Folder",
       "openRecent": "Open Recent",
       "openSketchInNewWindow": "Open Sketch in New Window",
@@ -407,6 +416,10 @@
       "verify": "Verify",
       "verifyOrCompile": "Verify/Compile"
     },
+    "sketchbook": {
+      "newRemoteSketch": "New Remote Sketch",
+      "newSketch": "New Sketch"
+    },
     "survey": {
       "answerSurvey": "Answer survey",
       "dismissSurvey": "Don't show again",