autoresearch-hooks
Author pre/post-iteration hooks for an autoresearch session. Use when the user asks to add research fetching, Slack/webhook notifications, persistent learnings, auto-tagging, anti-thrash intervention, idea rotation, or any side effect around iterations.
Works with
---
name: autoresearch-hooks
description: Author pre/post-iteration hooks for an autoresearch session. Use when the user asks to add research fetching, Slack/webhook notifications, persistent learnings, auto-tagging, anti-thrash intervention, idea rotation, or any side effect around iterations.
license: MIT
---
# autoresearch-hooks
Optional scripts that run at iteration boundaries in an autoresearch session. Two hooks, both transparent to the loop-running agent — their effect is a file on disk or a steer message.
```
.auto/hooks/
before.sh # fires before each iteration (prospective)
after.sh # fires after each log_experiment (retrospective)
```
Both files are optional. Files without the executable bit are silently ignored.
---
## Contract
### Stdin — `before.sh`
One JSON line. Parse with `jq`. Realistic example:
```json
{
"event": "before",
"cwd": "/path/to/workdir",
"next_run": 6,
"last_run": {
"run": 5,
"status": "discard",
"metric": 42.1,
"description": "Simplified to sorted(arr) — copy cost dominates",
"asi": {
"hypothesis": "Built-in sort avoids Python overhead",
"next_focus": "list copy avoidance"
}
},
"session": {
"metric_name": "total_ms",
"metric_unit": "ms",
"direction": "lower",
"baseline_metric": 40.7,
"best_metric": 33.5,
"run_count": 5,
"goal": "optimize sort speed"
}
}
```
| Field | Notes |
| ------------------------- | ------------------------------------------------------------------- |
| `last_run` | The most recent run entry. `null` on a fresh session. |
| `session.direction` | `"lower"` or `"higher"` — which end of the scale wins. |
| `session.baseline_metric` | First run of the current segment. `null` until one run exists. |
| `session.best_metric` | Optimal metric across **kept** runs only. `null` until one is kept. |
| `session.goal` | The session name set by `init_experiment`. |
| `session.run_count` | Total runs logged so far (any status). |
### Stdin — `after.sh`
```json
{
"event": "after",
"cwd": "/path/to/workdir",
"run_entry": {
"run": 6,
"status": "discard",
"metric": 38.9,
"description": "Timsort hybrid slower on random",
"asi": {
"hypothesis": "Partial-sort heuristic on input distribution",
"learned": "Overhead dominates on random arrays"
}
},
"session": {
"metric_name": "total_ms",
"metric_unit": "ms",
"direction": "lower",
"baseline_metric": 40.7,
"best_metric": 33.5,
"run_count": 6,
"goal": "optimize sort speed"
}
}
```
| Field | Notes |
| ----------- | ------------------------------------------------------------- |
| `run_entry` | The run just logged. Always present. |
| `session` | Same shape as in `before.sh`, reflecting state after the run. |
### Output
- **Stdout** (up to 8 KB) — delivered to the agent as a steer message on the next turn. Empty = silent.
- **Stderr + non-zero exit** — surfaced as an error steer.
- **Timeout** — 30 s hard kill; flagged in the observability entry.
### Preservation
`.auto/**` survives the auto-revert — the entire `.auto/` folder is preserved. (Legacy `autoresearch.*` paths are still preserved too, for in-flight sessions.)
---
## Examples
Runnable reference scripts live in this skill's `examples/` directory — one file per pattern. Paths are resolved against the skill directory (parent of SKILL.md). Browse them for inspiration; they're not policy.
- `examples/before/` — external search, qmd document search, anti-thrash, idea rotator, hypothesis reflection, context rotation
- `examples/after/` — learnings journal, macOS notification on new best, auto-tag winning commits
Each example is a complete, self-contained script with named constants, short helper functions, guard clauses, and intention-revealing names. Read the header comment for its purpose, copy to `.auto/hooks/<stage>.sh`, adapt.
---
## Steps to add a hook
1. **Understand the session.** Read `.auto/prompt.md` for the objective and metric; glance at `.auto/measure.sh` for the workload. Your hook should complement the loop, not duplicate it.
2. **Clarify the user's intent.** What should happen, at which boundary? Research before / log after / notify on wins / intervene on thrash / etc.
3. **Start from an example in `examples/`** that's closest to the intent (resolve against the skill directory). If nothing fits, write from scratch following the same style (named constants, short functions, guard clauses, JSON stdin parsed with `jq`). If the request combines retrospective + prospective concerns, use both `before.sh` and `after.sh` — don't overload one.
4. **Copy, adapt, mark executable.**
```bash
mkdir -p .auto/hooks
cp "<skill-dir>/examples/before/external-search.sh" .auto/hooks/before.sh
# ... adapt the script ...
chmod +x .auto/hooks/before.sh
```
5. **Sanity-test with a piped mock** before relying on it in the loop:
```bash
jq -n '
{
event: "before",
cwd: ".",
next_run: 1,
last_run: null,
session: {
metric_name: "total_ms",
metric_unit: "ms",
direction: "lower",
baseline_metric: null,
best_metric: null,
run_count: 0,
goal: "test"
}
}
' | ./.auto/hooks/before.sh
```
For `after.sh`, swap `last_run: null` for a `run_entry` object (see the schema above).
6. **Commit the hook** alongside other session files. It's preserved across reverts because it lives under `.auto/`.
---
## Rules of thumb
- **Read whatever fields the agent naturally writes** — `asi.hypothesis`, `asi.next_focus`, `asi.learned`, `description`. Don't invent a "hook input" field and instruct the agent to populate it; that breaks the transparency principle.
- **Silent is the default.** Only print to stdout when you have something useful for the agent. Empty stdout means no steer.
- **Guard with early exits.** `[ -z "$query" ] && exit 0` is cheaper and clearer than wrapping everything in `if`.
- **One concern per script.** If you want research + learnings, put them in separate files (`before.sh` and `after.sh`). Don't bundle.
- **No environment variables.** Everything is on stdin; extract `cwd` (and anything else) with `jq`. There is no `$AUTORESEARCH_WORK_DIR`.More API Design skills
lark-event
larksuite/cli
Lark/Feishu real-time event listening / subscribing / consuming: stream events as NDJSON via `lark-cli event consume <EventKey>` (covers IM messages/reactions/chat changes, Approval status changes, Task updates, VC meeting started/joined/ended, Minutes generated, Whiteboard updated, etc.). Use for Lark bots, real-time message processing, long-running subscribers, streaming webhook/push handlers. Supports `--max-events` / `--timeout` bounded runs and a stderr ready-marker contract — designed for AI agents running as subprocesses.
lark-contact
larksuite/cli
飞书 / Lark 通讯录:按姓名 / 邮箱解析成 open_id,或按 open_id 反查姓名 / 部门 / 邮箱 / 联系方式 / 个人状态 / 签名,以及按关键词搜索当前用户可见的机器人 / 智能体(agent)。当用户提到一个名字要下一步发消息 / 排日程,或拿到 open_id 想查具体信息时使用。不负责部门树遍历、按部门列员工、组织架构图,这类需求走原生 OpenAPI。
lark-openapi-explorer
larksuite/cli
飞书/Lark 原生 OpenAPI 探索:从官方文档库中挖掘未经 CLI 封装的原生 OpenAPI 接口。当用户的需求无法被现有 lark-* skill 或 lark-cli 已注册命令满足,需要查找并调用原生飞书 OpenAPI 时使用。

