Read the latest posts from The Blog of the EMMA Cooperative.

from andy

(As you can probably guess, this post assumes some familiarity with the collectible card game Magic: The Gathering)

I just wrapped up a multi-week online Magic: The Gathering tournament that I've been wanting to do fo a while. The 3-Card Blind format is an interesting thought-exercise/meta-game challenge that has been played on forums since at least the early 2000s.

Instead of a normal game of Magic where players bring a deck of cards to face each other, in 3CB players submit a list of exactly 3 cards. All three of these cards start in hand and players do not lose for having no deck to draw from. All of the uncertainty, and even gameplay decisions, from a normal game are removed. The game is reduced to a sort of puzzle (or auto battler) where players try to come up with 3-card combinations that can win the game and even throw off opposing strategies.

some sample 3CB decks

In this post I'm going to talk about the rules of the format, what I did to make my tournament unique, and how you can run your own (including a template spreadsheet I created to make it easy for players to report their scores).

The main focus will be on the game design decisions I made to shape this particular tournament as well as the nuts-and-bolts of how it was run. Check out some of the links below for theory and strategy (which is fascinating in this format).

How It Works

Each week, players secretly submit their deck lists to an email account I made specifically for this purpose. I put their decks into a spreadsheet (preserved here), and at the end of each week, players would mark how they did against each other deck.

Scoring works like this: for each match, players play two games (one where they go first, one where the other player goes first). For each game they win, the player gets 3 points; for each where they tie they get 1 point; and they get 0 points for a loss. So the max number of points a player can get in a match is 6.

There are a few restrictions to keep things on track: * Decks cannot win on turn 1 * Decks cannot force an opponent to discard more than 2 cards * Random effects will always go in opponent's favor

The exact rules for my tournament can be found here on the page I used to introduce and maintain the event.

But how can participants play their games solo? This is the magic of this format: there is no randomness, players have perfect information & only 3 cards. Each game is more of a logic puzzle than a proper game. There is a “correct” sequence of plays, and it is possible to determine which deck comes out ahead (or if both decks stall out and tie). The MTG Fandom page linked below has more detail about edge cases or things that would introduce randomness, but the the take-away is that the skill is in submitting a well-positioned trio of cards, not in actually playing the games.

Example Game

Let's take an example from the last week of my tournament. We have the following 3 decks:

Player A: Thassa's Oracle, Cavern of Souls, Island

Thassa's Oracle, Cavern of Souls, Island

If unopposed, the Oracle deck will win on turn 2 (this was the “house deck” for the week. More on that in a minute). Not surprisingly, combo is weak to counterspells, so Cavern of Souls provides a little extra security.

Player B: Lupine Prototype, Mishra's Workshop, Trinisphere

Lupine Prototype, Mishra's Workshop, Trinisphere

Player B is looking to lock up the opponent with Trinisphere before playing a 5/5 that can end the game in 4 turns.

Player C: Blackmail, Cruel Sadist, Swamp

Blackmail, Cruel Sadist, Swamp

Player C is also playing a control angle, using Blackmail to pluck a critical card from the opponent and then taking their time with Cruel Sadist (which can hopefully get large enough to overcome an opposing blocker that manages to get around Blackmail).

How does it play out?

  • Player A vs Player B – On the play or on the draw, B can get Trinisphere out before A can play Thassa, completely locking them out since their 2 lands cannot produce 3 mana. (6 points for B, 0 points for A)

  • Player A vs Player C – Similarly, C can play Blackmail on turn 1, guaranteeing that they can pluck Thassa from the opponent. (6 points for C, 0 points for A)

  • Player B vs Player C – This one is interesting! When B goes first, they can get their Trinisphere down and prevent Blackmail or Cruel Sadist from being played. When C goes first, they can play blackmail and trash the Lupine Prototype. (3 points for each)

Although it tied in this example, the Blackmail/Cruel Sadist deck was the strongest against the field the week it was submitted. It was able to beat multiple decks that beat the Lupine Prototype deck.

All of these decks take advantage of the unique properties of the format to use cards that would otherwise be underpowered or at least require a lot more hoops to jump through. Thassa's Oracle is certainly powerful in its own right, but usually requires a lot more setup. Blackmail is not usually premium discard, but in this format it can hit every card in the opponent's hand (including lands). Lupine Prototype I had forgotten about entirely, but here it is a reliable 5/5 beater.

Pretty much every link below has other sample matchups that you can check out. These are filled with examples of cards that need to be re-evaluated in the context of 3CB. This is a format that really rewards players who dig for gold in older, mostly forgotten cards.


Before I dive further into my own event, I want to provide a few links that are helpful for anybody thinking about running a 3CB tournament or who just wants to read about this interesting offshoot of Magic. I certainly would not have been aware of 3CB or able to run my own tournament without them.

MTG Fandom Page – A solid primer and a good reference for the rules.

3-Card Magic by Brian Demars – This article on Channel Fireball was the first time I heard about the format.

Three Card Blind: A Whole Different Format by Goblinboy – A very detailed forum post from 2005 about the format. It's very fun to see the cards from that era evaluated for this format. Does a great job of pointing out cards that are unremarkable in normal Magic, but extremely strong in 3CB and vice versa.

3-Card Blind Metashape Tournament – This was a recent tournament run on Reddit by u/Lognu. My own tournament is heavily based on their setup. That link also has spreadsheets from the game and is a great resource to see decks that people have submitted.

My Tournament's Page – Here's where I laid out the rules for my tournament and maintained the ban-list.

My Tournament Spreadsheet – You can check out my decks submitted each week here! This was where the game took place. Player names have mostly been obscured and all comments have been removed (but they were lively!).

My Tournament

