diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000000000000000000000000000000000000..03d9549ea8e4ada36fb3ecbc30fef08175b7d728
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,6 @@
+<component name="InspectionProjectProfileManager">
+  <profile version="1.0">
+    <option name="myName" value="Project Default" />
+    <inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
+  </profile>
+</component>
\ No newline at end of file
diff --git a/NodeApp/.env.vault b/NodeApp/.env.vault
index dfdcf927c6197bf63486a9fb84b97e47db10945c..1b27b44793a575e76c83badf684b00dae574c548 100644
--- a/NodeApp/.env.vault
+++ b/NodeApp/.env.vault
@@ -1,6 +1,6 @@
 #/-------------------.env.vault---------------------/
 #/         cloud-agnostic vaulting standard         /
-#/   [how it works](https://dotenvx.com/env-vault)  /
+#/   [how it works](https://dotenv.org/env-vault)   /
 #/--------------------------------------------------/
 
 # development
diff --git a/NodeApp/.idea/vcs.xml b/NodeApp/.idea/vcs.xml
index 5e5bcd02ce8b098302940ffa22bb6d19b8d8986f..d86e73b516141a07b5ba1f16f6f315749512bedc 100644
--- a/NodeApp/.idea/vcs.xml
+++ b/NodeApp/.idea/vcs.xml
@@ -2,7 +2,6 @@
 <project version="4">
   <component name="VcsDirectoryMappings">
     <mapping directory="$PROJECT_DIR$/.." vcs="Git" />
-    <mapping directory="$PROJECT_DIR$/DojoExercise_Technique_de compilation - TP" vcs="Git" />
     <mapping directory="$PROJECT_DIR$/src/shared" vcs="Git" />
     <mapping directory="$PROJECT_DIR$/src/sharedByClients" vcs="Git" />
   </component>
diff --git a/NodeApp/src/commander/exercise/ExerciseCommand.ts b/NodeApp/src/commander/exercise/ExerciseCommand.ts
index 02e40e36a7bd369b056c2cf5a8303e796d8af5f5..7d80e5f9894757332588ed31b84b9cdf5bd75553 100644
--- a/NodeApp/src/commander/exercise/ExerciseCommand.ts
+++ b/NodeApp/src/commander/exercise/ExerciseCommand.ts
@@ -3,6 +3,7 @@ import ExerciseCreateCommand     from './subcommands/ExerciseCreateCommand.js';
 import ExerciseRunCommand        from './subcommands/ExerciseRunCommand.js';
 import ExerciseCorrectionCommand from './subcommands/ExerciseCorrectionCommand.js';
 import ExerciseDeleteCommand     from './subcommands/ExerciseDeleteCommand';
