An agent that keeps this workspace's written record: it files notes under okf/issues/,
searches them to answer questions, and every change it makes is a git commit you can
revert. No Slack, Telegram, or email credentials — just Claude auth.
Run it
# 1. Claude auth (either one)
claude login # or: export ANTHROPIC_API_KEY=...
# 2. Copy the example into the workspaces home and make it a repo
mkdir -p ~/openstation && cp -r examples/notes-agent ~/openstation/notes
git -C ~/openstation/notes init -q .
# 3. Talk to it — a bare name resolves under ~/openstation
openstation notes dev
Then try:
you> we decided to use interval schedules instead of cron — write that down
you> what did we decide about scheduling?
you> run the stats tool
git log shows what it wrote — each turn that changes okf/ becomes a commit — and
git revert HEAD undoes it. Platform state under var/ is never committed, even though the
event log is written there during the same turn.
What each file is for
| Path | Whose file | Why it's here |
|---|---|---|
.openstation/openstation.yaml |
ours | management overlay: identity, executor, which settings file enforces it, channel membership. It references the Claude-native files and never restates their contents. |
.openstation/profiles/{member,admin}.md |
ours | per-role addendum layered on the charter. A role with no file here is refused, not silently downgraded. |
.claude/agents/notes.md |
Claude Code's | the charter. Deliberately carries no tools: field — the settings gate below is the sole narrowing; a curated list here would have to be hand-synced forever or silently void a grant. |
.claude/settings.notes.json |
Claude Code's | the enforced gate. Writes are scoped to Edit(okf/**)/Write(okf/**); var/ is denied so the agent can't read the platform's own state. |
.claude/skills/note/SKILL.md |
Claude Code's | teaches the note format. Claude discovers skills itself; the platform never reads this. |
tools/stats.py |
yours | proof that agent tools are any language: the platform is TypeScript, this is Python, reached as a subprocess. |
okf/issues/, okf/index.md |
the agent's | the artifact zone — the only place it may write. |
Things worth noticing
The gate is Claude's, not ours. Ask it to read .env and it refuses, citing
settings.notes.json — not because the platform filtered a list. One enforcement source of
truth. Worth knowing exactly how strong that is: enforcement happens inside Claude's
decision loop, so a deny entry is a strong default, not a hard boundary. Anything that
must never happen needs a PreToolUse hook or OS-level permissions behind it. (This agent
worked that out and filed it as a note on its first run.)
Writes are reversible by construction. Turn on autoCommit and every turn that changes
okf/ becomes a commit. Nothing outside the artifact zone is ever staged, even when it
isn't gitignored.
Add a second agent with no code:
openstation notes agents add reviewer --channel review
That writes a manifest entry plus its own .claude/agents/reviewer.md and
settings.reviewer.json. Note the current limit: agent selection resolves once at
startup, so one process serves one agent — per-message channel routing is not wired yet
(see docs/internal/roadmap.md, "Known gaps to v1").
Making it answer on Slack or Telegram
export SLACK_BOT_TOKEN=... SLACK_APP_TOKEN=... # or TELEGRAM_BOT_TOKEN=...
openstation notes serve
Connectors start from credential presence — secrets stay in the environment and never
enter openstation.yaml. Both transports are verified against fakes; neither has been run
against a live workspace yet.