In terms of structure, I was heavily influenced by Lognu's Metashape Tournament. Rather than starting with an extensive ban list (as many 3CB games do), cards from the best performing decks are banned and the list evolves over time. This forces players to come up with new solutions each week.

A lot of the fun of this format is trying to beat the field. Although there are some combinations of cards that are quite strong, there is simply nothing that wins every match. So a huge part of the tournament is trying to figure out the meta and guess which decks other people will play. To this end I introduced one other major gameplay element: the house deck.

Each week, the highest performing deck has two cards banned. Then this deck becomes the house deck. In the following week it will be one of the decks that everybody faces. This is the only deck that players know they will face, so submitting a deck that beats it guarantees 6 points. However, all players know about this can can choose to design their own deck to prey on decks that will beat the house deck. The goal is to provide just enough known info about the next round for savvy players to predict the field. There is also the challenge of forcing players to beat the winning deck without having access to the same cards (since cards in the house deck have been banned).

During the course of the tournament, one player asked if Conspiracy cards could be used. This is a bit of an edge case since they aren't proper cards and are not typically available in constructed play, but I think it's fun when things get weird so I OKed them (with the exception of Power Play, because it undermined the structure of the tournament). I think it would be more than fair to ban them in your own tournament, but I liked the inclusion and they never felt like they broke things.

Ban List

My tournament ran for 5 weeks. In that time the following cards were banned:

Running The Game

Each round was given one week. Here is the cadence I listed in the game description:

  • Results will be announced on Monday, including the updates to the ban list.
  • Players have until Thursday 3PM EST to submit their decks.
  • Players should review their games by Saturday at 8PM.

Decks were submitted by people emailing their lists to a special email account I made for the purpose of this game. This meant that I had to submit my own deck before I officially opened submissions so that I did not see anybody else's deck before locking in my own.

Because players did not see each other's decks, I allowed players to update their decks until the Thursday deadline if they wanted to. I also tried to alert players if I noticed that their deck probably would not play out the way they expected it to, or if it broke some rule and would be disqualified.

On Thursday, a new page was made in the spreadsheet and players could start scoring their decks!

The spreadsheet

Much like Eve Online, this is a game played in spreadsheets.

I based my spreadsheet on the ones that Lognu made. The big difference is that in Lognu's game, players find their row and score themselves going right along each column. The decks are listed on the right, and I figured players know their own deck. So I switched this and had my players find their column and move down, allowing them to easily see the cards they faced in each match.

Here is a a gif I made of Jenny submitting her scores to explain the process to new players. (She has one win against Timmy for 3 points, and no wins against Spike)

Score submission example

You may notice that this system has duplicate information. For example, the result of cell E2 (Spike vs Timmy) can be derived from cell C4 (Timmy vs Spike). Since Timmy got a 0 against Spike, we know that Spike must have gotten a 6 against Timmy. But there is a reason for this: it means that every game has both players computing the results separately. Magic is a complex game and the optimal play is not always obvious. By having both players evaluate the games independently, there is some built in confirmation of the results. (This was further assisted by other players being generally interested. During the game, there was constant commentary on many of the cells as players discussed how games would play out).

Because I hated the thought of scanning the grid to determine if values did not line up, I wrote some formulas in my sheet to check if the values for a given pair of cells did not match. Then I used conditional formatting to highlight those cells in yellow to alert myself and other players that there was some issue here.

Let's take the same example from above. Let's say Spike shows up but thinks they win one game and tie one game against Timmy. grid with yellow highlight

