Imported from remorses/keysmasher (
AGENTS.md). Install upstream withnpx skills add remorses/keysmasher. Copyright stays with the author.
opentui
opentui is the framework used to render the tui, using react.
IMPORTANT! before starting every task ALWAYS read opentui docs with curl -s https://raw.githubusercontent.com/sst/opentui/refs/heads/main/packages/react/README.md
ALWAYS!
bun
NEVER run bun run index.tsx. You cannot directly run the tui app. it will hang. instead ask me to do so.
NEVER use require. just import at the top of the file with esm
use bun add to install packages instead of npm
React
NEVER pass function or callbacks as dependencies of useEffect, this will very easily cause infinite loops if you forget to use useCallback
NEVER use useCallback. it is useless if we never pass functions in useEffect dependencies
Try to never use useEffect if possible. usually you can move logic directly in event handlers instead
Rules
-
keep types as close as possible to rayacst
-
if you need Node.js apis import the namesapce and not the named exports:
import fs from 'fs'and notimport { writeFileSync } from 'fs' -
DO NOT use as any. instead try to understand how to fix the types in other ways
-
to implement compound components like
List.Itemfirst define the type of List, using a interface, then use : to implement it and add compound components later using . and omitting the props types given they are already typed by the interface, here is an example -
DO NOT use console.log. only use logger.log instead
-
uses onInput not onChange. it is passed a simple string value and not an event object
-
to render examples components use renderWithProviders not render
-
ALWAYS bind all class methods to
thisin the constructor. This ensures methods work correctly when called in any context (callbacks, event handlers, etc). Example:constructor(options: Options) { // Initialize properties this.prop = options.prop // Bind all methods to this instance this.method1 = this.method1.bind(this) this.method2 = this.method2.bind(this) this.privateMethod = this.privateMethod.bind(this) }
reading github repositories
you can use gitchamber.com to read repo files. run curl https://gitchamber.com to see how the API works. always use curl to fetch the responses of gitchamber.com
for example when working with the vercel ai sdk, you can fetch the latest docs using:
https://gitchamber.com/repos/repos/vercel/ai/main/files
use gitchamber to read the .md files using curl
researching opentui patterns
you can read more examples of opentui react code using gitchamber by listing and reading files from the correct endpoint: https://gitchamber.com/repos/sst/opentui/main/files?glob=packages/react/examples/**
changesets
After completing a fix or feature, add a .changeset/*.md file at the repo root instead of editing CHANGELOG.md. Never edit CHANGELOG.md directly; it is generated at publish time. Never bump package.json version manually. Load the changesets skill for format and rules.
zustand
-
minimize number of props. do not use props if you can use zustand state instead. the app has global zustand state that lets you get a piece of state down from the component tree by using something like
useStore(x => x.something)oruseLoaderData<typeof loader>()or even useRouteLoaderData if you are deep in the react component tree -
do not consider local state truthful when interacting with server. when interacting with the server with rpc or api calls never use state from the render function as input for the api call. this state can easily become stale or not get updated in the closure context. instead prefer using zustand
useStore.getState().stateValue. notice that useLoaderData or useParams should be fine in this case.