diff --git a/README.md b/README.md
index 3ebec33e..05688f2a 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,9 @@
> [!NOTE]
-> This tool is only used for managing [Deno Deploy Classic](https://docs.deno.com/deploy/classic/) organizations and their projects. New Deno Deploy organizations use the `deno deploy` command built into the Deno Runtime. Learn more about the new `deno deploy` command in the [reference docs](https://docs.deno.com/runtime/reference/cli/deploy/)
+> This tool is only used for managing
+> [Deno Deploy Classic](https://docs.deno.com/deploy/classic/) organizations and
+> their projects. New Deno Deploy organizations use the `deno deploy` command
+> built into the Deno Runtime. Learn more about the new `deno deploy` command in
+> the [reference docs](https://docs.deno.com/runtime/reference/cli/deploy/)
# deployctl
diff --git a/deployctl.ts b/deployctl.ts
index 58df3363..d438355d 100755
--- a/deployctl.ts
+++ b/deployctl.ts
@@ -6,7 +6,7 @@ import {
greaterOrEqual as semverGreaterThanOrEquals,
parse as semverParse,
} from "@std/semver";
-import { setColorEnabled } from "@std/fmt/colors";
+import { bold, setColorEnabled, yellow } from "@std/fmt/colors";
import { type Args, parseArgs } from "./src/args.ts";
import { error } from "./src/error.ts";
import deploySubcommand from "./src/subcommands/deploy.ts";
@@ -23,7 +23,7 @@ import inferConfig from "./src/config_inference.ts";
import { wait } from "./src/utils/spinner.ts";
const help = `deployctl ${VERSION}
-Command line tool for Deno Deploy.
+Command line tool for Deno Deploy Classic.
SUBCOMMANDS:
deploy Deploy a script with static files to Deno Deploy
@@ -99,6 +99,57 @@ if (Deno.stdin.isTerminal()) {
}
}
+// Show a deprecation notice directing users to the new "deno deploy" command.
+// - Interactive terminals: always show
+// - Non-interactive (CI): show once per day, cached to disk
+// - Set DEPLOYCTL_NO_DEPRECATION_NOTICE=1 to suppress entirely
+if (!Deno.env.get("DEPLOYCTL_NO_DEPRECATION_NOTICE")) {
+ let showNotice = false;
+
+ if (Deno.stdin.isTerminal()) {
+ showNotice = true;
+ } else {
+ // In non-interactive environments, only show once per day
+ const { deprecationNoticePath, configDir } = getConfigPaths();
+ try {
+ const json = await Deno.readTextFile(deprecationNoticePath);
+ const { lastShown } = JSON.parse(json) as { lastShown: number };
+ const moreThanADay =
+ Math.abs(Date.now() - lastShown) > 24 * 60 * 60 * 1000;
+ if (moreThanADay) {
+ showNotice = true;
+ }
+ } catch {
+ // File doesn't exist yet or is unreadable — show the notice
+ showNotice = true;
+ }
+
+ if (showNotice) {
+ // Update the cache so we don't show again for 24 hours
+ try {
+ await Deno.mkdir(configDir, { recursive: true });
+ await Deno.writeTextFile(
+ deprecationNoticePath,
+ JSON.stringify({ lastShown: Date.now() }, null, 2),
+ );
+ } catch {
+ // Not critical — if we can't write the cache, the notice will
+ // just show again next time.
+ }
+ }
+ }
+
+ if (showNotice) {
+ console.error(
+ yellow(bold("warning")) +
+ `: deployctl is for Deno Deploy Classic only.\n` +
+ ` For the new Deno Deploy, use the "deno deploy" command built into the Deno runtime.\n` +
+ ` Learn more: https://docs.deno.com/runtime/reference/cli/deploy/\n` +
+ ` To suppress this warning, set DEPLOYCTL_NO_DEPRECATION_NOTICE=1\n`,
+ );
+ }
+}
+
const subcommand = args._.shift();
switch (subcommand) {
case "deploy":
diff --git a/examples/fresh/static/logo.svg b/examples/fresh/static/logo.svg
index ef2fbe4c..5b99e0b1 100644
--- a/examples/fresh/static/logo.svg
+++ b/examples/fresh/static/logo.svg
@@ -1,6 +1,19 @@
\ No newline at end of file
+
+
+
+
+
diff --git a/src/utils/info.ts b/src/utils/info.ts
index 37c4c707..181f9f73 100644
--- a/src/utils/info.ts
+++ b/src/utils/info.ts
@@ -11,6 +11,7 @@ export function getConfigPaths() {
configDir,
updatePath: join(configDir, "update.json"),
credentialsPath: join(configDir, "credentials.json"),
+ deprecationNoticePath: join(configDir, "deprecation_notice.json"),
};
}