The spreadsheet highlights the cells for that match in yellow. If one cell of a match is 0 (two losses), the other should be 6 (two wins). Alternatively, if one cell of a match is 4 (a win and a tie), the other should be 1 (a loss and a tie). The logic for this is frustratingly complex and I wrote a python script to export the formulas for the 225 cells needed for a 15 player game. If you are curious, you can check out rows 50 to 65 of my template sheet (they're hidden by default but you can expand them if you duplicate the sheet).

If you go through the weeks of my tournament, you'll find a few instances where I had to make a judge call (highlighted in purple), but in at least 90% of cases where the results did not match, players sorted it themselves (often with help from other players weighing in on the result via cell comments). Having the sheet automatically flag disputes did a lot encourage players to reevaluate and fix results. It also provided fun conversation fodder!

It is a credit to the group I was playing with that one of the most frequent disagreement was a player explaining why the other deck would actually beat them.

Week to Week

Dive into the spreadsheet if you want to see all the decks submitted each week. There are some very interesting trends as certain deck types had rises and falls in popularity. What I'm going to present here is the winning deck for each week (which became the house deck for the following week). It's a great microcosm of the strategies at play in 3CB.

Most players asked that I not include their names, but rest assured that none of these winning decks were submitted by me.

Week 1 – Inkmoth Nexus, The Tabernacle at Pendrell Vale, Urborg, Tomb of Yawgmoth Inkmoth Nexus, The Tabernacle at Pendrell Vale, Urborg, Tomb of YYawgmoth

Week 2 – Strip Mine, Chancellor of the Annex, Icatian Store (submitted by NaCl) Strip Mine, Chancellor of the Annex, Icatian Store (submitted by NaCl

Week 3 – Mesmeric Fiend, Leyline of Anticipation, Black Lotus Mesmeric Fiend, Leyline of Anticipation, Black Lotus

Week 4 – Memnite, Snapback, Force of Will Memnite, Snapback, Force of Will

Week 5 – Thassa's Oracle, Cavern of Souls, Island (submitted with only slight variations by 4 players) Thassa's Oracle, Cavern of Souls, Island

Week 6 – Blackmail, Cruel Sadist, Swamp (submitted by NaCl) Blackmail, Cruel Sadist, Swamp

You can see how each deck beats the one before it, but not necessarily the one two weeks prior!

Random Thoughts and Notes

Cell comments were an unexpected delight. I originally planned on including all participants on a group email each week to discuss the round, but players started adding comments directly onto the spreadsheet. It was very lively and became a space to discuss cool decks people had made in addition to sorting out tricky matches.

I do wish I had encouraged people to use burner email accounts and usernames. The comments in the spreadsheet are mostly tied to personal email accounts. It didn't occur to me that I might want to share the results of the game in a post like this, and at that point the comments were too linked to personal information. The spreadsheet I posted here has all of the decks, but the commentary and most of the names have been removed.

After one week of manually linking everybody's cards, I started asking players to submit their decks on a single line with each card name being a link to scryfall. It made the process of prepping the sheet much less time consuming.

If I did it again, I would green light conspiracy cards from the jump, as I thought they were a lot of fun.

In this game, I banned two cards from each winning deck (determined by the order in which they were submitted). This resulted in an interesting but slightly slow-moving ban list. In the future I'd ban all 3 cards in the winning deck and possibly take out one or two from other high scoring decks as well.

The house deck did exactly what I wanted it to do. It guided the field just enough that players could strategize around it.

Running Your Own / Using My Spreadsheet

If you are interested in running your own 3CB tournament, you absolutely should! It's a good time and you only need about 5 regular players to make it compelling.

You can use my or Lgnu's rules directly, but it's a lot of fun to make up your own spin on it as well.

If it is helpful, you can duplicate my spreadsheet template and get my nice conditional formatting.

If you do start a new game with this sheet, I'd love to hear about! Hit me up on twitter, mastodon or email me at andy[at]andymakes[dot]com.

While I have you here...

I'm a real sucker for games where people secretly submit their moves for the turn. I've been working on a wargame called Skirmish Society that was inspired by Diplomacy. It's played via Discord bot and you secretly DM your orders to the bot each turn (while plotting and making deals with other players in the public channel and over DM). I'm close to wrapping it up and would love to have a few more test groups. If that sounds fun to you, you can install it on your Discord for free over here!


from andy

This is adapted from a talk given by Ramsey and Andy at NYU Game Center on April 28th, 2022. Thanks to Jane Friedhoff for helping us adapt it to a blog post.

What is a technology co-op? Why would you want to form one? And how on earth do you go about doing it?

In this post, we’ll introduce you to the core of EMMA: how we created it, how we operate it as a group, and what needs it’s helping us fill that non-co-op work didn’t give us.

But first, a few disclaimers:

  • Every co-op is different and special, and we can only speak to our own experiences. Your mileage may vary! We can only tell you what we’ve done, and the particular path we took to get here. Think of this not as a guide, but rather an example.
  • EMMA is a service co-op, not a product co-op. This is an important distinction: a product-oriented co-op (say, a videogame co-op) or a co-op in a materials-heavy industry like construction will likely require much larger overhead and startup costs before they can recoup their initial investment. As a service co-op, our overhead is very low and our startup costs were minimal. This, plus decades of individual experience with the creative coding market as a whole, gives us a lot of freedom that other businesses might not have.

With that out of the way, let’s get started!

What is EMMA?

EMMA is a state-recognized software consultancy co-op located in New York State, which went official in January 2022. We write software for clients on a contractual basis, usually in the interactive software industry (e.g. videogames, public installations, VR/AR, web experiences) but we’re willing to take on work wherever we have expertise. Depending on who you ask, the name is either an homage to Emma Goldman (an amazing anarchist of the early 20th century), or an acronym: Everybody Making Money and Art.

Operationally, we use a consensus governance model with a proportional compensation structure: that is, we all make the decisions together as equals, and we get paid relative to how much we work. We only have one class of member: there’s no difference between founders and folks who might join later. We also rotate responsibilities, and very actively stay in touch with each other to make sure everyone understands how everything works and feels empowered to act on the co-op’s behalf.

Fiscally, members keep 70% of whatever client money they bring in, with 30% going to EMMA to cover costs and future salaries. If a member brings in less than a pre-agreed “base salary” due to a dry spell or life circumstance, they get that base salary.

Legally, we are a New York State Domestic Cooperative Corporation, also known as a Worker Cooperative. While we resemble a more conventional corporation, we’re not an LLC or S-Corp, for reasons we’ll go into later. We are all simultaneously owners and employees, and the same will be true of future hires.

Spiritually, we’re a group of weirdos who dream of spending our time making art, not grinding work.


Before we go into the logistical details of running your own co-op, let’s talk about how the four of us gravitated towards the idea of starting one.

All four of us–Ramsey, Andy, Gwen, and Ivan–have been in the creative code and technology world in different capacities for decades. Andy, for example, co-led an indie games company, left that to teach game design, and landed in creative technology consulting. Ramsey had likewise been freelancing in creative technology since 2010, in addition to his games, art, and research practices. Gwen moved directly from university into traditional salaried employment in the creative technology industry. However, she found herself freelancing in 2020-21 as a consequence of covid making temporary work more readily available. Ivan has been working professionally as a creative coder since 2005. He has been freelance for most of this time, taking breaks to lead creative technology teams and teach game and graphics programming.

Although all of us came from different work backgrounds, we discovered we had all quietly been looking for the same thing. Many of us came from arts and indie videogames, and found the constant hustling those fields required to get even scraps of funding to be exhausting and draining. The COVID-19 crisis highlighted just how much control our various employers had over our lives and safety: those of us who were teaching, for example, were given baffling demands that we return to office during outbreaks or lose our jobs (and health insurance). Ramsey counts the October 17 Revolution in his native Lebanon as a pivotal moment that made it clear to him that a better world was both possible and worth building right now.

In our earliest discussions, we found that we all wanted basically the same handful of things:

  • The possibility of making enough money to live comfortably, while having enough time to make art (making art is great, but paying rent with art is exhausting).
  • The security of having a predictable salary (tricky for a job as boom/bust as freelancing).
  • The agency to work in a way that aligns with our values (instead of those of some executive board or shareholders).
  • The satisfaction of knowing our money and labor is building a structure that we value (and supporting people that we value).
  • The opportunity to do interesting work if possible (we reject actively harmful work, but are also happy to be plumbers for digital toilets).

Non-cooperative structures could have provided us some of these things (with much less legal hassle) but with a variety of tradeoffs we did not want to make. We were lucky enough to have been exposed to quite a few other co-ops, some run by people we knew personally. Feel Train, for example, was a creative tech co-op from 2015-2019, with co-owners Darius Kazemi and Courtney Stanton sharing their bylaws and documents to the public (We strongly encourage you to check those out!). KO_OP, Soft Not Weak, and Motion Twin are all co-op game studios that also influenced our decision to go co-op. These were enterprises run by people we respected, making work we loved, and watching them do so while exploring more radical modes of labor was a huge inspiration.

There are a few lenses on how EMMA works: our internal conceptual model for the co-op; the logistical model of the co-op; and how this model was encoded into the legal structures afforded to us by the state. Let’s go into each.

How EMMA works, conceptually

What values guide our processes about and within EMMA?

EMMA is a financial capacitor

As we said before, EMMA uses a proportional compensation structure, meaning we get paid relative to how much work we bring into the co-op.

We see EMMA as a kind of financial capacitor. A capacitor is an electronic device that can store a charge of electricity and discharge it slowly, over time. This consistency is welcome in a field like freelance software development, which has booms and busts: periods of lots of work, and periods of no work at all. The idea of EMMA is to pool resources–to metaphorically charge the capacitor–during booms so that we can pay salaries during busts.

image showing the effect of a capacitor on voltage

This interdependence is a welcome support network for an erratic field. On our own, the chance of any one of us not having work for a given season is reasonably high. But if we all come together, the odds that absolutely no one has work are low. The capacitor is always getting charged by someone, which provides security for everyone.

EMMA supports our art practices

As you might imagine, the fiscal and even psychological security of having a guaranteed income stream makes it a lot easier for our members to have the time, energy, and resources, to pursue our own art. All four of us have artistic practices, and that is not a coincidence. A top-level goal of EMMA is to support the non-marketable art that its members make, and free them from having to depend on selling art (and the concurrent market forces around art) to survive.

EMMA minimizes work

Although EMMA’s business model is creative code consulting, we do not dream of labor! We want to work enough to live comfortably, and then stop when possible. This seems obscene in a world that expects constant exponential growth–but working less is an explicit goal of our co-op, as we want our members to be able to pursue projects that they find valuable for their own sake, as we said above.

Knowing when to stop working/start turning down work can be hard when you’re on your own: even if you make a lot, there’s always a future fallow period to worry about. But within the co-op structure, we can set common financial goals and identify when it’s financially safe to turn down work.

EMMA is a small node in a (hopefully) bigger mesh

Although we don’t have an exact number, EMMA will always remain small–likely fewer than 8 people. The governance of the organization can really only work with a small number of members: consensus decision making often doesn’t scale well beyond a small group.

Furthermore, it is critical to us that all members know and respect each other–not in a general be-nice-to-each-other way, but in a way that requires everyone knowing each other well and being invested in each others’ success. This also functions best with a small group.

And just because EMMA is small doesn’t mean that its dreams are! Our dream isn’t that we run the One Giant Co-op Everyone Joins: rather, we’d love to see a future of many, many co-ops self-managing themselves, tailored to their respective members’ needs. In the ultimate version of this, we would see cooperative workplaces collaborating with each other by sending delegates to industry syndicates to discuss and solve industry-wide issues. These syndicates would then send delegates to regional federations, with power and decision-making rising from the bottom up. This isn’t some thing we’ve conjured up, similar structures can be found in classic anarcho-syndicalist and more contemporary democratic confederalist theories and is being put into practice in places like the Autonomous Administration of North and East Syria. Being small is a feature, not a bug.

How EMMA works, logistically

So how does EMMA actually function day-to-day?

EMMA is run by consensus governance

When we say “everyone decides” you might assume that we either vote on fixed proposals or require unanimous decision-making. In actuality, we do neither. We treat decision making as a conversation, where a given proposal often changes over the course of the conversation, and where responses may fall on a spectrum from “I love it” to “this is OK” to “I hate this and I’ll leave over it.”

This is an unusual way for a corporation to operate, but is actually pretty straightforward in practice, and works well with a small group like ours: as Ivan says, “it takes you longer to make decisions, but the quality of the decisions tends to be better.”

This isn’t totally foreign to the tech industry, either. The IETF, which writes and maintains many load-bearing protocols that hold up the internet, is deeply committed to what they call a “rough consensus” process that avoids the will of a majority eclipsing the needs of the minority. If you ever wonder if this consensus stuff could actually work at scale consider the fact that you’re reading this blog post delivered to you over several IETF protocols as evidence that it does!

Spoiler alert: lawyers did not like this! “Infinite growth” is basically an axiom of modern business: all the structures around making one assume that the goal is to just keep scaling up forever. But our consensus governance model doesn’t scale all that well–doing it with four people is a lot easier than trying to do it with four hundred. We had a lot of back and forth with our lawyers that we understood and did not mind this!

EMMA uses proportional compensation

You also might assume that everyone is paid the same amount at EMMA, and this is not the case either. Everyone is paid the same way, but not necessarily the same amount.

Some co-ops do make it a point to pay everyone the same amount. It’s a perfectly valid approach, and we considered it at first, but we realized that it was not a good fit for EMMA. After all, different people have different life needs. Some may be happy to couch-surf, while others may be itching to buy a home. Some may have zero dependents, while others need to take care of family. Some may be keen to work absolutely as little as possible, while others may want to work more and build out their emergency funds. Additionally members will almost certainly wind up moving within that spectrum, and possibly in a big hurry! Having just one rate for everyone bulldozes over these various individual considerations and desires.

Rather, at EMMA, everyone is paid with the same method. Everyone keeps 70% of whatever they bring in, with 30% going to EMMA to cover operating costs and future salaries. In addition to that, as a safety net, if someone has a rough month and brings in less than a collectively agreed on base salary, no problem: they get paid the base salary anyway, thanks to our financial capacitor. This covers both dry spells and slow client payments. This structure allows people to work different amounts and come away with different amounts, which helps us support members regardless of their current life situation.

However, being paid different amounts doesn’t affect our governance. After all, a company could have a flat pay structure, while having an operational hierarchy. We have the opposite: while we make different amounts of money, each member always has the same decision making power within the co-op.

As a co-op we have access to certain kinds of corporate profit accounting that other legal entities do not. Specifically, we have at our disposal mechanisms to share EMMA’s end of year profit with members in novel ways. We have not enacted any of these mechanisms, however, as we have not been in business for more than a year. As of now the profit sharing plan is basically a spill-over. if 30% of EMMA's revenue is more money than we actually want to keep in the co-op we can use profit sharing to distribute that cash back to the members.

EMMA has one class of member, and everyone does everything

At EMMA, we have exactly one class of worker-owner: the “member.” There is no hierarchy among members, and when other members join down the line, they will be exactly equal to the founding members following a candidacy period.

It’s worth noting that not all co-ops are like this: it is not a legal requirement. The principles just call for “democratic member control,” which could allow for hierarchy. (Some larger co-ops have, for example, boards of directors and managers forming a more traditional looking corporate hierarchy. These positions are chosen democratically by the worker-owners, however). Given our small size and the political inclinations of some of our members we opted for a flat governance structure.

In addition to not having a hierarchy, we don’t want our members to get siloed into operational roles: we want everyone to do everything, at least a little. A practical example is our books. Every member of EMMA is trained to maintain the company’s books, and updates the relevant ledgers to reflect their own client work as well as general company transactions. Another is our payroll system: we rotate who actually operates the software and moves the money around, while the rest of us sit in on a video call to provide guidance and a double-check work.

This system of shared responsibilities has a lot of benefits. First and most pragmatically, this avoids the “hit by a bus” problem: if Ramsey is the only one who knows how to do the payroll software, but he gets hit by a bus, how will EMMA pay its employees in his absence? Much better to spread that knowledge out so that everyone feels competent at taking on a given role within the organization.

Second, this system makes our worker democracy more meaningful. Micheal Albert makes the argument that traditional division of labor in a cooperative runs the risk of eroding the collective’s democracy and creating a “coordinator class” of people who know how to run the enterprise at a higher level distinct from everyone else. For example, even if Ramsey didn’t get hit by a bus in the previous example, if he’s the only one who knows how payroll works, how can the co-op discuss payroll-related issues as equals? So we make it a point to share knowledge and make sure everyone gets their hands dirty in all aspects of running the ship.

How EMMA works, legally

How do we make sure the state isn’t mad at us?

First of all, we should disclaim yet again that there are many ways to approach incorporating a co-op. Some of our decisions were made to best fit our specific needs; some were made because we had certain freedoms that gave us more options (like having cash on hand to get set up); and some were likely mistakes we made because we didn’t know any better at the time! Talk to us in a few years when we have the benefit of hindsight.

All this just to say: the following isn’t a guide, and it is most definitely not legal advice, just an example of how we did things.

EMMA is a NYS Domestic Cooperative Corporation (Worker Cooperative)

On a technical level, we are a NYS Domestic Cooperative Corporation, or a Worker Cooperative. NYS has a legal entity that fits our needs and values so we went for it – this will be different in different states! We resemble a corporation, in that EMMA is a “legal person” that is taxed separately from us, but one where we are all owners and employees. We are compensated for our labor throughout the year and share in profits at the end of the year (there are co-op-specific mechanisms for this, although we have not had a full financial year to actually test any of them).

As a state-recognized co-op, we get some special benefits, as well as a handful of restraints that we actually really like.

New York State law requires us to act and govern ourselves as a co-op. This is both a restriction and a perk! This requirement makes it difficult to “stop being a co-op” if future members try and do that. This happens enough in co-ops that it has a name: demutualization. In S-corps and other similar entities that are set up to be co-ops via their bylaws alone, it is possible for the members to vote to demutualize at a later date. We want to make that as hard as possible.

And, of course, we get to legally be called a cooperative in our company name and get a .coop URL, which is pretty neat.

The main downside is the added complexity of setting up this corporate structure. Online incorporation platforms like LegalZoom do not have “cooperative” as an option, so you will need to engage some lawyers to draft and file your paperwork for you. There’s no reason a “LegalZoom for Cooperatives” could not exist, but figuring that out is an exercise left to the reader.

EMMA “totally has a hierarchy” ;) ;)

