Feat: Automatically run aws sso login when credentials need to be refreshed #1303

Closed
opened 2026-02-16 17:30:22 -05:00 by yindo · 5 comments
Owner

Originally created by @markjaquith on GitHub (Aug 14, 2025).

Originally assigned to: @thdxr on GitHub.

I get this about twice a day, because my job enforces a pretty fast expiration for AWS login credentials:

Error: AWS credential provider failed: The SSO session associated with this profile has expired. To refresh this SSO session run aws sso login with the corresponding profile.. Please ensure your credential provider returns valid AWS credentials with accessKeyId and secretAccessKey properties.

Should opencode automatically run aws sso login when this is encountered?

Originally created by @markjaquith on GitHub (Aug 14, 2025). Originally assigned to: @thdxr on GitHub. I get this about twice a day, because my job enforces a pretty fast expiration for AWS login credentials: > Error: AWS credential provider failed: The SSO session associated with this profile has expired. To refresh this SSO session run aws sso login with the corresponding profile.. Please ensure your credential provider returns valid AWS credentials with accessKeyId and secretAccessKey properties. Should opencode automatically run `aws sso login` when this is encountered?
yindo closed this issue 2026-02-16 17:30:22 -05:00
Author
Owner

@the-vampiire commented on GitHub (Aug 15, 2025):

hey @markjaquith i have never written a plugin but i gave it a shot.

originally tried handling the error in tool.execute.after but thats pretty brittle and it still results in the agent reporting the error and having to manually retry.

went with going in the before hook and it required some sort of timer otherwise it may get spammed.

i think this will work:

import type { Plugin } from "@opencode-ai/plugin";

// TODO: set this to your login frequency
const LOGIN_INTERVAL_SECONDS = 60 * 20;

// TODO: set command name to watch for
const COMMAND_NAME = 'aws';

// TODO: set login command
const LOGIN_COMMAND = `${COMMAND_NAME} sso login`;

// start this as 0 to do a guaranteed initial login first time plugin is run
let lastLoginTimestamp = 0;

const isLoginStale = (lastLoginTimestamp: number, currentTimestamp: number, staleTimeSeconds: number) => {
  const diffSeconds = ((currentTimestamp - lastLoginTimestamp) / 1000);

  return diffSeconds >= staleTimeSeconds;
}

export const AutoLoginPlugin: Plugin = async ({ app, client, $ }) => {
  return {
    "tool.execute.before": async (input, output) => {
      const isBashTool = input.tool === "bash";
      const isTargetCommand = isBashTool &&  output.args.command.startsWith(COMMAND_NAME);

      const currentTimestamp = Date.now();
      const shouldLogInAgain = isLoginStale(lastLoginTimestamp, currentTimestamp, LOGIN_INTERVAL_SECONDS);

      if (isTargetCommand && shouldLogInAgain) {
        console.log(`[${currentTimestamp}] Refreshing [${COMMAND_NAME}] login with command [${LOGIN_COMMAND}]`);
        await $`${LOGIN_COMMAND}`;

        lastLoginTimestamp = currentTimestamp;
      }

    },
  }
}

it would be nice to have the agent report "hey i took an auto-action" and i went down quite a rabbithole trying to find a way to do that. i dont believe its possible to send messages from plugins.

@the-vampiire commented on GitHub (Aug 15, 2025): hey @markjaquith i have never written a plugin but i gave it a shot. originally tried handling the error in `tool.execute.after` but thats pretty brittle and it still results in the agent reporting the error and having to manually retry. went with going in the before hook and it required some sort of timer otherwise it may get spammed. i think this will work: ```ts import type { Plugin } from "@opencode-ai/plugin"; // TODO: set this to your login frequency const LOGIN_INTERVAL_SECONDS = 60 * 20; // TODO: set command name to watch for const COMMAND_NAME = 'aws'; // TODO: set login command const LOGIN_COMMAND = `${COMMAND_NAME} sso login`; // start this as 0 to do a guaranteed initial login first time plugin is run let lastLoginTimestamp = 0; const isLoginStale = (lastLoginTimestamp: number, currentTimestamp: number, staleTimeSeconds: number) => { const diffSeconds = ((currentTimestamp - lastLoginTimestamp) / 1000); return diffSeconds >= staleTimeSeconds; } export const AutoLoginPlugin: Plugin = async ({ app, client, $ }) => { return { "tool.execute.before": async (input, output) => { const isBashTool = input.tool === "bash"; const isTargetCommand = isBashTool && output.args.command.startsWith(COMMAND_NAME); const currentTimestamp = Date.now(); const shouldLogInAgain = isLoginStale(lastLoginTimestamp, currentTimestamp, LOGIN_INTERVAL_SECONDS); if (isTargetCommand && shouldLogInAgain) { console.log(`[${currentTimestamp}] Refreshing [${COMMAND_NAME}] login with command [${LOGIN_COMMAND}]`); await $`${LOGIN_COMMAND}`; lastLoginTimestamp = currentTimestamp; } }, } } ``` it would be nice to have the agent report "hey i took an auto-action" and i went down quite a rabbithole trying to find a way to do that. i dont believe its possible to send messages from plugins.
Author
Owner

