๐Ÿƒ Playtime.nvim

July 16, 2026 ยท View on GitHub

Playtime Logo

๐Ÿƒ Playtime.nvim

A collection of (mostly card) games for Neovim that I (mostly) like.

A game of The Emissary being played

Requirements

  • Neovim 0.9+?
  • A pointing device (keyboard only navigation not currently supported!)

Included games

Some of the included games have (much nicer) for-sale digital or physical versions. If you like the game, buy it!

Classic Solitaires

FreeCell & Bakers Game. Spider (4, 2 and 1 suit variants). Calculation.

Classic-style Solitaires

Shenzhen Solitaire. Penguin. Curds & Whey. Forty Fortunes.

Solo card games

The Emissary (trick-taking).

Other games

SET (logic puzzle). Sweeper.

Instructions

Basic how-to-play guides are included in the links above or via the "How to play" menu item, with additional links to more complete or thematic instructions. Accessing some external instructions may require a Board Game Geek account (free), check the "files" section after logging in.

A game of Sweeper being lost.

Installation

Point your favorite Neovim plugin installer at github.com/rktjmp/playtime.nvim.

Usage

Execute :Playtime <game> <?seed> to run a game (use tab completion for a game list) or simply :Playtime for a graphical menu (scroll down for more games).

Most games support dragging cards to the appropriate positions, and clicking to "pick up" card(s) then clicking elsewhere to "put down" the card(s). Right clicking releases cards.

Invalid moves are reported using vim.notify so they appear in the command bar by default or via any custom notifier you may have installed.

Playtime minimises itself when the window loses focus. Refocusing the window re-raises the game.

Configuration

Playtime may be configured by calling require("playtime").setup({}).

You do not need to call setup unless you are altering a default option.

Supported options (struck through options are currently ... not supported):

Note: you may specify options in Lua style (window_position) or Fennel style (window-position).

  • fps (30): Animation frames-per-second. Must be greater than 1.
  • window-border (nil): Floating window border style. If not set here, windows will use Neovims vim.opt.winborder value or "shadow" if that option is not set.
  • window-position (center): Where to position the game window, may be center, ne, nw or a table or function that returns {row=row, col=col}.
  • minimise-position (se): Where to position the minimised window, may be ne, nw, se, sw or a table or function that returns {row=row, col=col}.
  • unfocused (minimise): what to do when the window loses focus.

The following configurations are game specific and names will change in the future, with a deprecation period.

  • __beta-game-set-font-glyph-width (nil): Hint to playtime that the font glyphs used by SET are wider than one character, may be wide or nil. If your cards look off center, try setting this to wide.
  • __game-the-emissary-icon (nil): Text used to show the Emissary character, if your font does not support the default, eg: "๐Ÿฏ๐Ÿฏ‚๐Ÿฏƒ".

You may also adjust the colors, see the FAQ.

Shenzhen Solitaire

Building

Playtime is written in Fennel, and uses hotpot.nvim as its build system.

To make changes, install hotpot.nvim and reload neovim, then when saving any .fnl file, they will automatically be compiled to lua.

If submitting a patch, it's preferable to include just the changes to fnl/ for review.

FAQ

My colors are U. G. L. Y.

Playtime currently uses a limited "traditional" color palette of red, green, yellow, orange, blue, magenta, cyan, white and black.

Where possible, colors are derived from existing highlight groups. No background color or text effects are kept, for this reason, the groups are not linked. Some colors names may not match their visual appearance, for example PlaytimeGreen may be blue if your color scheme defines DiagnosticOk to be blue.

Yellow, magenta and cyan are defined by Playtime itself because existing highlight groups did not provide a reliable default choice.

You can override the colors by defining any of the following highlight groups:

PlaytimeNormal     -- NormalFloat.fg, "general" elements
PlaytimeMuted      -- Comment.fg, disabled or "dim" elements
PlaytimeBackground -- NormalFloat, window background
PlaytimeMenu       -- PmenuSBar, "top menu" bar color
PlaytimeWhite      -- NormalFloat.fg
PlaytimeBlack      -- Comment.fg
PlaytimeRed        -- DiagnosticError.fg
PlaytimeGreen      -- DiagnosticOk.fg
PlaytimeYellow     -- Defined manually
PlaytimeOrange     -- DiagnosticWarn.fg
PlaytimeBlue       -- DiagnosticInfo.fg
PlaytimeMagenta    -- Defined manually
PlaytimeCyan       -- Defined manually

There are additional @playtime.* groups which link to the default groups which you may define for per-game alterations or tweak additional UI elements.

My text is U. G. L. Y.

I use the font Iosevka, so symbols are dictated by its unicode coverage. Some fonts may not support some symbols, or may render them in a different manner (2-ch wide instead of 1-ch for example). You may be able to configure a fallback font for your terminal, the Noto family may be a good option.

Why are my diamonds โœจgoldโœจ sometimes?

I found differentiating the suit by their icons alone to be difficult sometimes, so in games where suits matter, each suit is given their own color.

You can alter this behaviour by linking @playtime.game.card.diamonds.four_colors to @playtime.game.card.diamonds and @playtime.game.card.clubs.four_colors to @playtime.game.clubs.spades.

I thought this was a Neovim plugin, why do I need a mouse?!

When I wrote shenzhen-solitaire.nvim, I included support for keyboard control, then never used it once in two years.

Initially I did include keyboard controls in Playtime but again - never used them. I am not against including keyboard controls, especially in regard accessibility, but the simplest "tab around positions" is painfully slow to use and building a leap-like interface was a bit more than I wanted to take on initially.

Some terminals or setups might struggle with a mouse-only interface, such as ssh+terminal.app. If you are having trouble, first confirm that your terminal supports both left and right click (may require an modifier key) and that the events are being sent over ssh or whatever. You might also have to enable the mouse in Neovim or something. Think of it as a fun puzzle to solve! Wow, a free extra game!

A game of freecell being played