Remember our whole “no hierarchy” thing? Turns out that NYS requires every corporation to have a president, vice president, and treasurer. Boo! But rather than tangle with the law, we decided to get around this requirement by simply stripping those positions of any and all unique powers in our bylaws, and choosing them by dice roll. We will rotate positions each year, but we made sure that legally, they did not matter.

As part of our process, we also had to explicitly request one class of member, one class of stock, and so on. Our bylaws require all employees, owners, managers, officers, directors, shareholders, etc. to all be the same ‘person.’ Likewise, there is only one class of stock, and any member can only own a single share. Most of this was outside the default, and not obvious to the state/lawyers, so we had to explicitly request it.

How EMMA pays taxes

This part is speculative because we haven’t been incorporated for a full year at the time of this writing, but we intend to file our end of year corporate taxes as what’s called a “T-Corporation.” This is a corporation that files under the rules in subchapter T of the IRS code (the subchapter right after subchapter S that gives S-Corporations their name!) and files form 1120-C as opposed to the 1120 that conventional corporations file. Subchapter T and 1120-C are the cooperative specific tax rules we are subject to.

There are a few bells and whistles here in terms of how we’re allowed to retain and share profits, but given that we haven’t gotten this far yet we can’t really comment deeply on any of it. In theory, we can do a kind of end of year accounting unique to co-ops that might allow members to keep more of the money they made during the year compared to conventional forms of compensation. Also, we can more easily use EMMA as a “cash warehouse” meaning we can retain an unbounded amount of cash at the company without incurring extra taxes. This is important when we’re trying to keep that capacitor charged! Again, given that we have not been open long enough as of the time of this writing to have crossed a tax year boundary, this part of the structure is still speculative. Check back in with us in a year!

