Omahub
← All plugins
A

Tic-Tac-Toe

by anel

Play tic-tac-toe against the computer from the bar. Easy/Medium/Hard bot difficulty, unbeatable on Hard.

Security review

Review recommended · 1 finding

Deterministic scan — not a security guarantee

Medium
Risk level
Medium
Analyzed commit
b774e40
Scanned
1 month ago
  • medium package_manager companion.py:17

    System-wide Python package installation (not --user).

    pip

Automated analysis only — not a security guarantee.

AI advisory review

No obvious issues detected

Language-model assessment · ~deepseek/deepseek-v4-flash-latest — advisory only

Low
AI risk level
Low
Recommendation
install
Model
~deepseek/deepseek-v4-flash-latest
Analyzed commit
b774e40
Reviewed
1 month ago

The plugin is a straightforward tic-tac-toe bar widget. The only flagged item is a false positive: companion.py mentions 'pip' only in a comment explaining why it deliberately avoids pip dependencies, and the script itself is dependency-free. The online mode does spawn a child Python process and connect to a third-party WebSocket relay, which is disclosed in the README and is a normal network feature, not hidden behavior.

  • Online mode sends game moves to a third-party relay (wss://ttt-relay.celikovic.xyz:8443) and spawns companion.py as a child process; this is documented in the README and is not malicious, but it is a network dependency a user should be aware of.
  • The deterministic scan flagged companion.py:17 for 'pip', but that line is a comment explaining that the script intentionally has no pip dependencies; no actual package installation occurs.
How this check works

This review combines the deterministic scan (the rule-based results above) with an independent look at the plugin's code by a language model. The model reads a trimmed sample of the repository's files, the manifest, and the README, then gives a plain-language risk level and a recommendation: install (no notable danger), review (look closer first), or avoid (clearly dangerous).

It runs on the same analyzed commit as the deterministic scan and is strictly advisory — it is not a security guarantee and never blocks a plugin by itself. A human moderator still reviews plugins before they are listed.

AI advisory only — automated analysis, not a security guarantee.

Install
$ omarchy plugin add https://github.com/anelcelik/omarchy-tictactoe --enable
Widgets #bar #games

Tic-Tac-Toe

Play tic-tac-toe against the computer, or against a matched stranger online, from the Omarchy bar. Click the # icon to open the board.

Made by anel (@anelcelik).

Tic-Tac-Toe popup

Rules

  • You're always X, the computer is always O.
  • Who opens the game alternates: you, computer, you, computer, ... New game keeps the alternation going even if you close the popup mid-series.
  • Wins/losses/draws are tracked per difficulty (an Easy win and a Hard win aren't the same thing), plus a subtle all-time total underneath.

Play online

The "Mode" tab at the top of the popup switches between Offline (vs. the bot) and Online (vs. a matched stranger). Online:

  • Connects to a small matchmaking relay and joins the queue automatically.
  • Pairs you with whoever's next in line — first in gets X.
  • The relay is the referee: win/loss/draw is decided there, not locally, so your client and your opponent's can never end up disagreeing about how a match ended.
  • No rematches with the same opponent, no reconnect if you or they drop — closing the popup mid-match doesn't end it (the connection stays open in the background, same as the bot game keeps its board), but losing the connection does. If your opponent leaves, "Find new opponent" requeues you.
  • Switching back to Offline (or the bar widget going away) disconnects — your opponent just sees the same "opponent left" they'd see from any other drop.

Mode isn't remembered across a shell restart on purpose: it always starts back on Offline rather than silently rejoining a queue in the background.

Online play talks to companion.py, a small dependency-free script this plugin spawns as a child process — it bridges stdin/stdout JSON lines to a WebSocket connection, since QML has no raw-socket API of its own. It's a dumb relay of bytes on purpose: it doesn't parse or validate game messages, so the online protocol only needs to be understood in two places (the relay and Panel.qml), not three. Only requirement: python3 on PATH (standard on any Omarchy install already) — no pip packages, no Node.

If you're running your own relay for development, point Panel.qml's relayUrl property at it — it defaults to the live one this plugin talks to.

Bot difficulty

Set from the popup, persisted to shell.json:

  • Easy — blocks your immediate wins, otherwise plays at random. Never hunts for its own win, so it's genuinely beatable.
  • Medium — plays perfectly most of the time, but 35% of moves are random. Beatable if you catch the slip.
  • Hard — full minimax with alpha-beta pruning, every move. Provably unbeatable: worst case is a draw.

Game logic lives in Bot.js, independent of QML, if you want to tweak the bot (e.g. change Medium's randomness from 35%, or add a "blocks 2-in-a-rows" mid-tier).

Files

  • manifest.json — plugin identity and bar-widget registration
  • Panel.qml — bar icon + popup UI + game state, offline and online
  • Bot.js — offline bot logic: winner detection, minimax, difficulty tiers
  • companion.py — stdio↔WebSocket bridge to the online relay

Development

This plugin lives directly under ~/.config/omarchy/plugins/anel.tictactoe/ as its own git checkout. Saving any file here hot-reloads it into the running shell; if a change doesn't seem to apply (especially anything affecting bar slot sizing), force a clean reload with:

omarchy-restart-shell

Validate before committing:

omarchy plugin validate ~/.config/omarchy/plugins/anel.tictactoe
qmllint -I /usr/share/omarchy/shell ~/.config/omarchy/plugins/anel.tictactoe/Panel.qml

Remove

omarchy plugin remove anel.tictactoe