diff --git a/README.md b/README.md
index c3a910b0..54521de2 100644
--- a/README.md
+++ b/README.md
@@ -65,6 +65,13 @@ yarn 2+ have native support for patching dependencies via
 [`yarn patch`](https://yarnpkg.com/cli/patch). You do not need to use
 patch-package on these projects.
 
+### bun
+
+    bun add patch-package
+
+You can use `--dev` if you don't need to run bun in production, e.g. if you're
+making a web frontend.
+
 ### pnpm
 
 pnpm has native support for patching dependencies via
@@ -152,9 +159,15 @@ team.
 
 - `--use-yarn`
 
-  By default, patch-package checks whether you use npm or yarn based on which
-  lockfile you have. If you have both, it uses npm by default. Set this option
-  to override that default and always use yarn.
+  By default, patch-package checks whether you use npm, yarn or bun based on
+  which lockfile you have. If you have multiple lockfiles, it uses npm by
+  default (in cases where npm is not available, it will resort to yarn). Set
+  this option to override that default and always use yarn.
+
+- `--use-bun`
+
+  Similar to --use-yarn, but for bun. If both --use-yarn and --use-bun are
+  specified, --use-yarn takes precedence.
 
 - `--exclude <regexp>`
 
diff --git a/src/detectPackageManager.ts b/src/detectPackageManager.ts
index c7bb7559..5f2ae183 100644
--- a/src/detectPackageManager.ts
+++ b/src/detectPackageManager.ts
@@ -4,7 +4,7 @@ import chalk from "chalk"
 import process from "process"
 import findWorkspaceRoot from "find-yarn-workspace-root"
 
-export type PackageManager = "yarn" | "npm" | "npm-shrinkwrap"
+export type PackageManager = "yarn" | "npm" | "npm-shrinkwrap" | "bun"
 
 function printNoYarnLockfileError() {
   console.log(`
@@ -14,12 +14,20 @@ ${chalk.red.bold("**ERROR**")} ${chalk.red(
 `)
 }
 
+function printNoBunLockfileError() {
+  console.log(`
+${chalk.red.bold("**ERROR**")} ${chalk.red(
+    `The --use-bun option was specified but there is no bun.lockb file`,
+  )}
+`)
+}
+
 function printNoLockfilesError() {
   console.log(`
 ${chalk.red.bold("**ERROR**")} ${chalk.red(
-    `No package-lock.json, npm-shrinkwrap.json, or yarn.lock file.
+    `No package-lock.json, npm-shrinkwrap.json, yarn.lock, or bun.lockb file.
 
-You must use either npm@>=5, yarn, or npm-shrinkwrap to manage this project's
+You must use either npm@>=5, yarn, npm-shrinkwrap, or bun to manage this project's
 dependencies.`,
   )}
 `)
@@ -29,14 +37,40 @@ function printSelectingDefaultMessage() {
   console.info(
     `${chalk.bold(
       "patch-package",
-    )}: you have both yarn.lock and package-lock.json
+    )}: you have multiple lockfiles, e.g. yarn.lock and package-lock.json
 Defaulting to using ${chalk.bold("npm")}
-You can override this setting by passing --use-yarn or deleting
-package-lock.json if you don't need it
+You can override this setting by passing --use-yarn, --use-bun, or
+deleting the conflicting lockfile if you don't need it
+`,
+  )
+}
+
+function printSelectingDefaultYarnMessage() {
+  console.info(
+    `${chalk.bold(
+      "patch-package",
+    )}: you have both yarn.lock and bun.lockb lockfiles
+Defaulting to using ${chalk.bold("yarn")}
+You can override this setting by passing --use-bun, or
+deleting yarn.lock if you don't need it
 `,
   )
 }
 
+function checkForYarnOverride(overridePackageManager: PackageManager | null) {
+  if (overridePackageManager === "yarn") {
+    printNoYarnLockfileError()
+    process.exit(1)
+  }
+}
+
+function checkForBunOverride(overridePackageManager: PackageManager | null) {
+  if (overridePackageManager === "bun") {
+    printNoBunLockfileError()
+    process.exit(1)
+  }
+}
+
 export const detectPackageManager = (
   appRootPath: string,
   overridePackageManager: PackageManager | null,
@@ -47,23 +81,40 @@ export const detectPackageManager = (
   const shrinkWrapExists = fs.existsSync(
     join(appRootPath, "npm-shrinkwrap.json"),
   )
-  const yarnLockExists = fs.existsSync(join(appRootPath, "yarn.lock"))
-  if ((packageLockExists || shrinkWrapExists) && yarnLockExists) {
+  const yarnLockExists = fs.existsSync(
+    join(findWorkspaceRoot() ?? appRootPath, "yarn.lock"),
+  )
+  // Bun workspaces seem to work the same as yarn workspaces - https://bun.sh/docs/install/workspaces
+  const bunLockbExists = fs.existsSync(
+    join(findWorkspaceRoot() ?? appRootPath, "bun.lockb"),
+  )
+  if (
+    [
+      packageLockExists || shrinkWrapExists,
+      yarnLockExists,
+      bunLockbExists,
+    ].filter(Boolean).length > 1
+  ) {
     if (overridePackageManager) {
       return overridePackageManager
-    } else {
-      printSelectingDefaultMessage()
-      return shrinkWrapExists ? "npm-shrinkwrap" : "npm"
     }
-  } else if (packageLockExists || shrinkWrapExists) {
-    if (overridePackageManager === "yarn") {
-      printNoYarnLockfileError()
-      process.exit(1)
-    } else {
-      return shrinkWrapExists ? "npm-shrinkwrap" : "npm"
+    if (!packageLockExists && !shrinkWrapExists) {
+      // The only case where we don't want to default to npm is when we have both yarn and bun lockfiles.
+      printSelectingDefaultYarnMessage()
+      return "yarn"
     }
-  } else if (yarnLockExists || findWorkspaceRoot()) {
+    printSelectingDefaultMessage()
+    return shrinkWrapExists ? "npm-shrinkwrap" : "npm"
+  } else if (packageLockExists || shrinkWrapExists) {
+    checkForYarnOverride(overridePackageManager)
+    checkForBunOverride(overridePackageManager)
+    return shrinkWrapExists ? "npm-shrinkwrap" : "npm"
+  } else if (yarnLockExists) {
+    checkForBunOverride(overridePackageManager)
     return "yarn"
+  } else if (bunLockbExists) {
+    checkForYarnOverride(overridePackageManager)
+    return "bun"
   } else {
     printNoLockfilesError()
     process.exit(1)
diff --git a/src/getPackageResolution.ts b/src/getPackageResolution.ts
index a046e7f9..2d740070 100644
--- a/src/getPackageResolution.ts
+++ b/src/getPackageResolution.ts
@@ -7,6 +7,7 @@ import yaml from "yaml"
 import findWorkspaceRoot from "find-yarn-workspace-root"
 import { getPackageVersion } from "./getPackageVersion"
 import { coerceSemVer } from "./coerceSemVer"
+import { parseBunLockfile } from "./parseBunLockfile"
 
 export function getPackageResolution({
   packageDetails,
@@ -17,24 +18,32 @@ export function getPackageResolution({
   packageManager: PackageManager
   appPath: string
 }) {
-  if (packageManager === "yarn") {
-    let lockFilePath = "yarn.lock"
+  if (packageManager === "yarn" || packageManager === "bun") {
+    const isBun = packageManager === "bun"
+    const lockFileName = isBun ? "bun.lockb" : "yarn.lock"
+    let lockFilePath = lockFileName
     if (!existsSync(lockFilePath)) {
       const workspaceRoot = findWorkspaceRoot()
       if (!workspaceRoot) {
-        throw new Error("Can't find yarn.lock file")
+        throw new Error(`Can't find ${lockFileName} file`)
       }