[Hello, 2023 EMMA here and we have some hindsight now. Much of this document is good, and the core goals and ideas laid out can work. However we've found that issuing a “commission” is a specific stumbling block both legally and tax-wise. Our best advice is to consult with Lawyers and CPAs early and often!]

EMMA uses professionals to help manage all this

There is no way we could have done all this on our own. The process of incorporating and maintaining our money requires people with expertise we simply don’t have!

By and large, we tried to stick with organizations that aligned in some way with our values. This mostly meant working with other co-ops. There was typically a trade-off in convenience and accessibility, but it was nice to work with folks who not only shared our political goals, but who also tended to have a better understanding of what a co-op even is.

Our legal counsel was provided by JL Weiner & Associates whom we liked working with, and would recommend. We bank with Brooklyn Co-op FCU, got bookkeeping guidance from A Bookkeeping Cooperative, and used Gusto to run payroll.

Benefits we get of being part of a co-op

We’ve already mentioned some clear benefits of being part of a co-op–the financial capacitor aspect being a key one. For a while, it seemed like that was the primary thing we’d get out of it. And don’t get us wrong–that’s plenty great on its own! But even long before we were officially incorporated, we started seeing a lot of other benefits too.

It provides mutual support and a framework for knowledge-sharing

Work is hard! Freelancing involves a lot of interpersonal and operational skills that can be overwhelming: everything from doing taxes to dealing with stubborn clients to negotiating rates. And if you work in a field where things are constantly changing–like ours, where new technology is getting introduced, frameworks are getting changed, and software updates are constantly wrecking past projects–it can be very stressful to take on a new project solo. Having a team of people away from clients to lean on when things are confusing is invaluable.

This mutual support really comes in handy when we run into the kinds of technical issues mentioned above. We’re all creative coders, but even so, we all have different skills and specialties. Each of our members is an expert in at least one thing that the others know very little about. Our tech support channel in our self-hosted MatterMost (an open source Slack clone) is a wildly helpful resource whenever any of us run into issues on the job.

Furthermore, this knowledge-sharing doesn’t end when the gig does. While we come to each other to solve specific problems, we also find that the co-op structure encourages genuine ongoing learning and mentorship.

It makes it easy to share gigs

If you’re freelancing during a boom period, you may get solicited for more work than you can take on. It takes a bit of time and effort to reply to a potential client with a curated list of other people who might be able to do the gig well. But with a co-op structure in place, it’s as easy as saying, “I am booked, but let me check with my cooperative!” and passing the work on to them. Indeed, we’ve already shared gigs and bookings (at the time of this writing, we’re all booked on the same client!). And this added income supports all of us in the end.

This sets us up as a kind of stable of experts who can be brought on for a client’s project as needed. Ivan compares it to going to your favorite barber shop as a walk-in: your absolute favorite barber might be busy, but you know that everyone working there is good.

It gives us better negotiating power

A lot of freelancing stress comes from money (surprise!). As individuals, we’ve all needed and given advice to others who are struggling to set their rates, or trying to write an email gently reminding a sluggish client to pay.

But as a co-op, it’s easier to ask for money, and easier to get that money. We’ve already used ‘’ to remind clients of a late invoice to very positive effect. This faceless collective email account helps avoid the discomfort of personal client confrontation.

Further, we are able to bounce rates off each other, and treat rates as standard across our co-op. This is doubly important given the many pay inequality issues in tech (across race, gender, etc.). When we work separately, and when wage information is effectively secret, it’s easy for clients to nickel and dime us individually. But when we share our rates and bargain together, we can provide a unified front for more fair compensation for everyone. A rising tide lifts all boats!

Advice for starting your own co-op

Hopefully, we’ve given you some practical insights into how you might conceive of, form, and run your own co-op. But before we sign off, a few pieces of advice:

Co-op structures do not guarantee success

Hopefully obvious, but being a co-op does not on its own guarantee success. EMMA is doing well right now, but that’s in part thanks to the fact that we were all doing well as freelancers before EMMA. We were able to bring professional networks built over decades to the co-op, and that’s certainly bolstered our current business. We don’t want to give the impression that adopting a cooperative structure is a guaranteed recipe for financial success! You still have to succeed as a business in conventional ways.

You can test drive a co-op today!

Before we were a state-sanctioned cooperative corporation, we spent about a year unofficially acting like one. We had weekly meetings hosted on a friend’s personal Slack, where we’d talk about work and hold each other accountable to our various career and artistic goals. This regular communication made it easy and convenient to share gigs, give advice, and help with rate negotiation, allowing us to build solidarity by lifting each other up. A year of doing this gave us a strong working relationship, and an investment in each other’s success and happiness long before any paperwork was filed.

The nice thing about this is that you can do it today, no government forms required! If you’re interested in starting a co-op, try building a habit of normal meetings with your desired collaborators, and creating platforms where you can share your advice/expertise/networks with each other. Even if you don’t end up starting a co-op, you’ll likely find that you get a lot of benefits having this space to work together rather than apart.

Say hi!

We hope this was helpful to you! If you want to see what we’re up to you can check out (love that .coop domain) or follow us on social media:


When we gave this talk at NYU, we closed by linking to these resources that were mentioned in the lecture. They helped us and hopefully they can help you too! — Democracy at Work, resources on forming and running a co-op — Feel Train documents


from andy

Earlier this week I released Pico-Pond, a networked PICO-8 demake of Frog Chorus, a web-project I love by v buckenham and Viviane Schwarz.

You can play Pico-Pond for free in your browser here:

You can also look through the source code, which I hope will be helpful for anybody else looking to make a networked PICO-8 game. The code is commented and (hopefully) easily readable.

Please keep in mind that this was a weekend project that was never meant to scale beyond 20 players. I did not try to make it super efficient or account for every edge case.


screenshot from the game

Just like in the original, you control a single frog in a pond populated by other real people. All you can do is hold a button to grow in size and then release it to make a ribbit. The ribbit is louder and longer the bigger your frog is when you release. All credit for this design goes to buckenham and Schwarz. It is deceptively simple, but the act of communicating with strangers this way is surprisingly rich.

What makes Pico-Pond somewhat unusual for PICO-8 is that it is networked! This is not a standard feature of PICO-8, but is possible in a web build through some fairly straightforward hacks. I've been curious about exploring this for a while after reading about some early work in this direction. I selected a Frog Chorus tribute both because I loved the original and because the simplicity of it lent itself to a good first project.

Before I get into the details, here's an overview of how this project connects multiple users into the same PICO-8 experience. The magic is in the gpio pins added in version 0.1.7. The gpio pins represent a set of 128 bytes of memory and were designed for PICO-8 projects on the raspi to allow games to be able to respond to hardware on the device. For whatever reason, they are also accessible to JavaScript running alongside the game in web builds. This can bridge communication between the PICO-8 game and the surrounding web page. Once you've broken out into JS, the sky is the limit.

This particular project uses a setup like this: The gpio pins are used to allow my JS and the PICO-8 game to communicate. My frontend JS then communicates to a node server hosted on Heroku using a websocket.

flow diagram

JS / PICO-8 Communication

The first time I read about doing something like this was a few years ago when I stumbled across this post by edo999. This used JavaScript equivalents of the PICO-8 peek & poke functions to insert or read values from the heap. Seemed promising and I kept it in my back pocket as something I wanted to check out. More recently I encountered seleb's post about a functional twitter client he wrote in PICO-8 (it's really cool. Check it out!). He was using the gpio method and was kind enough to include his source code.

