diff --git a/deadlock-plugins/deadlock-extension/package.json b/deadlock-plugins/deadlock-extension/package.json
index 69aa8ecd31ee4a426c3aee800ade330a3baf4327..dce35c0d30feaa32b3c55174d0ee5a748939c0dc 100644
--- a/deadlock-plugins/deadlock-extension/package.json
+++ b/deadlock-plugins/deadlock-extension/package.json
@@ -64,7 +64,7 @@
         {
           "id": "help",
           "name": "Help",
-          "visibility": "collapsed"
+          "visibility": "visible"
         }
       ]
     },
diff --git a/deadlock-plugins/deadlock-extension/src/config.prod.ts b/deadlock-plugins/deadlock-extension/src/config.prod.ts
index 46ee6889446bcf153f9619125c3ab2bd4d753d65..40beee92f6ff88f45ecca11fd9946b6da96571cf 100644
--- a/deadlock-plugins/deadlock-extension/src/config.prod.ts
+++ b/deadlock-plugins/deadlock-extension/src/config.prod.ts
@@ -2,4 +2,4 @@ export const KEYCLOAK_DEVICE_AUTH_URL =
   'https://auth.deadlock.io/auth/realms/Deadlock/protocol/openid-connect/auth/device';
 export const KEYCLOAK_TOKEN_CREATE_URL = 'https://auth.deadlock.io/auth/realms/Deadlock/protocol/openid-connect/token';
 export const KEYCLOAK_USER_INFO_URL = 'https://auth.deadlock.io/auth/realms/Deadlock/protocol/openid-connect/userinfo';
-export const REJECT_UNAUTHORIZED = true;
+export const REGISTRY_MISSION_URL = 'registry.e-biz.fr/deadlock/deadlock-challenges';
diff --git a/deadlock-plugins/deadlock-extension/src/config.staging.ts b/deadlock-plugins/deadlock-extension/src/config.staging.ts
index e8ddb5e90e01601adc2b4f79ee07d241551c535b..5030cdd73e8e942bf5f0ebe0906c96b3088feeac 100644
--- a/deadlock-plugins/deadlock-extension/src/config.staging.ts
+++ b/deadlock-plugins/deadlock-extension/src/config.staging.ts
@@ -4,4 +4,4 @@ export const KEYCLOAK_TOKEN_CREATE_URL =
   'https://auth.staging.deadlock.io/auth/realms/Deadlock/protocol/openid-connect/token';
 export const KEYCLOAK_USER_INFO_URL =
   'https://auth.staging.deadlock.io/auth/realms/Deadlock/protocol/openid-connect/userinfo';
-export const REJECT_UNAUTHORIZED = true;
+export const REGISTRY_MISSION_URL = 'registry.e-biz.fr/deadlock/deadlock-challenges';
diff --git a/deadlock-plugins/deadlock-extension/src/config.ts b/deadlock-plugins/deadlock-extension/src/config.ts
index a53b3ab5bba69c5e9d7ed0ef82f7662a8227933f..eb332e792712a5598b88bdab2e38ec43ab137f5a 100644
--- a/deadlock-plugins/deadlock-extension/src/config.ts
+++ b/deadlock-plugins/deadlock-extension/src/config.ts
@@ -4,4 +4,4 @@ export const KEYCLOAK_TOKEN_CREATE_URL =
   'https://auth.dev.deadlock.io/auth/realms/Deadlock/protocol/openid-connect/token';
 export const KEYCLOAK_USER_INFO_URL =
   'https://auth.dev.deadlock.io/auth/realms/Deadlock/protocol/openid-connect/userinfo';
-export const REJECT_UNAUTHORIZED = false;
+export const REGISTRY_MISSION_URL = 'registry.e-biz.fr/deadlock/deadlock-challenges';
diff --git a/deadlock-plugins/deadlock-extension/src/core/controller.ts b/deadlock-plugins/deadlock-extension/src/core/controller.ts
index 7d7d3bb15fec7d1d56978bac11aa52d28b86716f..bb205d1317bdb47f244737f34ddccc2ec93ffc81 100644
--- a/deadlock-plugins/deadlock-extension/src/core/controller.ts
+++ b/deadlock-plugins/deadlock-extension/src/core/controller.ts
@@ -1,11 +1,18 @@
 import * as vscode from 'vscode';
-import { KEYCLOAK_DEVICE_AUTH_URL, KEYCLOAK_TOKEN_CREATE_URL, KEYCLOAK_USER_INFO_URL } from '../config';
-import { OPEN_QUICK_SETUP_COMMAND } from '../theia/command';
+import {
+  KEYCLOAK_DEVICE_AUTH_URL,
+  KEYCLOAK_TOKEN_CREATE_URL,
+  KEYCLOAK_USER_INFO_URL,
+  REGISTRY_MISSION_URL,
+} from '../config';
+import { log } from '../recorder/utils';
+import { OPEN_GETTING_STARTED_COMMAND } from '../theia/command';
 import BriefingView from '../view/briefingView';
 import QuickSetupView from '../view/quickSetupView';
 import { CHOOSE_MISSION_WORKDIR_COMMAND, CommandHandler, OPEN_URL_IN_BROWSER_COMMAND } from './commandHandler';
 import ExtensionStore from './extensionStore';
 import KeycloakOAuth2DeviceFlowConnection from './keycloakOAuth2DeviceFlowConnection';
