diff --git a/PluginsAndFeatures/azure-toolkit-for-intellij/.idea/gradle.xml b/PluginsAndFeatures/azure-toolkit-for-intellij/.idea/gradle.xml
index 6cb7b0faf15..5703eba69cb 100644
--- a/PluginsAndFeatures/azure-toolkit-for-intellij/.idea/gradle.xml
+++ b/PluginsAndFeatures/azure-toolkit-for-intellij/.idea/gradle.xml
@@ -14,6 +14,7 @@
+
@@ -30,6 +31,7 @@
+
diff --git a/PluginsAndFeatures/azure-toolkit-for-intellij/azure-intellij-plugin-azd/build.gradle.kts b/PluginsAndFeatures/azure-toolkit-for-intellij/azure-intellij-plugin-azd/build.gradle.kts
new file mode 100644
index 00000000000..68b62489073
--- /dev/null
+++ b/PluginsAndFeatures/azure-toolkit-for-intellij/azure-intellij-plugin-azd/build.gradle.kts
@@ -0,0 +1,5 @@
+dependencies {
+ intellijPlatform {
+ bundledPlugin("org.jetbrains.plugins.terminal")
+ }
+}
diff --git a/PluginsAndFeatures/azure-toolkit-for-intellij/azure-intellij-plugin-azd/src/main/java/com/microsoft/azure/toolkit/intellij/azd/actions/AzdCommandAction.java b/PluginsAndFeatures/azure-toolkit-for-intellij/azure-intellij-plugin-azd/src/main/java/com/microsoft/azure/toolkit/intellij/azd/actions/AzdCommandAction.java
new file mode 100644
index 00000000000..2e470fddc44
--- /dev/null
+++ b/PluginsAndFeatures/azure-toolkit-for-intellij/azure-intellij-plugin-azd/src/main/java/com/microsoft/azure/toolkit/intellij/azd/actions/AzdCommandAction.java
@@ -0,0 +1,77 @@
+package com.microsoft.azure.toolkit.intellij.azd.actions;
+
+import com.intellij.openapi.actionSystem.ActionUpdateThread;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.CommonDataKeys;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.terminal.ui.TerminalWidget;
+import com.microsoft.azure.toolkit.intellij.azd.utils.AzdCliUtils;
+import com.microsoft.azure.toolkit.intellij.azd.utils.TerminalUtils;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Set;
+
+public abstract class AzdCommandAction extends AnAction {
+
+ @Override
+ public void actionPerformed(@NotNull AnActionEvent event) {
+ final Project project = event.getProject();
+ if (project == null) return;
+
+ final VirtualFile file = event.getData(CommonDataKeys.VIRTUAL_FILE);
+ if (file == null) return;
+
+ final String directory = file.getParent() != null ? file.getParent().getPath() : null;
+ if (directory == null) return;
+
+ final String command = event.getPresentation().getDescription();
+ if (command == null || command.isEmpty()) return;
+
+ // Create terminal tab under the `directory`
+ final TerminalWidget terminal = TerminalUtils.createTerminalWidget(project, directory, command);
+ if (AzdCliUtils.azdCliInstallAttempted) {
+ AzdCliUtils.setupAzdEnvs(terminal);
+ }
+
+ // Check if azd installed, if not, prompt to install
+ if (!AzdCliUtils.checkAzdCliInstalled(terminal)) {
+ final int result = Messages.showYesNoDialog(
+ project,
+ "Azure Developer CLI is not installed. Would you like to install it?",
+ "Install Azure Developer CLI",
+ "Install",
+ "Later",
+ Messages.getQuestionIcon()
+ );
+ if (result == Messages.YES) {
+ AzdCliUtils.installAzdCli(terminal);
+ } else {
+ return;
+ }
+ }
+
+ terminal.sendCommandToExecute(AzdCliUtils.getAzdInvocation(command));
+ }
+
+ @Override
+ public void update(@NotNull AnActionEvent event) {
+ final VirtualFile file = event.getData(CommonDataKeys.VIRTUAL_FILE);
+ // Only enable the action for specific files
+ final boolean enabled = file != null && getSupportedFiles().contains(file.getName());
+ event.getPresentation().setEnabledAndVisible(enabled);
+ }
+
+ public abstract Set getSupportedFiles();
+
+ /**
+ * `ActionUpdateThread.OLD_EDT` is deprecated and going to be removed soon.
+ * Recommend to override `getActionUpdateThread()`
+ */
+ @Override
+ public @NotNull ActionUpdateThread getActionUpdateThread() {
+ return ActionUpdateThread.BGT;
+ }
+}
diff --git a/PluginsAndFeatures/azure-toolkit-for-intellij/azure-intellij-plugin-azd/src/main/java/com/microsoft/azure/toolkit/intellij/azd/actions/AzdInitCommandAction.java b/PluginsAndFeatures/azure-toolkit-for-intellij/azure-intellij-plugin-azd/src/main/java/com/microsoft/azure/toolkit/intellij/azd/actions/AzdInitCommandAction.java
new file mode 100644
index 00000000000..ca0449aa9f3
--- /dev/null
+++ b/PluginsAndFeatures/azure-toolkit-for-intellij/azure-intellij-plugin-azd/src/main/java/com/microsoft/azure/toolkit/intellij/azd/actions/AzdInitCommandAction.java
@@ -0,0 +1,11 @@
+package com.microsoft.azure.toolkit.intellij.azd.actions;
+
+import java.util.Set;
+
+public class AzdInitCommandAction extends AzdCommandAction {
+
+ @Override
+ public Set getSupportedFiles() {
+ return Set.of("pom.xml");
+ }
+}
diff --git a/PluginsAndFeatures/azure-toolkit-for-intellij/azure-intellij-plugin-azd/src/main/java/com/microsoft/azure/toolkit/intellij/azd/actions/AzdUpCommandAction.java b/PluginsAndFeatures/azure-toolkit-for-intellij/azure-intellij-plugin-azd/src/main/java/com/microsoft/azure/toolkit/intellij/azd/actions/AzdUpCommandAction.java
new file mode 100644
index 00000000000..7c5779f2495
--- /dev/null
+++ b/PluginsAndFeatures/azure-toolkit-for-intellij/azure-intellij-plugin-azd/src/main/java/com/microsoft/azure/toolkit/intellij/azd/actions/AzdUpCommandAction.java
@@ -0,0 +1,11 @@
+package com.microsoft.azure.toolkit.intellij.azd.actions;
+
+import java.util.Set;
+
+public class AzdUpCommandAction extends AzdCommandAction {
+
+ @Override
+ public Set getSupportedFiles() {
+ return Set.of("azure.yaml");
+ }
+}
diff --git a/PluginsAndFeatures/azure-toolkit-for-intellij/azure-intellij-plugin-azd/src/main/java/com/microsoft/azure/toolkit/intellij/azd/utils/AzdCliUtils.java b/PluginsAndFeatures/azure-toolkit-for-intellij/azure-intellij-plugin-azd/src/main/java/com/microsoft/azure/toolkit/intellij/azd/utils/AzdCliUtils.java
new file mode 100644
index 00000000000..9c99a06b1bf
--- /dev/null
+++ b/PluginsAndFeatures/azure-toolkit-for-intellij/azure-intellij-plugin-azd/src/main/java/com/microsoft/azure/toolkit/intellij/azd/utils/AzdCliUtils.java
@@ -0,0 +1,178 @@
+package com.microsoft.azure.toolkit.intellij.azd.utils;
+
+import com.google.gson.Gson;
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.configurations.GeneralCommandLine;
+import com.intellij.execution.process.OSProcessHandler;
+import com.intellij.execution.process.ProcessEvent;
+import com.intellij.execution.process.ProcessListener;
+import com.intellij.execution.process.ProcessOutput;
+import com.intellij.execution.process.ProcessOutputTypes;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.terminal.ui.TerminalWidget;
+import org.jetbrains.annotations.NotNull;
+
+import javax.annotation.Nullable;
+import java.nio.file.Paths;
+import java.util.concurrent.TimeUnit;
+
+public class AzdCliUtils {
+
+ private static final Logger logger = Logger.getInstance(AzdCliUtils.class);
+
+ private static final long CACHE_LIFETIME = 15 * 60 * 1000; // 15 minutes
+
+ private static long lastCheckTime = 0;
+
+ private static AzdVersion cachedAzdVersion = null;
+
+ public static boolean azdCliInstallAttempted = false;
+
+ public static boolean checkAzdCliInstalled(TerminalWidget terminal) {
+ if (azdCliInstallAttempted) {
+ return true;
+ } else {
+ return getAzdCliVersion(terminal) != null;
+ }
+ }
+
+ @Nullable
+ private static AzdVersion getAzdCliVersion(TerminalWidget terminal) {
+ // Check if the cached result is still valid
+ final long currentTime = System.currentTimeMillis();
+ if (cachedAzdVersion != null && (currentTime - lastCheckTime) < CACHE_LIFETIME) {
+ return cachedAzdVersion;
+ }
+
+ try {
+ final GeneralCommandLine commandLine = new GeneralCommandLine()
+ .withExePath("azd")
+ .withParameters("version", "--output", "json");
+
+ final ProcessOutput output = runCommand(commandLine);
+ if (output.getExitCode() == 0) {
+ final String stdout = output.getStdout();
+ final Gson gson = new Gson();
+ final AzdVersion azdVersion = gson.fromJson(stdout, AzdVersion.class);
+ // Cache the result
+ cachedAzdVersion = azdVersion;
+ lastCheckTime = currentTime;
+ return azdVersion;
+ } else {
+ logger.warn("Failed to check azd version. Exit code: " + output.getExitCode());
+ }
+ } catch (Exception ex) {
+ logger.warn("Unexpected error while checking azd version", ex);
+ }
+
+ return null;
+ }
+
+
+ private static ProcessOutput runCommand(GeneralCommandLine commandLine) throws ExecutionException {
+ final OSProcessHandler processHandler = new OSProcessHandler(commandLine);
+ final ProcessOutput output = new ProcessOutput();
+
+ processHandler.addProcessListener(new ProcessListener() {
+ @Override
+ public void onTextAvailable(ProcessEvent event, Key outputType) {
+ if (ProcessOutputTypes.STDOUT.equals(outputType)) {
+ output.appendStdout(event.getText());
+ } else if (ProcessOutputTypes.STDERR.equals(outputType)) {
+ output.appendStderr(event.getText());
+ }
+ }
+
+ @Override
+ public void processTerminated(ProcessEvent event) {
+ output.setExitCode(event.getExitCode());
+ }
+ });
+
+ processHandler.startNotify();
+ processHandler.waitFor(TimeUnit.SECONDS.toMillis(30)); // Wait up to 30 seconds
+ return output;
+ }
+
+ private static class AzdVersion {
+
+ private AzdVersionInfo azd;
+
+ public AzdVersionInfo getAzd() {
+ return azd;
+ }
+
+ public static class AzdVersionInfo {
+ private String version;
+ private String commit;
+
+ public String getVersion() {
+ return version;
+ }
+
+ public String getCommit() {
+ return commit;
+ }
+ }
+ }
+
+ public static void installAzdCli(@NotNull TerminalWidget terminal) {
+ final String installCommand = getInstallationCommandLine();
+ terminal.sendCommandToExecute(installCommand);
+ setupAzdEnvs(terminal);
+ }
+
+ private static String getInstallationCommandLine() {
+ // See https://aka.ms/azd-install
+ final String commandLine;
+ if (SystemInfo.isWindows) {
+ commandLine = "powershell -ex AllSigned -c \"Invoke-RestMethod 'https://aka.ms/install-azd.ps1' | Invoke-Expression\"";
+ } else if (SystemInfo.isLinux || SystemInfo.isMac) {
+ commandLine = "curl -fsSL https://aka.ms/install-azd.sh | bash";
+ } else {
+ final String osName = System.getProperty("os.name");
+ logger.error("Unsupported platform: " + osName);
+ throw new UnsupportedOperationException("Unsupported platform: " + osName);
+ }
+ return commandLine;
+ }
+
+ /**
+ * On Unix, the CLI is installed to /usr/local/bin, which is always going to be in the PATH.
+ * On Windows, the install location is at %LOCALAPPDATA%\Programs\Azure Dev CLI when installed by default.
+ * To avoid needing to restart IDE to get the updated PATH, we'll temporarily add the default install location,
+ * as long as it's Windows, AZURE_DEV_CLI_PATH is unset, "Azure Dev CLI" isn't already in the PATH, and the user
+ * did try to install within this session.
+ */
+ public static void setupAzdEnvs(@NotNull TerminalWidget terminal) {
+ if (SystemInfo.isWindows && System.getenv("AZURE_DEV_CLI_PATH") == null && !getPathEnv().contains("/Azure Dev CLI/")) {
+ terminal.sendCommandToExecute(String.format("$env:Path = '%s;' + $env:Path", getDefaultAzdInstallLocation()));
+ azdCliInstallAttempted = true;
+ }
+ }
+
+ private static String getPathEnv() {
+ String pathEnv = System.getenv("PATH");
+ if (pathEnv == null) {
+ pathEnv = "";
+ }
+ return pathEnv;
+ }
+
+ private static String getDefaultAzdInstallLocation() {
+ final String localAppData = System.getenv("LOCALAPPDATA");
+ return Paths.get(localAppData, "Programs", "Azure Dev CLI").toString();
+ }
+
+ public static String getAzdInvocation(String command) {
+ final String azureDevCliPath = System.getenv("AZURE_DEV_CLI_PATH");
+ if (azureDevCliPath == null) {
+ return command;
+ } else {
+ return azureDevCliPath + command.substring(3);
+ }
+ }
+
+}
diff --git a/PluginsAndFeatures/azure-toolkit-for-intellij/azure-intellij-plugin-azd/src/main/java/com/microsoft/azure/toolkit/intellij/azd/utils/TerminalUtils.java b/PluginsAndFeatures/azure-toolkit-for-intellij/azure-intellij-plugin-azd/src/main/java/com/microsoft/azure/toolkit/intellij/azd/utils/TerminalUtils.java
new file mode 100644
index 00000000000..645960493bf
--- /dev/null
+++ b/PluginsAndFeatures/azure-toolkit-for-intellij/azure-intellij-plugin-azd/src/main/java/com/microsoft/azure/toolkit/intellij/azd/utils/TerminalUtils.java
@@ -0,0 +1,14 @@
+package com.microsoft.azure.toolkit.intellij.azd.utils;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.terminal.ui.TerminalWidget;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.terminal.TerminalToolWindowManager;
+
+public class TerminalUtils {
+
+ public static TerminalWidget createTerminalWidget(@NotNull Project project, @NotNull String workingDir, String command) {
+ final TerminalToolWindowManager terminalManager = TerminalToolWindowManager.getInstance(project);
+ return terminalManager.createShellWidget(workingDir, command, true, true);
+ }
+}
diff --git a/PluginsAndFeatures/azure-toolkit-for-intellij/azure-intellij-plugin-azd/src/main/resources/META-INF/azure-intellij-plugin-azd.xml b/PluginsAndFeatures/azure-toolkit-for-intellij/azure-intellij-plugin-azd/src/main/resources/META-INF/azure-intellij-plugin-azd.xml
new file mode 100644
index 00000000000..51f9c8d35fc
--- /dev/null
+++ b/PluginsAndFeatures/azure-toolkit-for-intellij/azure-intellij-plugin-azd/src/main/resources/META-INF/azure-intellij-plugin-azd.xml
@@ -0,0 +1,15 @@
+
+ com.intellij.modules.platform
+ org.jetbrains.plugins.terminal
+
+
+
+
+
+
+
+
diff --git a/PluginsAndFeatures/azure-toolkit-for-intellij/azure-intellij-plugin-azd/src/main/resources/icons/azd-logo.svg b/PluginsAndFeatures/azure-toolkit-for-intellij/azure-intellij-plugin-azd/src/main/resources/icons/azd-logo.svg
new file mode 100644
index 00000000000..cde780b97b9
--- /dev/null
+++ b/PluginsAndFeatures/azure-toolkit-for-intellij/azure-intellij-plugin-azd/src/main/resources/icons/azd-logo.svg
@@ -0,0 +1,13 @@
+
+
diff --git a/PluginsAndFeatures/azure-toolkit-for-intellij/build.gradle.kts b/PluginsAndFeatures/azure-toolkit-for-intellij/build.gradle.kts
index 8f261f94a30..815add8fd61 100644
--- a/PluginsAndFeatures/azure-toolkit-for-intellij/build.gradle.kts
+++ b/PluginsAndFeatures/azure-toolkit-for-intellij/build.gradle.kts
@@ -210,6 +210,7 @@ dependencies {
implementation(project(":azure-intellij-plugin-integration-services"))
implementation(project(":azure-intellij-plugin-cloud-shell"))
implementation(project(":azure-intellij-plugin-java-sdk"))
+ implementation(project(":azure-intellij-plugin-azd"))
implementation("commons-io:commons-io")
implementation("org.apache.commons:commons-lang3")
implementation("com.microsoft.azure:azure-toolkit-common-lib")
diff --git a/PluginsAndFeatures/azure-toolkit-for-intellij/settings.gradle.kts b/PluginsAndFeatures/azure-toolkit-for-intellij/settings.gradle.kts
index a3697b9af45..8b496daf216 100644
--- a/PluginsAndFeatures/azure-toolkit-for-intellij/settings.gradle.kts
+++ b/PluginsAndFeatures/azure-toolkit-for-intellij/settings.gradle.kts
@@ -50,3 +50,4 @@ include("azure-intellij-plugin-keyvault-java")
include("azure-intellij-plugin-integration-services")
include("azure-intellij-plugin-java-sdk")
include("azure-intellij-plugin-cloud-shell")
+include("azure-intellij-plugin-azd")
diff --git a/PluginsAndFeatures/azure-toolkit-for-intellij/src/main/resources/META-INF/plugin.xml b/PluginsAndFeatures/azure-toolkit-for-intellij/src/main/resources/META-INF/plugin.xml
index 75a04e3fb56..a40e29217cb 100644
--- a/PluginsAndFeatures/azure-toolkit-for-intellij/src/main/resources/META-INF/plugin.xml
+++ b/PluginsAndFeatures/azure-toolkit-for-intellij/src/main/resources/META-INF/plugin.xml
@@ -82,6 +82,7 @@
+