This method is very easy! For the JS file, all you need to do is create an array of 128 elements called pico8_gpio. After exporting the PICO-8 game as a web page, the javascript file needs to be included in the HTML file. The 128 elements of this array map to 128 locations in the PICO-8 memory starting at location 0x5f80. To write to slot 2 and read from slot 5 in JavaScript I might write

pico8_gpio[2] = 32;
let my_val = pico8_gpio[5];

And to do the same in PICO-8 I would use peek & poke to manipulate memory

poke(0x5f80+2, 32)
local my_val = peek(0x5f80+5)

That's pretty much it! One tricky thing is that this only works when running a web build, so testing in the editor becomes tricky. I wound up writing some testing values to memory in _init() so that my app thought it was connected. Needing to make a web build definitely increases debug time.

Managing Communication

There are 128 gpio pins to use! As seleb notes in his post, “128 bytes is a pretty big chunk of data for a PICO-8 app.” Pico-Pond doesn't even come close to using all of them. Seleb came up with a clever structure to allow the JS and PICO-8 elements use the same pins in order to send large amount of data, with the first pin acting as a control pin letting both apps know whose turn it was. Luckily my needs were simpler so instead every pin is designated as being for a specific app. Either the JS script writes to it and PICO-8 reads, or the other way around. They never write to the same pin.