+import Mission from './mission';
 
 export default class Controller {
   public connection: KeycloakOAuth2DeviceFlowConnection;
@@ -33,10 +40,11 @@ export default class Controller {
       handleUri(uri: vscode.Uri) {
         const queryParams: URLSearchParams = new URLSearchParams(uri.query);
         const action: string | null = queryParams.get('action');
+        log('Opening link', uri);
 
         switch (action) {
           case 'open-challenge':
-            that.launchMission(queryParams.get('missionId'));
+            that.launchMission(queryParams.get('missionId'), queryParams.get('missionVersion'));
             break;
 
           default:
@@ -86,8 +94,8 @@ export default class Controller {
     vscode.commands.executeCommand(OPEN_URL_IN_BROWSER_COMMAND.cmd, vscode.Uri.parse(url));
   }
 
-  public async launchMission(missionId: string | null) {
-    if (missionId) {
+  public async launchMission(missionId: string | null, missionVersion: string | null) {
+    if (missionId && missionVersion) {
       vscode.window.showInformationMessage(`vous lancez la mission ${missionId}`);
       const hadMissionWorkdir = this.extensionStore.getMissionWorkdir() !== undefined;
       if (!hadMissionWorkdir) {
@@ -97,13 +105,25 @@ export default class Controller {
       const hadBeenConnected = (await this.extensionStore.getAccessToken()) !== undefined;
 
       if (!hadBeenConnected) {
-        this.authenticate();
+        await this.authenticate();
         vscode.window.showInformationMessage('Nouvelle connexion validée');
       } else {
         vscode.window.showInformationMessage('Déjà connecté: session récupérée');
       }
 
-      vscode.commands.executeCommand(OPEN_QUICK_SETUP_COMMAND.cmd);
+      // TODO Should I fetch GET api/missions/{missionId} one day instead of passing necessary parameters in vscode xdg-open link ?
+      const mission = new Mission({
+        registryBaseURL: REGISTRY_MISSION_URL,
+        missionId: missionId,
+        missionVersion: missionVersion,
+      });
+      vscode.window.showInformationMessage(
+        'opening inside folder ' + this.extensionStore.getMissionWorkdir()! + '/' + missionId,
+      );
+      await mission.setup({});
+      await mission.openEditorInFolder();
+
+      vscode.commands.executeCommand(OPEN_GETTING_STARTED_COMMAND.cmd);
     }
   }
 }
diff --git a/deadlock-plugins/deadlock-extension/src/core/mission.ts b/deadlock-plugins/deadlock-extension/src/core/mission.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a684dbbcfa5f5f80b8050703182a7666c4eecdb9
--- /dev/null
+++ b/deadlock-plugins/deadlock-extension/src/core/mission.ts
@@ -0,0 +1,135 @@
+import { exec as _exec } from 'child_process';
+import * as fs from 'fs';
+import * as util from 'util';
+import * as vscode from 'vscode';
+import { error as err, log } from '../recorder/utils';
+import ExtensionStore from './extensionStore';
+
+/**
+ * {@link https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback}
+ */
+const exec = util.promisify(_exec);
+
+export default class Mission {
+  private readonly hostBaseWorkDir: string;
+  private readonly dockerImageURL: string;
+  private readonly hostMissionDir: string;
+  private readonly hostMissionDevcontainerDir: string;
+  private readonly hostMissionDevcontainerFileDir: string;
+  private readonly hostMissionMountDir: string;
+  private readonly remoteUserHomeDir: string;
+  private readonly remoteMissionDir: any;
+  private readonly remoteGiteaWorkDir: string;
+  constructor(private params: { registryBaseURL: string; missionId: string; missionVersion: string }) {
+    const { registryBaseURL, missionId, missionVersion } = params;
+    this.hostBaseWorkDir = ExtensionStore.getInstance().getMissionWorkdir() ?? '';
+    this.hostMissionDir = `${this.hostBaseWorkDir}/${missionId}`;
+    this.hostMissionDevcontainerDir = `${this.hostMissionDir}/.devcontainer`;
+    this.hostMissionDevcontainerFileDir = `${this.hostMissionDevcontainerDir}/devcontainer.json`;
+    this.hostMissionMountDir = `${this.hostMissionDir}/mounted`;
+    this.dockerImageURL = getDockerImageURL(registryBaseURL, missionId, missionVersion);
+    this.remoteUserHomeDir = '/home/deadlock';
+    this.remoteMissionDir = `${this.remoteUserHomeDir}/mission`;
+    this.remoteGiteaWorkDir = `/project`;
+  }
+
+  static async pullImage(url) {
+    const { stdout, stderr } = await exec(`docker pull ${url}`);
+    log(stdout);
+    err(stderr);
+  }
+
+  public async setup(options?: Partial<DockerfileSpecific & Base & VSCodespecific & LifecycleScripts>) {
+    await fs.promises.mkdir(this.hostMissionDevcontainerDir, { recursive: true });
+    await fs.promises.mkdir(this.hostMissionMountDir, { recursive: true });
+    await fs.promises.writeFile(
+      this.hostMissionDevcontainerFileDir,
+      (() => {
+        const devcontainer: Partial<DockerfileSpecific & Base & VSCodespecific & LifecycleScripts> = {
+          name: `deadlock-${this.params.missionId}`,
+          image: this.dockerImageURL,
+          extensions: ['Deadlock.deadlock-coding'],
+          remoteUser: 'deadlock',
+          // mounts: [
+          //   `source=${this.hostMissionDir}/workspace,target=${'/workspace'},type=${'volume'},consistency=${'cached'}`,
+          // ],
+          userEnvProbe: 'interactiveShell',
+          settings: {
+            'terminal.integrated.defaultProfile.linux': 'bash',
+            'terminal.integrated.profiles.linux': {
+              bash: {
+                path: '/bin/bash',
+              },
+            },
+          },
+          overrideCommand: false,
+          shutdownAction: 'stopContainer',
+          workspaceMount: `source=${this.hostMissionMountDir},target=${this.remoteMissionDir},type=bind`,
+          workspaceFolder: `${this.remoteMissionDir}`,
+          onCreateCommand: `cp -R ${this.remoteGiteaWorkDir} ${this.remoteMissionDir}`,
+          ...options,
+        };
+        return JSON.stringify(devcontainer, null, 2);
+      })(),
+    );
+  }
+
+  public async openEditorInFolder(arbitraryPath?: string) {
+    if (arbitraryPath) {
+      return vscode.commands.executeCommand('remote-containers.openFolder', vscode.Uri.file(arbitraryPath));
+    }
+    if (!fs.existsSync(this.hostMissionDir)) {
+      log('WARN missing path ', this.hostMissionDir);
+      await fs.promises.mkdir(this.hostMissionDir, { recursive: true });
+    }
+    await vscode.commands.executeCommand('remote-containers.openFolder', vscode.Uri.file(this.hostMissionDir));
+  }
+}
+
+export function getDockerImageURL(base, missionId, missionVersion) {
+  return `${base}/${missionId}:${missionVersion}`;
+}
+interface DockerfileSpecific {
+  image?;
+  dockerFile?;
+  context?;
+  'build.args'?;
+  'build.target'?;
+  'build.cacheFrom'?;
+  containerEnv?;
+  containerUser?;
+  mounts?;
+  workspaceMount?;
+  workspaceFolder?;
+  runArgs?;
+}
+
+interface Base {
+  name?;
+  forwardPorts?;
+  portsAttributes?;
+  otherPortsAttributes?;
+  remoteEnv?;
+  remoteUser?;
+  updateRemoteUserUID?;
+  userEnvProbe?;
+  overrideCommand?;
+  features?;
+  shutdownAction?;
+}
+
+interface VSCodespecific {
+  extensions?;
+  settings?;
+  devPort?;
+}
+
+interface LifecycleScripts {
+  initializeCommand?;
+  onCreateCommand?;
+  updateContentCommand?;
+  postCreateCommand?;
+  postStartCommand?;
+  postAttachCommand?;
+  waitFor?;
+}
diff --git a/deadlock-plugins/deadlock-extension/src/view/webviewBase.ts b/deadlock-plugins/deadlock-extension/src/view/webviewBase.ts
index 1639cb5634d43b3209661865ad8e2bb0a3dac4ee..df113cdf39c27f3fd6408f2668706fe7f1b4869d 100644
--- a/deadlock-plugins/deadlock-extension/src/view/webviewBase.ts
+++ b/deadlock-plugins/deadlock-extension/src/view/webviewBase.ts
@@ -90,17 +90,12 @@ export abstract class WebviewBase implements Disposable {
 
   async show(column: ViewColumn = ViewColumn.Beside): Promise<void> {
     if (this.panel == null) {
-      this.panel = window.createWebviewPanel(
-        this.id,
-        this.title,
-        { viewColumn: column, preserveFocus: false },
-        {
-          retainContextWhenHidden: true,
-          enableFindWidget: true,
-          enableCommandUris: true,
-          enableScripts: true,
-        },
-      );
+      this.panel = window.createWebviewPanel(this.id, this.title, ViewColumn.Active, {
+        retainContextWhenHidden: true,
+        enableFindWidget: true,
+        enableCommandUris: true,
+        enableScripts: true,
+      });
 
       this.disposablePanel = Disposable.from(
         this.panel,