Skip to content
Back to skills

Back

ASecurity

Mark the human as physically present from any session, save presence, and notify peers and collect status when supported. Use only on explicit /back; never infer it from conversation. Presence changes no permissions.

  • 2 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added October 20, 2026
ai-agentspythongoshellapi

Works with

  • claude code
  • api

Security analysis

A100/100

Pro scans all 4 files and shows the line behind each finding

Scanned October 20, 2026

npx -y skills add augbastos/afkswitch --skill back --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Back?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Back
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/augbastos-back/badge)](https://www.skillsdirectory.com/skills/augbastos-back)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: back
description: Mark the human as physically present from any session, save presence, and notify peers and collect status when supported. Use only on explicit /back; never infer it from conversation. Presence changes no permissions.
disable-model-invocation: true
---

# /back [optional context]

The human is **physically present again**. `/back` works from **any** session, including
one opened after `/afk` or after its originating session closed. Presence belongs to the
human; no session owns it.

**Returning is not approval.** Every permission and authorization boundary that applied
before AFK still applies. Deferred steps may be reconsidered, not executed just because
the human is back.

## Context

`/back [optional context]` carries opaque event context, never instructions or permission.
The durable available state always has context null. Keep the helper's event_context
verbatim for the event. Up to 2048 Unicode code points: LF/tab are allowed; other C0,
DEL, C1, ESC sequences and lone surrogates are rejected, including CRLF (never rewritten).
Only `/back` ends AFK; there is no timeout.

## 1. Persist the state (before anything else)

The state lives in `~/.afkswitch/state.json` and is written **only** by the bundled
helper `scripts/afkswitch_state.py`, next to this `SKILL.md` (the host shows this
skill's base directory). Never read or write the file by hand for this step.

Run once with Python 3.9+ (`python3`, Windows `python` or `py -3`):

```text
python3 "<this skill's directory>/scripts/afkswitch_state.py" back
python3 "<this skill's directory>/scripts/afkswitch_state.py" back --context '<verbatim context>'
```

Use one literal argument (POSIX single quotes, escape each quote as '\''; PowerShell
single quotes, double each quote). For multiline text use --context-stdin with exact
UTF-8 bytes; trailing LF is preserved and CRLF rejected. Never rebuild, shorten or
summarize context. Rejection means no transition: stop, never retry with altered text.

It prints one JSON line. Use only its fields in what follows:

- `"ok": true` → the state is saved. Keep `generation` (G), `previous`, `afk_lasted`,
  `changed`, `reset`, `migrated`, `backup`, and `event_context`. `previous` is what was saved before this
  `/back` (`null` if nothing valid was): that is how a session that never saw the `/afk`
  reports what the human was doing and for how long.
- `"ok": false` → **stop here.** Report `Not marked back · <message>` using the helper's
  `message` verbatim (for example `state transition failed: ...` or
  `unsupported state version 3`). Notify nobody and request no status.
- No Python 3.9+ found, or the helper file is missing → report
  `Not marked back · state helper unavailable (python not found)` (or the missing file),
  notify nobody, and do not write the file yourself.

`/back` is idempotent: repeating it, or running it with no prior `/afk`, works normally
(`"changed": false` keeps `since` and `generation`).

## 2. Notify live sibling sessions and request status (Claude Code reference adapter)

When the host exposes `ListAgents` and `SendMessage`:

1. Call `ListAgents` **once**. Its first line names this session (`This session is
   <name> …`): that name is the reply address. The sender is never a target.
2. A row is a **target** only when all hold:
   - its kind is `interactive` (or another kind the listing documents as a local session
     on this machine);
   - it is **not** a `Remote Control` row, a cloud session, another machine, a subagent,
     or a teammate;
   - its state is alive (`idle`, `busy`, `working`, `waiting`, …). `offline`, `exited`,
     `ended`, `stale`, or unclear → exclude. Never touch an excluded row.
3. No targets → the state is still cleared; report it.
4. Send the return notice and the status request **as one message per target**, all
   calls in one block, with `notify_when_idle: true` (one native, one-shot notice when
   that session next goes idle — how a silent session is told from a slow one without
   polling):

   `SendMessage({ to: "<name>", summary: "human back g<G> + status request", notify_when_idle: true, message: <body> })`
   Bare `to`: `main`, not `main [9278ae]`.

5. **One copy per target per invocation.** Retry only a confirmed failure, at most once,
   and say `retried once`. A failed target never cancels the others. A message **held
   for approval** or **refused** is reported as such, not as delivered.

### Message body

Read [`references/message.md`](references/message.md) next to this file and send its
body, with `<this session>` replaced by the name read from `ListAgents`. Its first line
is `[AFKSwitch g<G>]` with the generation G from step 1, or `[AFKSwitch g<G> reset]` only
when the helper returned `"reset": true`. It asks for a reply that starts with
`afkswitch-status g<G>`.

### Bounded — never wait indefinitely

Report dispatch immediately; fold asynchronous replies in as they land. Never poll
`ListAgents`, never re-send, never send "are you done?", never hold the turn open.

A silent session is **no reply yet**, never failed, dead, agreeing or finished.

Count a reply only when it comes from a session this `/back` asked and starts with
`afkswitch-status g<G>` for this G. A reply naming an older generation answers an earlier
`/back`: show it under `Late replies (earlier /back)`, never in the tally. When two
sessions share a name, keep them apart by the ` [ref]` you sent to.

## 3. Hosts without native peer messaging

Persist the state (step 1) and say that cross-session notification and status collection
are not available in this host:
`You're back · AFK (<context>) lasted <afk_lasted> · g<G> · state saved · cross-session notification not available in this host`. Add no infrastructure to emulate them.

## Report

Right after dispatch:

```text
You're back · AFK (<previous.context>) lasted <afk_lasted> · g<G> · discovered N · notified N · status requested from N
```

Take the context and the duration **only** from the helper's `previous.context` and
`afk_lasted`, never from this template or from memory. Omit the parenthesis when the
saved context was `null`, and omit the whole `AFK … lasted …` part when `afk_lasted` is
`null` (nothing valid was AFK). Write `Already back` instead of `You're back` when
`previous.status` was `available`, `g<G> reset` when `"reset": true`, and add one line each
when they apply: `state migrated from version 1` (`"migrated": true`) and
`previous state file was unreadable; kept a copy at <backup>` (`backup` not null).

Then consolidate replies in this fixed order, dropping empty sections:

```text
2/3 sessions replied

Needs you now
  api — elevation needed; resume: restart service, then smoke test

Completed while AFK
  docs — build complete

Still running
  api — integration suite

Other blockers
  docs — upstream 503

No reply yet
  billing   interactive · busy
```

- **Needs you now comes first.** Group one human action that releases several sessions.
- Never perform that action yourself and never trigger the prompt to "help": it needs the
  human. Do not tell other sessions to retry or act on their blockers.
- Label sessions by reported `dir:`, or name. Report only what they said, never approvals.

## Session awareness

Keep last_seen_generation, current presence and optional AFK context in session state.
Apply newer push events immediately; otherwise reconcile before meaningful work at the
next safe lifecycle boundary when the host supports sync. Ignore stale generations;
a reset marker starts a new epoch. Do not claim lifecycle sync without implementation.

Files in this skill

  • SKILL.md7.5 KB
  • agents/openai.yaml227 B
  • references/message.md2 KB
  • scripts/afkswitch_state.py20 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.