
Product
Microsoft Teams Notifications Are Now Available in Socket
Socket can now send alerts and supply chain attack notifications to Microsoft Teams, with filters that route the right updates to each channel.
Plan-first terminal coding agent — it shows you the plan before it touches your code, with an arcade to play while it works
A plan-first terminal coding agent, with an arcade to play while it works.
sco is the agent: it plans before it touches anything, shows you a diff before
every change, and applies nothing you have not approved. Beside it is the daemon
and arcade this project started as — real development activity (tool calls,
tests, commits, whether it comes from sco or from a Claude Code session via
hooks) feeds a deterministic XP and quest system, and there is a game to play
while the work runs. All game content, narration, and low-value prompt offload
run against a local LM Studio model, so the play layer costs zero cloud
tokens.
Requires Node 22 or newer. better-sqlite3 declares >=22, and on Node 20
npm only warns before the daemon segfaults inside new Database(). The floor is
declared in package.json with engine-strict, so an unsupported Node fails at
install with a clear message instead.
npm install -g scofield # puts `sco` on your PATH
Or from a clone of this repository:
npm install && npm link
sco, the agentvibevault run --only ANTHROPIC_API_KEY -- sco # a session in this repository
vibevault run --only ANTHROPIC_API_KEY -- sco "add rate limiting to /login"
Without linking, run it in place instead: npx sco "..." from inside this
directory, or node bin/sco.mjs "..." from anywhere. More on sco itself in
sco — the agent core below.
As a Claude Code plugin — the daemon starts itself on the next session:
/plugin marketplace add lunaos-ai/luna-code
/plugin install scofield@sco
Or run the daemon directly, from the same clone:
npm start # daemon on 127.0.0.1:7777
npm run dev # same, with auto-reload
Then open http://127.0.0.1:7777/web/, or run node tui/index.mjs for the
terminal surface.
extensions/vscode/ is a fourth surface: a sco icon in the editor title bar,
and level, streak and phase in the status bar.
cd extensions/vscode && npx @vscode/vsce package
code --install-extension scofield-1.0.0.vsix
It is a viewer, not a second daemon — it starts nothing and stores nothing, and the Claude Code plugin still owns the daemon's lifecycle. It is also the quietest surface deliberately: an editor is the most intrusive place this product appears, so a level-up changes a number in the status bar and does nothing else. No notification, no focus steal, no panel you did not open.
LM Studio is optional. Without it the daemon serves static content packs and
reports offline for LM-backed endpoints; games, XP, and quests are unaffected.
Everything above is local. Nothing about you leaves the machine unless you ask for it, and the daemon never makes an outbound request.
GET /api/progression/card.svg renders your card locally, which is all you need
to look at it. To embed it somewhere public — a GitHub README — an image proxy
has to fetch it, and it cannot reach 127.0.0.1. So GET /api/share/url encodes
your stats into the URL itself and points at a stateless renderer:
curl 127.0.0.1:7777/api/share/url
The renderer at luna-share.*.workers.dev has no database, no KV, no
accounts, and no request logging — wrangler deploy reports "No bindings
found". It is a pure function from URL to image. Nothing is stored because
there is nowhere to store it.
Two things worth being straight about:
Self-host it in one step — workers/share/ is a single Worker:
npx wrangler deploy --config workers/share/wrangler.jsonc
# then point the daemon at it
SCO_SHARE_BASE=https://your-worker.workers.dev
sco is its own agent loop and its own identity, living beside the daemon
above: it plans before it touches anything, shows you a diff before any file
change, and treats the daemon and arcade as an optional play layer rather than
something it depends on.
Run it two ways. sco on its own, in a repository, opens a session — a
prompt you type at, where each request is asked of something that remembers the
last one, and the whole sitting lands in one transcript:
$ sco
sco · plan-first coding agent
in ~/projects/api · 3 skills
Type what you want done. /help for commands, Ctrl-C to stop a turn.
● raise the rate limit
Inside a session: /help, /skills, /context, /clear, /exit. Ctrl-C
cancels the turn in flight and hands the prompt back — it does not kill the
session. Ctrl-D leaves.
sco "one request" is the same agent for a single request, which is the form a
script wants. See Install above; flags
are --yes (approve the plan and every diff without asking), --dry-run
(show everything, change nothing), --sessions (list past runs), --resume
(continue the last run, or --resume=<id> a named one — it replays that
conversation and then plans again, since an old approval is not consent for a
new run), and --no-events (skip notifying the daemon).
sco reads the same skills Claude Code does: a directory with a SKILL.md in
.claude/skills/, either in the repository or in your home directory. The
frontmatter's name and description are shown to the agent — one line each —
and it loads a body only when it decides one applies, so twenty skills cost
twenty lines of context until one is needed. A repository skill wins a name
clash with a personal one.
Loading a skill is a read, not an execution. It puts instructions in the window; it widens nothing, and every change they lead to still arrives at the diff gate.
Its terminal surface is a design system in ui/, derived from Apple's HIG: three type
tiers, five semantic colour roles, a left rail instead of boxes, and an ASCII fallback
for terminals that cannot draw the glyphs. Colour is never the only signal, and nothing
you are asked to approve is ever shortened to fit — read ui/README.md
for the rules.
It is a separate binary (bin/sco.mjs) over a separate library (agent/) — read
agent/README.md for the module map, the invariants it enforces, and
the limitations it documents honestly rather than hides. The design rationale — why a
library and not a service, why two approval gates instead of one — is in
docs/superpowers/specs/2026-08-06-scofield-agent-core-design.md.
npm test # ~1200 tests; boots its own throwaway daemon
npm run lint
npm run format
npm run check # lint + format + manifest + tests
pushci run # the full pipeline: quality, Node 22/24, Linux, worker build
CI is pushci (pushci.yml), not GitHub Actions. It runs
the matrix explicitly — nvm for the Node axis, docker for Linux — because
pushci migrate silently drops matrices, and that matrix is what caught the
Node 20 segfault above.
Claude Code ──hooks──▶ sco daemon (127.0.0.1:7777) ──▶ LM Studio (127.0.0.1:1234)
│ SSE event bus
┌───────┬───┴───┬────────────┐
web arcade VS Code TUI plugin commands
The daemon is the only stateful component. The plugin, web arcade, and TUI are thin clients over its HTTP and SSE API. Everything binds to 127.0.0.1 only.
| Method | Path | Purpose |
|---|---|---|
GET | /api/health | Health check |
POST | /events/session | Session opened |
POST | /events/prompt-start | Claude began working |
POST | /events/tool-use | Tool call observed — classified and awarded XP |
POST | /events/prompt-end | Claude finished — awards XP |
POST | /events/agent/:type | A sco run reports itself — awards XP for real work |
GET | /events/stream | SSE feed for web/TUI clients |
GET | /api/games | Game registry listing |
POST | /api/lm/content | Generated game content by kind |
POST | /api/lm/ask | Cheap-task offload completion |
POST | /api/rag/query | Resource retrieval + answer |
POST | /api/rag/reindex | Rebuild corpus index |
POST | /api/progression/score | Game reports a score/run result |
GET | /api/progression/profile | XP, level, active quests |
GET | /api/progression/summary | Level, streak, momentum, combo, quests, badges |
GET | /api/progression/streak | Streak summary + 60-day contribution strip |
GET | /api/progression/achievements | The 58-badge catalog with progress |
GET | /api/progression/quests | Today's 3 daily and this week's 2 weekly quests |
GET | /api/progression/rules | The complete reward table (see below) |
GET | /api/progression/share | Plain-text share card, rendered locally |
GET | /api/progression/card.svg | The same card as an SVG (?theme=dark|light|auto) |
GET | /api/progression/badge.json | Shields-compatible badge payload (?kind=level) |
GET | /api/share/url | Public card/badge links, built locally; nothing is sent |
GET | /api/attention | Whether Claude is working, and whether arcade XP is open |
GET | /api/games/:slug/history | Recent runs for one game |
GET | /api/stats | Aggregate totals — games played, XP, avg score, play time |
POST | /api/lm/quiz | Multiple-choice quiz generated from the retrieved corpus |
XP comes from real development activity, not only from games. The rules are pure
functions in daemon/progression/rules.mjs, so the reward table is one file.
| Event | XP |
|---|---|
Prompt completed (Stop hook) | 10 |
| Test suite passes | 25 |
| Test suite fails | 0 — never penalised |
| Commit created | 15 |
File edited (Edit/Write) | 3 |
| Any other successful tool call | 1 |
| Failed tool call | 0 |
Commands are matched per shell segment, so echo "npm test" is not a test run
and git log --format=commit is not a commit.
A tight loop of real work builds a combo (max 3.0x) that multiplies dev XP
only. Levels follow the curve in daemon/progression/levels.mjs: 80 XP to
level 2, rising to a permanent cap of 2000 XP per level from level 19 on.
| Arcade outcome | XP |
|---|---|
| Won | 4 |
| Lost / abandoned | 1 |
| Run under 5s, or within 20s of the last one | 0 |
Four rules bound arcade XP, all enforced by the daemon rather than any client:
GET /api/progression/rules returns this whole table at runtime. No award in
this product depends on chance or on the clock.
The 25% came from measurement rather than taste. tests/simulation/personas.mjs
runs six developers the tuning was never written against — a reader who rarely
commits, a three-days-on contractor, someone who works past midnight, a TDD
practitioner, a returner after ninety days, and one built to grind the cabinets.
Across every shape people actually work in, arcade XP lands at 2–19% of dev. The
grinder rode the old bound to 99%, which meant playing roughly doubled his level.
A quarter costs the other five nothing and binds only him.
Edit sco.config.json:
{
"port": 7777,
"lmStudio": {
"baseUrl": "http://127.0.0.1:1234/v1",
"chatModel": "qwen/qwen3.6-35b-a3b",
"embedModel": "text-embedding-nomic-embed-text-v1.5",
"timeoutMs": 3000
},
"autoOpenArcade": false,
"surface": "web",
"offload": { "enabled": true, "maxInputChars": 4000 }
}
Environment variables override the config, mainly so tests and multiple checkouts do not collide:
| Variable | Effect |
|---|---|
SCO_PORT | Port the daemon binds (overrides port) |
SCO_DB | Path to the SQLite file (default sco.db at the repo root) |
SCO_LM_BASE_URL | Overrides the LM endpoint; empty string disables the LM |
SCO_ARCADE | off turns the arcade off entirely |
SCO_SHARE_BASE | Overrides where /api/share/url points (self-host the renderer) |
Upgrading from an older install: on first boot, if sco.db does not exist yet,
the daemon looks next to it for luna.db (or the older finsavvy.db) and
renames whichever it finds into place — every level, badge and streak carries
over automatically. This happens once; if sco.db already exists, the old file
is left untouched.
SCO_ARCADE=off
or { "arcade": { "enabled": false } } in sco.config.json.
The game list empties, nothing opens, and arcade events stop. XP, quests, streaks and achievements keep accruing from your actual work exactly as before, and turning it back on restores every value untouched — nothing is deleted and nothing is forfeited. It is one variable, and it costs you nothing.
bin/sco.mjs # sco CLI — args, approval gates, diff rendering
agent/ # sco's agent loop (see agent/README.md)
.claude-plugin/plugin.json # plugin manifest (hooks declared inline)
hooks/ # session-start, prompt-submit, post-tool-use, stop
commands/ # play.md, quest.md, profile.md
daemon/
server.mjs # HTTP + SSE, static game hosting
lm/client.mjs # OpenAI-compatible LM Studio client
lm/router.mjs # game content prompt routing
lm/fallback.mjs # static content packs when LM Studio is down
lm/offload.mjs # cheap-task offload classification
rag/index.mjs # embedding index build + query
rag/chunker.mjs # corpus row -> chunk
progression/rules.mjs # deterministic XP rules (pure)
state/store.mjs # SQLite ledger, profile, quests, scores
scripts/run.sh # start/stop/status/tui/open — daemon process manager
scripts/validate-plugin.mjs # manifest check, run in CI
games/
_sdk/sco-game.js # postMessage host API for games
registry.json # slug, title, tags, LM content kinds
<slug>/index.html # vendored games
web/ # arcade shell, catalog, quest HUD
tui/ # terminal fallback renderer
workers/share/ # stateless share-card renderer (self-host target)
data/resources.csv # corpus (from THE_RESOURCES_TABLE.csv)
sco.config.json # models, port, toggles
| Failure | Behavior |
|---|---|
| Daemon not running | Hooks no-op. Claude Code unaffected. /play starts it. |
| Port 7777 taken | Daemon probes /api/health; foreign occupant → error in /play only. |
| LM Studio down | Static content packs; no narration; /ask-local reports offline. |
| Model returns invalid JSON | One retry with stricter prompt, then static fallback. |
| Game crashes | Frame isolated; arcade shell shows reload control; no XP awarded. |
MIT — see LICENSE
FAQs
Plan-first terminal coding agent — it shows you the plan before it touches your code, with an arcade to play while it works
The npm package scofield receives a total of 0 weekly downloads. As such, scofield popularity was classified as not popular.
We found that scofield demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Product
Socket can now send alerts and supply chain attack notifications to Microsoft Teams, with filters that route the right updates to each channel.

Security News
pnpm 12 rewrites the package manager in Rust, cutting install times by up to 90% while preserving pnpm 11 workflows and lockfiles.

Security News
Socket CTO Ahmad Nassri joins AppSec leaders at Black Hat to discuss active malware, package manager risks, and software supply chain defense.