+import ExerciseListCommand from "./subcommands/ExerciseListCommand";
 
 
 class ExerciseCommand extends CommanderCommand {
@@ -18,6 +19,7 @@ class ExerciseCommand extends CommanderCommand {
         ExerciseRunCommand.registerOnCommand(this.command);
         ExerciseDeleteCommand.registerOnCommand(this.command);
         ExerciseCorrectionCommand.registerOnCommand(this.command);
+        ExerciseListCommand.registerOnCommand(this.command);
     }
 
     protected async commandAction(): Promise<void> {
diff --git a/NodeApp/src/commander/exercise/subcommands/ExerciseListCommand.ts b/NodeApp/src/commander/exercise/subcommands/ExerciseListCommand.ts
new file mode 100644
index 0000000000000000000000000000000000000000..14ec7d36e75fde800708092f469a6b5578fa36c4
--- /dev/null
+++ b/NodeApp/src/commander/exercise/subcommands/ExerciseListCommand.ts
@@ -0,0 +1,235 @@
+// ExerciseListCommand.ts
+import CommanderCommand from '../../CommanderCommand';
+import chalk from 'chalk';
+import ora from 'ora';
+import DojoBackendManager from '../../../managers/DojoBackendManager';
+import AccessesHelper from '../../../helpers/AccessesHelper';
+import Exercise from '../../../sharedByClients/models/Exercise';
+import inquirer from 'inquirer';
+import Table from 'cli-table3';
+
+import Fuse from 'fuse.js';
+import User from '../../../sharedByClients/models/User';
+
+class ExerciseListCommand extends CommanderCommand {
+    protected commandName: string = 'list';
+
+    protected defineCommand(): void {
+        this.command
+            .description('list your exercises')
+            .action(this.commandAction.bind(this));
+    }
+
+    protected async commandAction(): Promise<void> {
+        console.log(chalk.cyan('Please wait while we retrieve your exercises...'));
+
+        // Check access
+        if (!await AccessesHelper.checkStudent()) {
+            return;
+        }
+
+        // Fetch user's exercises
+        const userExercises: Exercise[] | undefined = await DojoBackendManager.getUserExercises();
+
+        if (!userExercises || userExercises.length === 0) {
+            ora().info('You have no exercises yet.');
+            return;
+        }
+
+        // Display the list of exercises
+        this.displayExerciseList(userExercises);
+
+        // Ask the user for further actions
+        await this.askUserForActions(userExercises);
+    }
+
+    private async askUserForActions(exercises: Exercise[]): Promise<void> {
+        const { action } = await inquirer.prompt([
+            {
+                type: 'list',
+                name: 'action',
+                message: 'Que souhaitez-vous faire ?',
+                choices: [
+                    { name: 'Voir les détails d\'exercice', value: 'details'},
+                    { name: 'Filter les exercises', value: 'filter' },
+                    { name: 'Exit', value: 'exit' },
+                ],
+            },
+        ]);
+
+        if (action === 'details') {
+            await this.selectExerciseForDetails(exercises);
+        } else if (action === 'filter') {
+            await this.filterExercises(exercises);
+        } else {
+            ora().info('No further actions selected.');
+        }
+    }
+
+    private async selectExerciseForDetails(exercises: Exercise[]): Promise<void> {
+        const { selectedExercise } = await inquirer.prompt([{
+            type: 'list',
+            name: 'selectedExercise',
+            message: 'Selectionner un exercice :',
+            choices: [
+                ...exercises.map(exercise => ({
+                    name: exercise.name,
+                    value: exercise.id,
+                })),
+                { name: 'Exit', value: 'exit' },
+            ],
+        }]);
+
+        if (selectedExercise === 'exit') {
+            ora().info('Pas de détails requis: détails dispo  avec la commande `dojo exercise info <id>`.');
+            return;
+        }
+
+        const selected = exercises.find(ex => ex.id === selectedExercise);
+        if (selected) {
+            await this.displayExerciseDetails(selected);
+        } else {
+            ora().info('Invalid selection. No exercise details to show.');
+        }
+    }
+
+    private async filterExercises(exercises: Exercise[]): Promise<void> {
+        const { filterType } = await inquirer.prompt([
+            {
+                type: 'list',
+                name: 'filterType',
+                message: 'Comment souhaitez-vous filtrer les exercices ?',
+                choices: [
+                    { name: 'Par saisie texte', value: 'fuzzy' },
+                    { name: 'Par professeurs', value: 'professor' },
+                    { name: 'Exit', value: 'exit' },
+                ],
+            },
+        ]);
+
+        if (filterType === 'fuzzy') {
+            await this.fuzzySearchExercises(exercises);
+        } else if (filterType === 'professor') {
+            await this.filterByProfessor(exercises);
+        } else {
+            ora().info('No filtering selected.');
+        }
+    }
+
+    private async fuzzySearchExercises(exercises: Exercise[]): Promise<void> {
+        const { searchQuery } = await inquirer.prompt([
+            {
+                type: 'input',
+                name: 'searchQuery',
+                message: 'Entrez le nom de l\'exercice (laisser vide pour la liste complète) :',
+            },
+        ]);
+
+        if (!searchQuery) {
+            this.displayExerciseList(exercises);
+            return;
+        }
+
+        const fuse = new Fuse(exercises, {
+            keys: ['name'],
+            threshold: 0.5,
+            distance: 150,
+        });
+
+        const searchResults = fuse.search(searchQuery).map(result => result.item);
+
+        if (searchResults.length === 0) {
+            ora().info('Aucun exercice trouvé correspondant à votre recherche.');
+            return;
+        }
+
+        if (searchResults.length === 1) {
+            // Display details and members for the single matching exercise
+            const singleExercise = searchResults[0];
+            this.displayExerciseDetails(singleExercise);
+        } else {
+            // Display only exercise names and info about viewing details
+            ora().info(' Plusieurs exercices trouvés correspondant à votre recherche :');
+            const exerciseNames = searchResults.map(exercise => exercise.name);
+            console.log('  ', exerciseNames.join('\n   '));
+
+            ora().info('Les détails sont disponibles avec la commande : `dojo exercise info <id>`.');
+        }
+    }
+
+    private async filterByProfessor(exercises: Exercise[]): Promise<void> {
+
+        const professors: User[] | undefined = await DojoBackendManager.getProfessors();
+
+        if (!professors || professors.length === 0) {
+            ora().info('No professors found.');
+            return;
+        }
+
+        const professorChoices = professors.map(professor => ({
+            name: `${professor.gitlabUsername}`,
+            value: professor // Use the professor object as the value
+        }));
+
+        const { selectedProfessor } = await inquirer.prompt([
+            {
+                type: 'list',
+                name: 'selectedProfessor',
+                message: 'Selectionnez un professeur:',
+                choices: professorChoices
+            }
+        ]);
+
+        console.log(`Selected professor: ${selectedProfessor.gitlabUsername}`);
+        ora().info('Filter by professor is not yet implemented.');
+    }
+
+    private displayExerciseList(exercises: Exercise[]): void {
+        const headers = ['Exercise Name', 'GitLab Link'];
+
+        // Calculate the maximum width for each column
+        const maxWidths = headers.map(header => header.length);
+
+        exercises.forEach(exercise => {
+            maxWidths[0] = Math.max(maxWidths[0], exercise.name.length);
+            maxWidths[1] = Math.max(maxWidths[1], exercise.gitlabLink.length);
+        });
+
+        const table = new Table({
+            head: headers,
+        });
+
+        exercises.forEach((exercise) => {
+            table.push([
+                exercise.name,
+                exercise.gitlabLink,
+            ]);
+        });
+
+        ora().info('Your exercises:');
+        console.log(table.toString());
+    }
+
+    private async displayExerciseDetails(exercise: Exercise): Promise<void> {
+        ora().info(`Detail of Exercise with ID: ${exercise.id}`);
+        console.log(chalk.magenta('  - Exercise Name:'), exercise.name);
+        console.log(chalk.magenta('  - Assignment Name:'), exercise.assignmentName);
+        console.log(chalk.magenta('  - GitLab ID:'), exercise.gitlabId);
+        console.log(chalk.magenta('  - GitLab Link:'), chalk.blue.underline(exercise.gitlabLink));
+        console.log(chalk.magenta('  - GitLab Last Info Date:'), exercise.gitlabLastInfoDate);
+
+        // Fetch exercise members
+        const exerciseMembers = await DojoBackendManager.getExerciseMembers(exercise.id);
+
+        if (exerciseMembers && exerciseMembers.length > 0) {
+            ora().info('Exercise Members:');
+            exerciseMembers.forEach(member => {
+                console.log(chalk.magenta(`  - ${member.id} ${member.name}`));
+            });
+        } else {
+            ora().info('No members found for this exercise.');
+        }
+    }
+}
+
+export default new ExerciseListCommand();
\ No newline at end of file
diff --git a/NodeApp/src/managers/DojoBackendManager.ts b/NodeApp/src/managers/DojoBackendManager.ts
index 50c2c0e01201345dd26e8f7d5375e24b20d0c881..3d7d094cc3b649a848a900f70834708ac7d98f77 100644
--- a/NodeApp/src/managers/DojoBackendManager.ts
+++ b/NodeApp/src/managers/DojoBackendManager.ts
@@ -554,6 +554,17 @@ class DojoBackendManager {
     public async getTeachers(): Promise<Array<User> | undefined> {
         return this.getUsers('teacher');
     }
+
+    public async getExerciseDetail(exerciseId: string): Promise<Exercise | undefined> {
+        try {
+
+            const response = await axios.get<Exercise>(DojoBackendHelper.getApiUrl(ApiRoute.EXERCISE_DETAIL).replace('{{exerciseId}}', String(exerciseId)));
+            return response.data;
+        } catch ( error ) {
+            console.error('Error fetching exercise details:', error);
+            return undefined;
+        }
+    }
 }