@the-vampiire commented on GitHub (Aug 15, 2025):

heres a more generalized one that can handle multiple commands

import type { Plugin } from "@opencode-ai/plugin";

interface CommandConfig {
  commandName: string;
  loginCommand: string;
  intervalSeconds: number;
  lastLoginTimestamp: number;
}

// Configuration for commands that need auto-login
const COMMAND_CONFIGS: CommandConfig[] = [
  {
    commandName: 'aws',
    loginCommand: 'aws sso login',
    intervalSeconds: 60 * 20, // 20 minutes
    lastLoginTimestamp: 0, // Start at 0 for guaranteed initial login
  },
  // Add more commands here as needed:
  // {
  //   commandName: 'gcloud',
  //   loginCommand: 'gcloud auth login',
  //   intervalSeconds: 60 * 30, // 30 minutes
  //   lastLoginTimestamp: 0,
  // },
];

const isLoginStale = (lastLoginTimestamp: number, currentTimestamp: number, staleTimeSeconds: number) => {
  const diffSeconds = ((currentTimestamp - lastLoginTimestamp) / 1000);
  return diffSeconds >= staleTimeSeconds;
}

export const AutoLoginPlugin: Plugin = async ({ app, client, $ }) => {
  return {
    "tool.execute.before": async (input, output) => {
      const isBashTool = input.tool === "bash";
      
      if (!isBashTool) return;

      const currentTimestamp = Date.now();

      for (const config of COMMAND_CONFIGS) {
        const isTargetCommand = output.args.command.startsWith(config.commandName);
        const shouldLogInAgain = isLoginStale(config.lastLoginTimestamp, currentTimestamp, config.intervalSeconds);

        if (isTargetCommand && shouldLogInAgain) {
          console.log(`Refreshing ${config.commandName} login`);
          await $`${config.loginCommand}`;
          config.lastLoginTimestamp = currentTimestamp;
          
          return;
        }
      }
    },
  }
}
@the-vampiire commented on GitHub (Aug 15, 2025): heres a more generalized one that can handle multiple commands ```ts import type { Plugin } from "@opencode-ai/plugin"; interface CommandConfig { commandName: string; loginCommand: string; intervalSeconds: number; lastLoginTimestamp: number; } // Configuration for commands that need auto-login const COMMAND_CONFIGS: CommandConfig[] = [ { commandName: 'aws', loginCommand: 'aws sso login', intervalSeconds: 60 * 20, // 20 minutes lastLoginTimestamp: 0, // Start at 0 for guaranteed initial login }, // Add more commands here as needed: // { // commandName: 'gcloud', // loginCommand: 'gcloud auth login', // intervalSeconds: 60 * 30, // 30 minutes // lastLoginTimestamp: 0, // }, ]; const isLoginStale = (lastLoginTimestamp: number, currentTimestamp: number, staleTimeSeconds: number) => { const diffSeconds = ((currentTimestamp - lastLoginTimestamp) / 1000); return diffSeconds >= staleTimeSeconds; } export const AutoLoginPlugin: Plugin = async ({ app, client, $ }) => { return { "tool.execute.before": async (input, output) => { const isBashTool = input.tool === "bash"; if (!isBashTool) return; const currentTimestamp = Date.now(); for (const config of COMMAND_CONFIGS) { const isTargetCommand = output.args.command.startsWith(config.commandName); const shouldLogInAgain = isLoginStale(config.lastLoginTimestamp, currentTimestamp, config.intervalSeconds); if (isTargetCommand && shouldLogInAgain) { console.log(`Refreshing ${config.commandName} login`); await $`${config.loginCommand}`; config.lastLoginTimestamp = currentTimestamp; return; } } }, } } ```
Author
Owner

@rekram1-node commented on GitHub (Dec 27, 2025):

[automated] Closing due to 90+ days of inactivity. Feel free to reopen if you still need this!

@rekram1-node commented on GitHub (Dec 27, 2025): [automated] Closing due to 90+ days of inactivity. Feel free to reopen if you still need this!
Author
Owner

@itahol commented on GitHub (Jan 10, 2026):

Hey @rekram1-node , I would still like this very much!

@itahol commented on GitHub (Jan 10, 2026): Hey @rekram1-node , I would still like this very much!
Author
Owner

@anenger commented on GitHub (Jan 23, 2026):

Would be awesome if this was built into opencode cc: @thdxr

@anenger commented on GitHub (Jan 23, 2026): Would be awesome if this was built into opencode cc: @thdxr
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#1303