Co Inbox logo

Co Inbox

OrganizationPopular
openonion
co-inbox

Drive `co feishu` / `co lark` — a chat bot as a directory of files. Use when an agent must receive messages from a Feishu or Lark group, reply to them, or run a command per message. Covers setup by QR, the nine verbs, the queue's guarantees, and every exit code.

Overview

Publisheropenonion
Repositoryconnectonion
Skill nameco-inbox
Stars
1.5K
Forks
218
Bundled files
Instructions only
LicenseApache-2.0
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • Self-contained

    Everything the model needs lives in the instructions — no extra files to sync.

  • Open source

    Published by openonion on GitHub. Read the source before you install it.

Installation

Install the Co Inbox AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/openonion/connectonion.git /tmp/connectonion
mkdir -p .claude/skills
cp -r /tmp/connectonion/connectonion/useful_skills/co-inbox .claude/skills/co-inbox
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Co Inbox in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Co Inbox on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Co Inbox is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

The inbox

A Feishu or Lark bot, as a directory. One process writes messages into it; you read them. Nothing here knows what an agent is.

Always read the output, not just the exit code. listen prints nothing on a clean hour, and consume runs commands whose own failures it reports on stderr while continuing.

Which command

you want torun
set it up, from nothingco auth feishu
set it up, reusing a bot you already haveco auth feishu --app-id cli_…
check it is configuredco feishu check
take the next message and act on it yourselfco feishu receive
run a program for every message, foreverco feishu consume -- <command>
answer a message you tookco feishu reply <id> "text"
decide not to answer oneco feishu done <id>
send without being askedco feishu send <chat> "text"
see what is waitingco feishu ls
watch it workco feishu log -f
hold the connection yourselfco feishu listen

co lark … is the same nine verbs against Lark. Pick by where your bot lives; the credentials are separate (FEISHU_APP_* and LARK_APP_*).

The 80%

bash
co auth feishu                      # scan the QR; the app exists, keys saved
co feishu check                     # names what is still missing, if anything
# add the bot to a group and @ it
co feishu ls                        # what is waiting
m=$(co feishu receive)              # take one; blocks until there is one
echo "$m" | jq -r .text
co feishu reply "$(echo "$m" | jq -r .id)" "on it"

Or hand every message to a program and let it loop:

bash
co feishu consume -- claude -p      # its stdout becomes the reply
co feishu consume -- codex exec -
co feishu consume -- ./answer.sh

consume gives the command the message JSON on stdin and these variables: CO_PROVIDER, CO_CHAT, CO_THREAD, CO_SENDER, CO_MSG_ID, CO_CHAT_DIR.

The message

Seven fields, identical on every provider:

json
{"id":"om_9f8e","chat":"oc_a1b2","thread":null,"sender":"on_7c6d",
 "text":"look at today's failed deploys","mentioned":true,"at":"2026-09-02T10:31:07Z"}

chat is where a reply goes. id is all reply needs — it looks up the chat and thread itself. The provider's own payload is not included unless the listener was started with --raw, so contact names and group titles never reach a prompt by accident.

Gotchas that change what you report

  • Taking a message is a claim, and claims expire. receive moves the file from new/ to cur/. If you neither reply nor done within an hour, it goes back to new/ and somebody else gets it. A long job is fine — consume renews the claim while your command runs — but a script that takes a message and then sleeps is not.
  • done is not optional. A message you decided to ignore stays claimed until it expires, then comes back. done <id> is how you say the silence was deliberate.
  • A reply happens once. reply <id> refuses a second reply to the same id; --again is the override. Feishu also dedupes on its side for an hour.
  • Two consumers never get the same message, because taking one is rename(2). Running two is safe and is how you scale; the loser just gets the next one.
  • listen is the only writer and there is one of it. A second listen on the same directory exits 1 rather than competing. receive and consume start one in the background if none is running.
  • Nothing is deleted. received.jsonl keeps every message forever, so grep is your history and disk is your limit.
  • --json is not a flag here. Every verb that returns data already prints one JSON object per line.

Where it lives

text
~/.co/inbox/feishu/          # $CO_INBOX_HOME moves the whole root
├── received.jsonl           # every message, appended
├── sent.jsonl               # every reply, and every send that failed
├── done.jsonl               # what was deliberately not answered
├── new/  cur/               # the queue, and what is claimed
└── log                      # connected, reconnecting, send failed

ls new/ is the unread count. tail -f received.jsonl is a live view. You do not need any command in this skill to read it.

Exit codes

exitmeansrun next
0it workedthe tip the command printed
1the platform refused, or a listener is already runningco feishu log
2wrong argumentsco feishu <verb> --help
3not configuredco auth feishu
124receive waited and no message cameco feishu ls

Every one of these prints a line naming the command to run next. A refusal that names no command is a bug — report it rather than guessing.

When it is not set up

co feishu check exits 3 and names each missing piece. The usual answer is co auth feishu: it creates the application by QR and writes both values. If the bot already exists and is already in the groups you need, co auth feishu --app-id cli_… authorizes that one instead, keeping its groups and permissions — a freshly created application is in no group at all.

listen additionally needs the SDK, and says so: pip install lark-oapi.

What this does not do

It does not decide who may command an agent. Anything that can read a file can read this directory, and the only filter the tool applies is the platform's own — a group message must @ the bot. Sender allowlists belong to whatever consumes the directory.

It does not recover a gap without the scope for it. History recovery reads back what arrived while the listener was down, and that needs the bot scope im:message.group_msg. Without it every pass fails, the checkpoint is held rather than advanced, and co <provider> check exits 1 and prints a link that grants it — so check that before reporting a gap as message loss. Measured on a live tenant 2026-09-15: with the scope, a message posted during a 90-second gap was recovered and queued exactly once.

It does not recover a conversation this inbox has never seen. Recovery reconciles only chats already in received.jsonl, and in a group it admits only messages that mention the bot — unrelated discussion during a gap is dropped on purpose, not lost.

Frequently asked questions

What does the Co Inbox AI skill do?

Drive `co feishu` / `co lark` — a chat bot as a directory of files. Use when an agent must receive messages from a Feishu or Lark group, reply to them, or run a command per message. Covers setup by QR, the nine verbs, the queue's guarantees, and every exit code.

Why use Co Inbox on TypingMind?

Because you install it once and use it with any model. Co Inbox is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Co Inbox in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/openonion/connectonion/tree/main/connectonion/useful_skills/co-inbox. TypingMind reads its SKILL.md and installs it as a skill you can enable per chat.

Which AI models can use Co Inbox?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Co Inbox?

As many as you like. As long as a model supports skills, you can use Co Inbox with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Co Inbox AI skill free?

Yes. It is published on GitHub by openonion under the Apache-2.0 license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