-      lockFilePath = join(workspaceRoot, "yarn.lock")
+      lockFilePath = join(workspaceRoot, lockFilePath)
     }
     if (!existsSync(lockFilePath)) {
-      throw new Error("Can't find yarn.lock file")
+      throw new Error(`Can't find ${lockFileName} file`)
     }
-    const lockFileString = readFileSync(lockFilePath).toString()
+    const lockFileString = isBun
+      ? parseBunLockfile(lockFilePath)
+      : readFileSync(lockFilePath).toString()
     let appLockFile
     if (lockFileString.includes("yarn lockfile v1")) {
       const parsedYarnLockFile = parseYarnLockFile(lockFileString)
       if (parsedYarnLockFile.type !== "success") {
-        throw new Error("Could not parse yarn v1 lock file")
+        throw new Error(
+          `Could not parse yarn v1 lock file ${
+            isBun ? "- was originally a bun.lockb file" : ""
+          }`,
+        )
       } else {
         appLockFile = parsedYarnLockFile.object
       }
@@ -43,7 +52,11 @@ export function getPackageResolution({
         appLockFile = yaml.parse(lockFileString)
       } catch (e) {
         console.log(e)
-        throw new Error("Could not parse yarn v2 lock file")
+        throw new Error(
+          `Could not parse yarn v2 lock file ${
+            isBun ? "- was originally a bun.lockb file (should not happen)" : ""
+          }`,
+        )
       }
     }
 
diff --git a/src/index.ts b/src/index.ts
index 8ee449a9..31a92fec 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -84,7 +84,7 @@ if (argv.version || argv.v) {
     )
     const packageManager = detectPackageManager(
       appPath,
-      argv["use-yarn"] ? "yarn" : null,
+      argv["use-yarn"] ? "yarn" : argv["use-bun"] ? "bun" : null,
     )
     const createIssue = argv["create-issue"]
     packageNames.forEach((packagePathSpecifier: string) => {
@@ -198,9 +198,15 @@ Usage:
 
     ${chalk.bold("--use-yarn")}
 
-        By default, patch-package checks whether you use npm or yarn based on
-        which lockfile you have. If you have both, it uses npm by default.
-        Set this option to override that default and always use yarn.
+        By default, patch-package checks whether you use npm, yarn or bun based on
+        which lockfile you have. If you have multiple lockfiles, it uses npm by
+        default (in cases where npm is not available, it will resort to yarn). Set 
+        this option to override that default and always use yarn.
+        
+    ${chalk.bold("--use-bun")}
+    
+        Similar to --use-yarn, but for bun. If both --use-yarn and --use-bun are
+        specified, --use-yarn takes precedence.
 
     ${chalk.bold("--exclude <regexp>")}
 
diff --git a/src/parseBunLockfile.ts b/src/parseBunLockfile.ts
new file mode 100644
index 00000000..2ebed2d0
--- /dev/null
+++ b/src/parseBunLockfile.ts
@@ -0,0 +1,15 @@
+import { spawnSync } from "child_process"
+
+// Adapted from https://github.com/oven-sh/bun/blob/ffe4f561a3af53b9f5a41c182de55d7199b5d692/packages/bun-vscode/src/features/lockfile.ts#L39,
+// rewritten to use spawnSync instead of spawn.
+export function parseBunLockfile(lockFilePath: string): string {
+  const process = spawnSync("bun", [lockFilePath], {
+    stdio: ["ignore", "pipe", "pipe"],
+  })
+  if (process.status !== 0) {
+    throw new Error(
+      `Bun exited with code: ${process.status}\n${process.stderr.toString()}`,
+    )
+  }
+  return process.stdout.toString()
+}