Athenode

Approvals and rules

An approval is your decision on an action that your AI coding agent asks the SSH gateway to run: you approve it, reject it or always allow it. The SSH gateway is the part of Athenode through which your AI agent runs commands and transfers files on your SSH hosts, each action approved by you or by a rule you set. A connection is one SSH host in the SSH gateway, with its login, its host key and its rules, as the SSH gateway overview describes.

Three settings decide whether an action waits for you: the confirmation mode of the connection or of the session, the allow rules that let matching actions run without asking, and the denylist, whose matches always wait. Every action needs a reason from the agent, which is shown above the command when you decide.

Action Goes through approval
exec, start_job Yes, matched as a command
cancel_job Yes, matched as cancel_job followed by the job's command
read_file, write_file, list_dir, upload, download Yes, matched as the tool followed by the remote path
add_service, update_service that create or change a health check Yes, matched like an exec of the check's command
job_status, job_logs, exec_output, service_health, run_service_check No. They run at once and appear in History

Approvals, allow rules and the denylist are managed in the web UI only. No tool of the Athenode MCP server reads or changes them, and no CLI command does.

Choose the confirmation mode of a connection

The confirmation mode of a connection decides what happens to an action that no allow rule covers. You set it when the agent's work on a host should wait for you, or run on its own. On Athenode Pro you need the owner role in the project, as project roles lists.

Mode Label What it does
confirm Require confirmation Every action waits for your approval, unless all of it matches allow rules. A new connection has this mode.
auto Auto Every action runs without asking, except those that match the denylist.
  1. Open Connections in the SSH Gateway group of the sidebar and select the connection.
  2. Open the Settings tab.
  3. Under Behaviour, at Default confirmation mode, choose Require confirmation or Auto.
  4. Select Save changes.

The mode applies to the sessions that do not override it. An action takes the mode that applies when it arrives, so a change does not release actions that are already waiting.

Change the confirmation mode of one session

A session is the work of one AI tool session on one connection. Each session has its own window, listed under its connection in the sidebar, and it can override the connection's mode, for example to let one agent run a series of checks without asking while other sessions keep asking.

  1. Open the session: select it under its connection in the sidebar, or select one of its actions on the Live or History page.
  2. At Confirmation mode in the session's header, choose Auto or Confirm. Connection default returns the session to the connection's mode, which it shows in brackets.

The new mode applies to the actions that arrive afterwards. An action already waiting keeps waiting for your decision. A new session of the AI tool starts with the connection's mode again. On Athenode Pro only the account whose agent runs the session can change its mode, and everyone else sees the mode as text.

Approve or reject an action

An action that needs approval waits until you decide, until the approval timeout ends or until the AI tool cancels the call. Athenode tells you about it in several places:

  • The header of the web UI shows "An action is waiting for your approval." with the number of waiting actions, and Review opens the session of the oldest one.
  • The browser tab's title starts with the number in brackets, such as (2).
  • The Live page lists every action that is waiting or running, across all sessions of the project, with the agent's reason, the command, the connection, the session and the tool.
  • With desktop notifications on, the browser shows "Approval needed:" followed by the connection's name. Turn them on under Notifications on the Settings page with Allow. The choice applies to that browser only.

To decide:

  1. Open Live and select the waiting action. An action you can decide is marked "Open to decide".
  2. In the session window, read the reason and the command.
  3. Select Approve to run the action, Reject to refuse it, or Always allow… to approve it and save an allow rule, as allow an action from now on describes.

The first decision counts. If the action was decided in another tab or window, or has timed out, the session window shows "Already decided" and nothing runs. On Athenode Pro only the account whose agent asked decides, administrators included, and everyone else sees "Waiting for the decision of the user whose agent asked." The gateway on Athenode Pro describes who sees which sessions.

What the agent receives for each outcome

Outcome What happens What your AI agent receives Status of the action
Approved The action runs The result of the action Running, then Done or Failed
Rejected Nothing runs "Rejected by user" Rejected
Timed out Nothing runs "Approval timed out after 10m", with the approval timeout in force Timed out
Cancelled by the AI tool Nothing runs "Cancelled by the client" Cancelled
Athenode stopped while the action waited Nothing runs "SSH Gateway is shutting down" Aborted, after the next start

The approval timeout is 10 minutes. It starts when the action arrives and does not restart. You change it on the Settings page, as History and gateway settings lists, and the new value applies to actions that arrive afterwards. An action that was running when Athenode stopped shows Interrupted after the next start.

The agent's result never says that an action matched the denylist, and no tool shows the denylist to the agent.

Keep your AI tool waiting during an approval

Your AI tool has its own time limit for a tool call, and an action that waits for you counts towards it. While an action waits, Athenode tells the AI tool every 15 seconds that the call is still in progress. The AI tool's own limit still applies, so set it above the approval timeout.

In Claude Code, set MCP_TOOL_TIMEOUT in milliseconds before you start it. With the approval timeout of 10 minutes, 15 minutes leaves room:

MCP_TOOL_TIMEOUT=900000 claude

For an AI tool with a fixed limit of its own, set the approval timeout below that limit. When the AI tool gives up first, the action ends as Cancelled and nothing runs.

Allow an action from now on

Always allow… approves the waiting action and saves a pattern as an allow rule of the connection, so matching actions run without asking from then on. Use it for commands you would approve every time, such as systemctl status nginx.

  1. In the session window of the waiting action, select Always allow….
  2. Read the pattern Athenode proposes. For a command it is the first word followed by *, such as df *, or the first two words for git, docker, systemctl, kubectl, apt, apt-get, npm, pnpm and yarn, such as systemctl status *. For a file tool it is the tool and the file's folder, such as read_file /var/log/nginx/*. For a cancellation it is cancel_job *.
  3. Optional: edit the pattern. Below it, "Matches this action" or "Does not match this action" says whether the pattern covers the waiting action, with the reason when it cannot.
  4. Select Always allow.