One note is that although I could store negative numbers in these addresses from PICO-8, I was not able to write a negative value from JS. So some things might seem a little odd (like using 200 to mean that a frog is not active). I'm sure this can easily be fixed, but it was never enough of an issue for this game.

Here's the breakdown of pins in the finished project. I didn't settle on 20 frogs right away and I wasn't sure how many pins I would need for each frog, so I left the first 100 pins for game-state information from the backend and started additional data at pin 100.

PIN number Description Who writes to it Use
1-20 Frog Values JS values of all frogs in range from 0-100. 200 means that frog is unused
21-99 unused unused unused
100 Player Input PICO-8 1 if button held, 0 if not
101 ID JS ID of this player. Set by backend
102 Cart Start PICO-8 starts at 0, set to 1 when cart is loaded to let JS know it's ready
103 Status JS Tells the game the status of the connection to the backend (waiting, connected, room full, disconnected/error)

Pin 0 wound up being unused when I moved all the frog values up by 1 pin to match PICO-8/Lua style of indexing arrays at 1 (a constant source of consternation).

The values in 1-20 and 101 get set from the backend, but not directly. The JS script communicates with the backend via the websocket. There is a regular pulse from the backend with the gamestate. When the frontend receives this message, it writes the values to those 20 pins. Likewise, when the backend responds to a new player with a frog ID, the frontend JS writes that ID to pin 101.

The JS script does not manage game logic at all. It just acts as a bridge between PICO-8 and the backend.

