Official agent skill

Thinking In Boc

by microsoft in microsoft/bocpy

Think in Behavior-Oriented Concurrency, not threads-and-locks.

OfficialMITAuto-check passedDevelopment

Install Thinking In Boc

skills CLI
$ npx skills add microsoft/bocpy --skill thinking-in-boc -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install microsoft/bocpy thinking-in-boc --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/microsoft/bocpy.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.github/skills/thinking-in-boc .claude/skills/thinking-in-boc && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
thinking-in-boc
GitHub stars
201
Token cost
~2.6k tokens
SKILL.md length
1,214 words
Files
1
Skills in repo
9
Repo updated
First seen
Licence
MIT

At a glance

Think in Behavior-Oriented Concurrency, not threads-and-locks.

  • Works in 6 steps: Sequencing on data — @when(cown) → Fan-in / barrier — @when(cowns) vs… → Happens-after — chain on the prior… → …
  • Reviewing any bocpy code (library
  • SKILL.md covers The smells, The replacements, The BOC checklist and When the classical answer is…, plus 1 more section
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

Thinking In Boc is an agent skill from microsoft/bocpy, published by the product's own GitHub organization. Think in Behavior-Oriented Concurrency, not threads-and-locks. Use when: writing or reviewing any bocpy code (library, examples, tests), about to reach for time.sleep / threading.Event / atomic counters / polling loops / waitfor helpers, designing how a downstream behavior observes an upstream one, scheduling work to run after the next worker is free, or building loop / tail-recursion patterns. Catches the reflex to apply classical synchronization to a problem that wants a cown.

Its SKILL.md is about 2.6k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Development. The repository describes itself as: Behavior-Oriented Concurrency in Python. The licence is MIT.

When your agent uses it

  • Reviewing any bocpy code (library
  • About to reach for time.sleep / threading.Event / atomic counters / polling loops / waitfor helpers
  • Designing how a downstream behavior observes an upstream one
  • Scheduling work to run after the next worker is free

Example prompts

  • “/thinking-in-boc”

Requirements

  • Python 3

Workflow steps

6 steps, taken from the step headings in SKILL.md.

  1. Sequencing on data — @when(cown)
  2. Fan-in / barrier — @when(cowns) vs @when(a, b, c)
  3. Happens-after — chain on the prior behavior's result cown
  4. Run when any worker is free — @when()
  5. Behavior loops — tail-recursive self-scheduling
  6. Single-assignment rendezvous — the behavior's own result cown

What it can do on your machine

Read from SKILL.md and the folder at commit c8f3ceb. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are python).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Thinking In Boc loads about 2.6k tokens when it runs. Until then it costs about 126 tokens; SKILL.md has 1,214 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~126
When it runs · the whole SKILL.md, loaded when a task matches
~2.6k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from microsoft/bocpy at commit c8f3ceb, republished under its MIT licence (© microsoft). 1,214 words, ~2,569 tokens.

Download SKILL.mdSave it as .claude/skills/thinking-in-boc/SKILL.md (or your agent's skills folder).
name
thinking-in-boc
description
Think in Behavior-Oriented Concurrency, not threads-and-locks. Use when: writing or reviewing any bocpy code (library, examples, tests), about to reach for time.sleep / threading.Event / atomic counters / polling loops / wait_for_* helpers, designing how a downstream behavior observes an upstream one, scheduling work to run after the next worker is free, or building loop / tail-recursion patterns. Catches the reflex to apply classical synchronization to a problem that wants a cown.

Thinking in Behavior-Oriented Concurrency

This skill is a corrective. The default reflex when synchronizing concurrent work is to reach for threads-and-locks primitives: shared state, a mutex, a condition variable, a busy-wait loop, an atomic counter, an event flag, a Future. In BOC, those answers are almost always wrong — not because they break, but because they bypass the very mechanism that makes BOC safe and fast.

The BOC question is not "what synchronization primitive do I need here?"

It is: "what cown is this work ordered against, and what behavior should run when that cown is free?"

Read this skill any time you catch yourself writing one of the smells below.

The smells

If you find yourself typing any of these inside, or in code that interacts with, a BOC program — stop and re-derive the design.

SmellWhat you almost certainly meant
time.sleep(...) in a polling loopSchedule a behavior on the cown the predicate depends on.
while not <flag>: ... busy-waitSame — make <flag> a cown and @when(flag) a behavior.
threading.Event / Condition / LockA cown plus a behavior chain.
wait_for_<x>_version(target) polling@when(downstream_cowns) — let the cown graph order it.
atomic_counter from PythonA Cown(int) mutated inside @when(counter).
Future, Queue.get(), "ferry one value out"return the value from a behavior; @when(that_behavior) reads it.
time.sleep(0) "yield"@when() — the empty-cown behavior runs when a worker is free.
if work_remaining: do_work(); else: stop in a thread loopA behavior loop: the behavior re-schedules itself with @when(state) on the same cown until done.

The smells are signals that you are managing concurrency outside the runtime. The runtime cannot help you make that correct or fast.

The replacements

There are only a handful of BOC patterns. Almost every problem decomposes into one of them.

1. Sequencing on data — @when(cown)

A behavior runs when its cowns are free. That is the entire ordering mechanism. If step2 must observe step1's effect on x, both behaviors take x:

python
@when(x)
def step1(x):
    x.value = "ready"

@when(x)
def step2(x):
    assert x.value == "ready"

You did not need a lock. You did not need an event. You did not need to poll. The runtime acquired x for step1, released it, and only then gave it to step2.

2. Fan-in / barrier — @when(cowns) vs @when(a, b, c)

There are two distinct shapes for "this behavior depends on multiple cowns" and choosing the right one matters.

Use @when(a, b, c) — separate positional arguments — when you know at write-time exactly which cowns the behavior needs and they have distinct roles. The decorated function takes one named parameter per cown:

python
@when(account_a, account_b)
def transfer(src, dst):                     # two roles, two names
    dst.value += src.value
    src.value = 0

Use @when(cowns) — a single list/tuple argument — when the set is dynamic or homogeneous (its size is determined at runtime, or the cowns play the same role). The decorated function takes one parameter which is the list itself:

python
cowns = [Cown(i) for i in range(N)]
for c in cowns:
    @when(c)
    def producer(c):
        ...                                 # writes whatever it writes

@when(cowns)                                # one list arg, not *cowns
def consumer(cowns):
    total = sum(c.value for c in cowns)     # cowns IS the list

This is the classical N-way barrier, expressed as data dependence: the runtime acquires every cown in the list before the behavior runs, so the consumer cannot start until every producer behavior has returned. Do not spread the list with * — @when accepts the list directly, and spreading would force you to know N at write-time, defeating the point.

Mixing the two forms — @when(anchor, cowns) — is also valid: the behavior takes one named parameter (anchor) plus one list parameter.

3. Happens-after — chain on the prior behavior's result cown

@when returns a Cown holding the behavior's result. Pass that cown to a later @when to enforce happens-after across unrelated data:

python
@when(x)
def writer(x):
    x.value = compute()

@when(y, writer)                            # y is unrelated; writer is the result cown
def reader(y, w):
    consume(y.value, w.value)               # runs only after writer finished

Here reader touches its own data (y) and would otherwise be free to run concurrently with writer. Depending on the writer result cown is what serializes them: the runtime cannot acquire writer until that behavior has returned, so reader sees its result via w.value.

4. Run when any worker is free — @when()

@when() with no arguments schedules a behavior with no data dependencies. It runs as soon as a worker is available. Use this when you want some work to happen in the background and you do not need to coordinate with any particular cown — for example, sending a report after forks have been released:

python
@when(left, right, hunger)
def take_bite(left, right, hunger):
    left.value.use(); right.value.use()
    hunger.value -= 1
    if hunger.value == 0:
        # forks released when this behavior returns; the report goes
        # out from a fresh behavior so it does not delay the release.
        @when()
        def _():
            send("report", ("full", index))

@when() is also the BOC equivalent of "tail-call this on the worker pool" — it lets the current behavior return promptly while the follow-up work waits its turn.

Show full SKILL.md (530 more words)Show less
5. Behavior loops — tail-recursive self-scheduling

To process work in chunks until done, do not write a while loop inside one behavior — that pins one worker for the duration. Instead, the behavior does one chunk and then schedules the next iteration on the same cown:

python
def step(state: Cown[State]):
    @when(state)
    def _(state):
        if state.value.done:
            send("done", state.value.result)
            return

        state.value.do_one_chunk()
        step(state)                         # tail-schedule next iteration

This is the BOC analogue of tail recursion. Each iteration releases the cown between chunks, so:

  • other behaviors waiting on state can interleave between iterations,
  • the worker is returned to the pool between chunks, and
  • work is naturally bounded by data availability — no busy-wait.

prime_factor.py (sieve_check → sieve_work → sieve_check) is the canonical example in this repository.

6. Single-assignment rendezvous — the behavior's own result cown

@when returns a Cown holding whatever the behavior returns. That cown is your rendezvous — there is no need to allocate a separate Cown(None) and assign into it:

python
@when(x)
def compute(x):
    return expensive(x.value)               # the result lives in `compute`

@when(compute)
def consume(result):                        # result is a Cown
    send("answer", result.value)            # unwrap with .value

This replaces Future / Queue for one-shot results. For streaming use the message queue (send / receive) directly.

The BOC checklist

Before writing any synchronization, ask:

  1. What cown does this work depend on? If the answer is "none" you may want @when(). If the answer is "X" you want @when(X). If you know at write-time exactly which cowns you need, prefer the explicit form @when(X, Y, Z) — it is faster than the list form because the runtime can resolve each dependency by position rather than iterating a sequence. Only fall back to @when([X, Y, Z]) (one list arg) when the set is dynamic or homogeneous.
  2. Who reads my output? Their @when(...) should include the cown I wrote to, or my behavior's result-cown.
  3. Am I about to loop in one behavior? If the loop body has any release-friendly point, lift it into a behavior loop (pattern 5) so other work can interleave.
  4. Am I about to poll, sleep, or block? Find the cown the predicate depends on. Make the polling code a behavior on that cown.
  5. Am I about to use a threading.* primitive inside a behavior? Almost certainly the wrong layer. Threads-and-locks primitives belong only at the BOC runtime boundary (test setup, wait(), receive() for assertions, the runtime's own internals).

When the classical answer is right

Classical synchronization is correct in three places:

  1. Outside the runtime, talking to it. The test thread blocking on receive("assert") for assertion messages is a thread-level wait, and that is fine — it is the boundary between the test harness and the behavior graph.
  2. wait() itself. The library uses condvars internally to block the main thread until the runtime drains. Do not reinvent this.
  3. C-level runtime internals. _core.c uses mutexes and condvars because it implements BOC. User Python code should not.

If you are not in one of those three places and you are reaching for a classical primitive, walk back through the checklist.

Self-correction prompt

If you have already written code that uses time.sleep, wait_for_*, an event flag, or a polling loop in a behavior or in code that schedules behaviors, treat it as a defect. Ask:

Which cown carries the dependency I am polling on? Why is the consuming work not a behavior on that cown?

Rewrite to remove the classical primitive. The result is almost always shorter, faster, and provably free of races.

© microsoft, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .github/skills/thinking-in-boc of microsoft/bocpy.

Open the folder on GitHubat commit c8f3ceb

Compare with similar skills

Thinking In Boc next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Thinking In Boc compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Thinking In Boc this skillmicrosoft/bocpy201—~2.6kAutomated safety check: PassMIT
Vercel Composition Patternssupabase/supabase111k59 repos~726Automated safety check: PassMIT
Finishing a Development Branchobra/superpowers296k5 repos~1.9kAutomated safety check: PassMIT
Typescript Advanced Typesrolling-scopes/rsschool-app10k25 repos~4.2kAutomated safety check: PassMPL-2.0
PR Babysitteropeninterpreter/openinterpreter69k3 repos~4.2kAutomated safety check: PassApache-2.0
Code Review ChecklistshareAI-lab/learn-claude-code78k5 repos~1.1kAutomated safety check: PassMIT

Similar skills

  • Official

    React composition patterns that scale. An agent skill from supabase/supabase.

    111k GitHub starsUsed in 59 repos~726 tokens
    DevelopmentAuto-check passed
  • Walks the last step of a branch: confirm tests pass, detect the git environment, ask how to integrate, carry out your choice and clean up the worktree.

    296k GitHub starsUsed in 5 repos~1.9k tokens
    DevelopmentAuto-check passed
  • Typescript Advanced Types

    rolling-scopes/rsschool-app

    Master TypeScript's advanced type system including generics, conditional types, mapped types, template literals, and utility types for building type-safe applications.

    10k GitHub starsUsed in 25 repos~4.2k tokens
    DevelopmentAuto-check passed
  • PR Babysitter

    openinterpreter/openinterpreter

    Watches an open GitHub pull request until it merges, handling review comments, diagnosing CI failures and retrying flaky checks along the way.

    69k GitHub starsUsed in 3 repos~4.2k tokens
    DevelopmentAuto-check passed
  • Code Review Checklist

    shareAI-lab/learn-claude-code

    Reviews code against a five-part checklist covering security, correctness, performance, maintainability and testing, and reports findings in a fixed format.

    78k GitHub starsUsed in 5 repos~1.1k tokens
    DevelopmentAuto-check passed
  • Greploop

    onyx-dot-app/onyx

    Iteratively improves a PR (GitHub), MR (GitLab), or shelved changelist (Perforce) until Greptile gives it a 5/5 confidence score with zero unresolved comments.

    32k GitHub starsUsed in 4 repos~3.3k tokens
    DevelopmentAuto-check passed

More from microsoft/bocpy

All 9 skills in this repo
  • Branch Review

    microsoft/bocpy

    Official

    Multi-perspective code review for a branch before merging. An agent skill from microsoft/bocpy.

    201 GitHub stars~3.2k tokensUpdated 10 days ago
    Auto-check passed
  • Official

    Write a C extension whose custom types can live inside a bocpy Cown and travel between worker sub-interpreters.

    201 GitHub stars~5.1k tokensUpdated 10 days ago
    Auto-check passed
  • Official

    Follow bocpy commenting and documentation conventions. An agent skill from microsoft/bocpy.

    201 GitHub stars~3.3k tokensUpdated 10 days ago
    Auto-check passed
  • Finalize PR

    microsoft/bocpy

    Official

    Finalize a feature branch for merge. An agent skill from microsoft/bocpy.

    201 GitHub stars~3.5k tokensUpdated 10 days ago
    Auto-check passed
  • Multi Perspective Plan

    microsoft/bocpy

    Official

    Multi-perspective planning with rebuttal rounds and adversarial review loop.

    201 GitHub stars~2.8k tokensUpdated 10 days ago
    Auto-check passed
  • Testing Message Queue

    microsoft/bocpy

    Official

    Write tests for the bocpy message queue — the lock-free tag-based MPSC ring buffer.

    201 GitHub stars~2.3k tokensUpdated 10 days ago
    Auto-check passed

Categories

Questions about Thinking In Boc

What does Thinking In Boc do?

Think in Behavior-Oriented Concurrency, not threads-and-locks. Thinking In Boc is an agent skill from microsoft/bocpy, published by the product's own GitHub organization. Think in Behavior-Oriented Concurrency, not threads-and-locks.

When should I use Thinking In Boc?

Thinking In Boc fits situations like: reviewing any bocpy code (library; about to reach for time.sleep / threading.Event / atomic counters / polling loops / waitfor helpers; designing how a downstream behavior observes an upstream one; scheduling work to run after the next worker is free.

How do I install Thinking In Boc in Claude Code?

Run `npx skills add microsoft/bocpy --skill thinking-in-boc -a claude-code`. Or copy the skill folder (.github/skills/thinking-in-boc in microsoft/bocpy) into .claude/skills/thinking-in-boc in your project. Claude Code loads it when a task matches its description.

How do I install Thinking In Boc in Codex?

Run `npx skills add microsoft/bocpy --skill thinking-in-boc -a codex`. Or copy the skill folder (.github/skills/thinking-in-boc in microsoft/bocpy) into .agents/skills/thinking-in-boc in your project. Codex loads it when a task matches its description.

Can I use Thinking In Boc in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add microsoft/bocpy --skill thinking-in-boc -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/thinking-in-boc, .gemini/skills/thinking-in-boc, .github/skills/thinking-in-boc and .opencode/skills/thinking-in-boc in your project.

What does Thinking In Boc need to run?

SKILL.md names no scripts, command-line tools or credentials: Thinking In Boc is instructions for the agent only. Our summary lists: Python 3.

Does Thinking In Boc access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Thinking In Boc safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Thinking In Boc use?

Thinking In Boc is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Thinking In Boc use?

About 2.6k tokens (SKILL.md is roughly 10k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Thinking In Boc?

Skills that share tags, products or a category with Thinking In Boc: Vercel Composition Patterns (supabase/supabase, 111k stars), Finishing a Development Branch (obra/superpowers, 296k stars), Typescript Advanced Types (rolling-scopes/rsschool-app, 10k stars) and PR Babysitter (openinterpreter/openinterpreter, 69k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Thinking In Boc?

microsoft (a GitHub organization, an official publisher) maintains it in microsoft/bocpy, which has 201 GitHub stars. The repository holds 9 skills in this directory. The repository was last updated on September 28, 2026.

Source: microsoft/bocpy on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.