The action runs and the rule appears on the connection's Rules tab. Other actions that are already waiting stay waiting. Always allow… is not offered for an action that matches the denylist: the session window names the denylist patterns it matched.

On Athenode Pro, Always allow for you saves a personal rule that applies to your own actions only. Personal rules and the global allow rules are described on the gateway on Athenode Pro.

Add or remove allow rules of a connection

The allow rules of a connection are the patterns under which actions run without asking on that connection. Write them in advance when you know what the agent will run. On Athenode Pro you need the owner role in the project.

  1. Open the connection and its Rules tab.
  2. Under Always allow, enter a pattern at New always-allow rule, such as systemctl status *.
  3. Select Add.

To remove a rule, select its delete button. A rule that matches a file tool is tagged File. An invalid pattern is refused with the reason, such as "The pattern is longer than 1000 characters". The rules of a connection go with it when you copy it to another project, as the SSH gateway overview describes.

Write a rule pattern

A pattern is the text that an allow rule or a denylist entry matches. Allow rules and the denylist use the same patterns, in three forms. A pattern holds up to 1,000 characters.

Form Written as Matches
Command glob, the default systemctl status * The whole command. * matches any text, / included, and ? one character. Everything else is literal. A trailing * also matches the command on its own, so ls * matches ls and ls -la /etc
Regular expression /^journalctl -u [a-z-]+$/, or /…/i to ignore case Any part of the command, so anchor it with ^ and $. Backreferences and lookaround are refused
File rule read_file /var/log/** That file tool only, on the remote path. The tools are read_file, write_file, list_dir, upload and download. * matches within one folder and ** across folders. A * does not match a name that starts with a dot

Command patterns never match a file tool, and file rules never match a command. These rules decide what a command pattern is compared with:

  • Spaces between words count as one space, a leading command or \ is dropped, and /usr/bin/tail counts as tail. Leading assignments such as LANG=C are dropped too.
  • A command run with sudo is matched as sudo followed by the command. ls * does not approve ls with sudo, and sudo ls * does.
  • A command joined with &&, ||, ;, | or & is approved by allow rules only when each part matches one. cd /srv/shop && git pull needs rules for both cd /srv/shop and git pull. The commands inside $(…), <(…) and >(…) count as parts too.
  • A file path is matched as the agent gave it, with ., .. and repeated slashes resolved. A path relative to the home folder stays relative, so read_file ~/shop/* and read_file /home/deploy/shop/* are separate rules.
  • A cancellation is matched as cancel_job followed by the command of the job.

Actions that no allow rule approves

Some commands can run something that their text does not show. An action that contains one of these always waits for approval in confirm mode, whatever the allow rules say, and in auto mode it runs like any other action that is not on the denylist:

  • Backticks, $ expansions outside single quotes such as rm $FILE, heredocs, comments, line breaks and unbalanced quotes.
  • Output redirection to anything other than /dev/null.
  • A command that runs other commands: bash, sh, zsh, dash, ksh, eval, exec, xargs, env, nohup, timeout, nice, ssh, source and ..
  • find with -exec, -execdir, -ok or -okdir.
  • Setting LD_PRELOAD, LD_LIBRARY_PATH, BASH_ENV, ENV, PATH or PROMPT_COMMAND, in the command or through the action's environment.
  • A file path that climbs above its starting folder, such as ~/../../etc/shadow.

When you choose Always allow… for such an action, the pattern preview says "Does not match this action" and lists the reasons.

Edit the denylist

The denylist is the list of patterns whose actions always need approval, in auto mode and over any allow rule, and can never be always allowed. The global denylist applies to every connection of every project on the server. On Athenode Pro it belongs to the administrators.

  1. Open Settings in the sidebar, outside a project.
  2. Go to Denylist.
  3. Enter a pattern at New denylist pattern, such as terraform destroy*, and select Add. To remove a pattern, select its delete button.

A new server starts with eight patterns, tagged Default:

Pattern Catches
rm -*r* Recursive deletion with a short option, such as rm -rf
rm --recursive* Recursive deletion with the long option
mkfs* Creating a file system
dd * Raw copies to and from devices
shutdown* Shutting down
reboot* Restarting
poweroff* Powering off
halt* Halting

You can remove the default patterns like any other, and a removed one does not come back. A denylist pattern matches more widely than an allow rule. It matches each part of a command, also with a leading sudo and its options removed, and anywhere in the command at the start of a word, so rm -*r* catches bash -c "rm -rf /tmp/build". A denylist pattern can also be a file rule, such as write_file /etc/**.

Change the denylist for one connection

A connection can add patterns to the global denylist, and switch global patterns off for itself. Add patterns for a host where more commands deserve a second look, such as a production database. On Athenode Pro, adding patterns needs the owner role in the project, and switching global patterns off is for administrators.

To add a pattern for one connection:

  1. Open the connection and its Rules tab.
  2. Under Always ask, enter a pattern at New denylist addition, such as pg_dump *.
  3. Select Add.

To switch a global pattern off for one connection:

  1. On the same tab, go to Global denylist on this connection.
  2. Switch on the entry of the pattern. It shows "disabled here".

On that connection, matching actions then follow the mode and the allow rules. Other connections keep the pattern, and the connection's own additions still apply. Deleting the global pattern removes the switch with it.