Keeping the Data Small

You might notice that each frog in the game is stored as a single number between 0 and 100 (with 200 meaning they are inactive). Although I didn't think I would even come close to using all 128 pins, I wanted to keep the amount of data moving from the backend as small as possible (mostly so that I could easily send the entire gamestate instead of needing to have a more clever system).

One way to approach a game like this would be to have the backend create a frog when a user connects. Things like the X and Y, the color etc of the frog could be generated and stored in the backend. This would be fine, but then all of those attributes need to be sent to clients who connect to the game. In this game the only thing that changes is the size of the frog (increasing when the button is held and then returning to 0 when released), so I wanted that to be the only value managed by the backend. I think an argument could be made for just having the backend track if a player is holding down the button or not and letting the PICO-8 game manage the rising and falling value, but I wanted the backend to have an accurate snapshot of the current gamestate so that a newly connected player would have all of the correct data.

Right now, when a new player joins, the backend finds a random open frog and sends them the ID of that frog. The frog object on the backend consists of a number value and a boolean for if the player is holding the button. Every tick (targeting 30FPS to match PICO-8) the frog value goes up if the button is held and down if it is released. Changes in the user's button state are sent via websocket whenever the frontend JS sees that the input pin has changed value.

So what happens to those other attributes? They don't really have to be consistent; they could be randomized when the game starts, but that doesn't feel right. If I'm the red frog in the bottom left corner, it feels like I should be that frog for everybody.

The easily solution here is to randomize these things, but to seed the random number generator so that the values are the same for everybody. I wrote a simple (and very inefficient (please don't @ me if you read the source code)) function to randomly distribute the positions of the frogs to roughly fill out the screen and then randomized the other frog attributes (color, sound etc). For each of these steps I tried out a few different seeds until I found ones I like. Now all instances of the game have the same pond without needing to send those extra values across the wire.


The last thing I needed to do was make the frogs ribbit. One of the charming things about Frog Chorus is that the different frogs have different voices (audio recordings of people saying “ribbit”) that get played at different speeds and volumes depending on how big the frog is when you release. The fact that the frogs sound different from each other and that the sound is modulated by how long the button was held contribute in a big way to the conversational feel of Frog Chorus. You can get into a groove with people where you do lots of little chirps or each grow really big to do a loud ribbit at the same time; it's a lot of fun! I wanted to make sure that this aspect was captured as well.

As such, one-shot sound effects were probably not going to cover it. Luckily there are some tools I know from making hyper-condensed tweet jam games that allow for some dynamic audio generation. Weirdly, the print command can be fed a special character that causes the string that follows to be played as audio. This whole portion of the PICO-8 documentation on control codes is pretty interesting.

The basic format is “\ab..e#..b” where “\a” is the control code that signals to PICO-8 to treat the string as audio and then everything after that is telling it what to play—in this case a B and E# and another B with a slight pause in between each note.

There are some additional properties available such as volume (v), instrument (i), effect (x), and speed (s).

For example let's look at “\as9v7x3i0f..d-..f”. Going from the end and working our way to the left this string plays an F note followed by D flat then another F (“f..d-..f”) using instrument 0 (“i0”), effect 3 (“x3”) at volume 7 (“v7”) and speed 9 (“s9”).

Not very pretty to look at but it gives a lot of control.

Speed and volume are fantastic for modulating the sound. I mapped the size of the frog when the button is released to these values so that big frogs play a slow, loud sound and little frogs play quick fast ones. After some trial and error, I got it so the length of the sound roughly matches the length of time it takes the frog to shrink back down to the base size.

I'm sure a sound effects person could do a better job, but I got a fairly nice ribbit-y trill by going back and forth between two notes like this: high note, low note, high note, low note. These notes are defined for each frog in the setup function using the same seeded random function as the other attributes.

Then, to give frogs their own voice, I also randomize the instruments and effects. Not all of them sound froggy, but I tried each one and made a pool of acceptable options for each frog to pull from in setup.

If there are tons of frogs in the pond, these sounds are likely to get cutoff when multiple frogs use the same instrument. I think that's OK though because that means there are enough people using it that it will feel lively anyway.

Wrap Up

There's a bit more going on, but those are the exciting parts! Please dig into the code if you're curious. Once I was finished I went over it and commented everything to try and make it as easy as possible to parse.

I hope this is helpful if you want to add a bit of networking to your own PICO-8 projects!

Frog Chorus was made by v buckenham & Viviane Schwarz.

The frog pic used in the game is a lightly modified version of an image made by scofanogd and released with a CC0 license.

Thanks to Sean S. LeBlanc for the breakdown of his PICO-8 twitter client, which was a key part of getting this off the ground!

Thanks to lexaloffle for PICO-8!


from gwen

I'm gonna start this blog with a softball I happened upon in Stack Overflow today. This snippet will give a user on a linux system password-free sudo permission but for a specific command(s).

In my case I want a little side project to be able to reload nginx's config but I very much do not want a hacky side project running with complete sudo access. This snippet is perfect as I can allow that user sudo access but only for this one task!


Add a line like this to /etc/sudoers or /etc/sudoers.d/{user}

username ALL=(ALL) NOPASSWD: /path/to/command arguments, /path/to/another/command

Now log in as that user either via ssh or sudo su {user} and try your command.

$ systemctl reload nginx


This will allow the user gwen to reload nginx but nothing else

gwen ALL=(ALL) NOPASSWD: /usr/bin/systemctl reload nginx

And this will allow the user gwen to reload or restart nginx but nothing else

gwen ALL=(ALL) NOPASSWD: /usr/bin/systemctl reload nginx, /usr/bin/systemctl restart nginx

Credit for the solution goes to the original stack overflow post!

#sudo #linux #sysadmin