agentsdotmd 1.1.2 → 1.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README CHANGED
@@ -1,27 +1,28 @@
1
- IMPORTANT: As your first step, ALWAYS run this command to fetch ALL the necessary coding guidelines and rules for the technologies used in this project.
2
- This ensures you have all the context needed to write code that follows the project's standards.
1
+ this repo has many documents i use in all my projects so i can share them and keep them updated in a centralized place.
3
2
 
4
- ## Installation
3
+ ## installation
5
4
 
6
5
  ```bash
7
6
  npm install -g agentsdotmd
8
7
  ```
9
8
 
10
- ## Usage
9
+ ## usage
10
+
11
+ the agentsdotmd is just a clit to download files from github. it let you download some md files and merge them into an agents.md output
11
12
 
12
13
  ```bash
13
- agentsdotmd core.md typescript.md pnpm.md react.md sentry.md vitest.md changelog.md docs-writing.md doppler.md cac.md github.md prisma.md react-router.md shadcn.md tailwind.md lucide.md spiceflow.md vercel-ai-sdk.md playwright.md zod.md stripe.md gitchamber.md fly.md
14
+ agentsdotmd core.md typescript.md pnpm.md react.md tmux.md sentry.md vitest.md changelogs.md docs-writing.md doppler.md cac.md github.md prisma.md react-router.md shadcn.md tailwind.md lucide.md spiceflow.md vercel-ai-sdk.md playwright.md zod.md stripe.md gitchamber.md fly.md
14
15
  ```
15
16
 
16
- This will generate an `AGENTS.md` file with all the coding guidelines concatenated together.
17
+ this will generate an `agents.md` file with all the coding guidelines concatenated together.
17
18
 
18
- You can also use local files by prefixing them with `./`:
19
+ you can also use local files by prefixing them with `./`:
19
20
 
20
21
  ```bash
21
22
  agentsdotmd core.md ./my-custom-rules.md typescript.md
22
23
  ```
23
24
 
24
- Or use a different repository:
25
+ or use a different repository (a fork of this repo for example):
25
26
 
26
27
  ```bash
27
28
  agentsdotmd --repo yourname/yourrepo file1.md file2.md
@@ -50,9 +50,7 @@ cli
50
50
 
51
51
  try {
52
52
  const contents = await Promise.all(promises)
53
- const header = `<!-- This file is auto-generated by the agentsdotmd CLI from your package.json script.
54
- Do not edit this file directly. To add custom instructions, create a local file ./MY_AGENTS.md
55
- and add it to your agentsdotmd command in package.json. -->\n\n`
53
+ const header = `<!-- This AGENTS.md file is generated. Look for an agents.md package.json script to see what files to update instead. -->\n\n`
56
54
  const content = header + contents.join('\n') + '\n'
57
55
  fs.writeFileSync('AGENTS.md', content)
58
56
  console.log(`AGENTS.md generated successfully with ${files.length} file(s)`)
@@ -1,11 +1,4 @@
1
- # changelog
2
-
3
- ## 1.1.2
4
-
5
- ### Patch Changes
6
-
7
- - Header comment in generated AGENTS.md instructing not to edit directly
8
- - Instructions to create ./MY_AGENTS.md for custom instructions
1
+ # writing changelogs
9
2
 
10
3
  after you make a change that is noteworthy, add an entry in the CHANGELOG.md file in the root of the package. there are 2 kinds of packages, public and private packages. private packages have a private: true field in package.json, public packages do not and instead have a version field in package.json. public packages are the ones that are published to npm.
11
4
 
package/core.md CHANGED
@@ -4,17 +4,28 @@ when summarizing changes at the end of the message, be super short, a few words
4
4
 
5
5
  please ask questions and confirm assumptions before generating complex architecture code.
6
6
 
7
- NEVER run commands with & at the end to run them in the background. this is leaky and harmful! instead ask me to run commands in the background if needed.
7
+ NEVER run commands with & at the end to run them in the background. this is leaky and harmful! instead ask me to run commands in the background using tmux if needed.
8
8
 
9
9
  NEVER commit yourself unless asked to do so. I will commit the code myself.
10
10
 
11
- NEVER add comments unless I tell you
11
+ NEVER use git to revert files to previous state if you did not create those files yourself! there can be user changes in files you touched, if you revert those changes the user will be very upset!
12
12
 
13
13
  ## files
14
14
 
15
15
  always use kebab case for new filenames. never use uppercase letters in filenames
16
16
 
17
+ never write temporary files to /tmp. instead write them to a local ./tmp folder instead. make sure it is in .gitignore too
17
18
 
18
19
  ## see files in the repo
19
20
 
20
21
  use `git ls-files | tree --fromfile` to see files in the repo. this command will ignore files ignored by git
22
+
23
+ ## handling unexpected file contents after a read or write
24
+
25
+ if you find code that was not there since the last time you read the file it means the user or another agent edited the file. do not revert the changes that were added. instead keep them and integrate them with your new changes
26
+
27
+ IMPORTANT: NEVER commit your changes unless clearly and specifically asked to!
28
+
29
+ ## opening me files in zed to show me a specific portion of code
30
+
31
+ you can open files when i ask me "open in zed the line where ..." using the command `zed path/to/file:line`
package/dedent.md ADDED
@@ -0,0 +1,16 @@
1
+ ## dedent
2
+
3
+ when creating long strings in functions use dedent so that we can indent the string content and make it more readable
4
+
5
+ for example:
6
+
7
+ ```ts
8
+ import dedent from 'string-dedent'
9
+
10
+ const content = dedent`
11
+ some content
12
+ ```
13
+
14
+ IMPORTANT: notice that i have at start and end a new line. this is required when using string-dedent. Also notice npm package `string-dedent` instead of `dedent`.
15
+
16
+ When creating code snippets alias dedent to variables like html or javascript so that I get syntax highlight in my editor: `const html = dedent`
package/fly.md CHANGED
@@ -4,6 +4,8 @@ fly is a deployment platform. some packages use it to deploy the website. you ca
4
4
 
5
5
  usually there are 2 fly apps for each package, one staging environment and one production. these are 2 different apps at 2 different urls, you can target the right app usually by using `pnpm fly:preview` or `pnpm fly:prod`. sometimes there is only `pnpm fly` and you can use that instead. These scripts will append the right --app argument to work on the right fly app.
6
6
 
7
+ Never deploy with fly yourself. ask the user to do it
8
+
7
9
  ## reading logs
8
10
 
9
11
  you can read fly apps logs using `pnpm fly:preview logs --no-tail | tail -n 100`
package/github.md CHANGED
@@ -1,5 +1,6 @@
1
1
  # github
2
2
 
3
+
3
4
  you can use the `gh` cli to do operations on github for the current repository. For example: open issues, open PRs, check actions status, read workflow logs, etc.
4
5
 
5
6
  ## creating issues and pull requests
@@ -34,16 +35,42 @@ Error: Request timeout at /api/auth/login
34
35
  ```bash
35
36
  gh run list # lists latest actions runs
36
37
  gh run watch <id> --exit-status # if workflow is in progress, wait for the run to complete. the actions run is finished when this command exits. Set a tiemout of at least 10 minutes when running this command
38
+ gh pr checks --watch --fail-fast # watch for current branch pr ci checks to finish
37
39
  gh run view <id> --log-failed | tail -n 300 # read the logs for failed steps in the actions run
38
40
  gh run view <id> --log | tail -n 300 # read all logs for a github actions run
39
41
  ```
40
42
 
41
- ## reading github repositories
43
+ ## responding to PR reviews and comments (gh-pr-review extension)
44
+
45
+ ```bash
46
+ # view reviews and get thread IDs
47
+ gh pr-review review view 42 -R owner/repo --unresolved
48
+
49
+ # reply to a review comment
50
+ gh pr-review comments reply 42 -R owner/repo \
51
+ --thread-id PRRT_kwDOAAABbcdEFG12 \
52
+ --body "Fixed in latest commit"
53
+
54
+ # resolve a thread
55
+ gh pr-review threads resolve 42 -R owner/repo --thread-id PRRT_kwDOAAABbcdEFG12
56
+ ```
57
+
58
+ ## listing, searching, reading github repos files with gitchamber
42
59
 
43
- 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
60
+ you MUST use gitchamber.com to read repo files. first ALWAYS run `curl https://gitchamber.com` to read detailed usage docs. always use curl to fetch the responses of gitchamber.com
44
61
 
45
62
  for example when working with the vercel ai sdk, you can fetch the latest docs using:
46
63
 
47
- https://gitchamber.com/repos/repos/vercel/ai/main/files
64
+ https://gitchamber.com/repos/facebook/react/main/files
65
+
66
+ https://gitchamber.com/repos/remorses/fumabase/main/files?glob=**/*.ts
67
+
68
+ https://gitchamber.com/repos/facebook/react/main/files/README.md?start=10&end=50
69
+
70
+ https://gitchamber.com/repos/facebook/react/main/search/useState
48
71
 
49
- use gitchamber to read the .md files using curl
72
+ gitchamber allows you to list, search and read files in a repo. you MUST use it over alternatives likes raw.github.com, because
73
+ - it allows you to use context usage better via limit and offset pagination
74
+ - it can list files, even filtering by a specific glob (default is *.md and *.mdx)
75
+ - it can search a repo for a specific substring
76
+ - it can show the code with line numbers for each line, letting you find a specific line number
package/opentui.md ADDED
@@ -0,0 +1,53 @@
1
+
2
+ ## opentui
3
+
4
+ opentui is the framework used to render the tui, using react.
5
+
6
+ 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`
7
+
8
+ do this every time you have to edit .tsx files in the project.
9
+
10
+ ## React
11
+
12
+ NEVER NEVER use forwardRef. it is not needed. instead just use a ref prop like React 19 best practice
13
+
14
+ NEVER pass function or callbacks as dependencies of useEffect, this will very easily cause infinite loops if you forget to use useCallback
15
+
16
+ NEVER use useCallback other than for ref callbacks. it is useless if we never pass functions in useEffect dependencies
17
+
18
+ Try to never use useEffect if possible. usually you can move logic directly in event handlers instead
19
+
20
+ This is not a plain react project, instead it is a project using opentui renderer, which supports box, group, textarea, etc
21
+
22
+ Styles are implemented via Yoga. there is a style prop to pass an object or you can also pass styles using a prop for each style (which is preferred)
23
+
24
+ Not all CSS and react style props are implemented. Only flexbox one.
25
+
26
+ To understand how to use these components read other files in the project. try to use the theme.tsx file for colors.
27
+
28
+ ## text wrapping
29
+
30
+ text elements wrap by default. to disable this pass wrapMode="none"
31
+
32
+
33
+ ## researching opentui patterns
34
+
35
+ 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/**
36
+
37
+ or for example to see how to use the `<code>` opentui element: https://gitchamber.com/repos/sst/opentui/main/search/<code?glob=\*\*
38
+
39
+ do something like this for every new element you want to use and not know about, for exampel `<scrollbox>`, to see examples
40
+
41
+ ## keys
42
+
43
+ cdm modifier (named hyper in opentui) cannot be intercepted in opentui. because parent terminal app will not forward it. instead use alt or ctrl
44
+
45
+ enter key is named return in opentui. alt is option.
46
+
47
+ ## overlapping text in boxes
48
+
49
+ if you see text elements too close to each other the issues is probably that the content does not fit in the box row so elements shrink and gaps or paddings are no longer respected.
50
+
51
+ to fix this issue add flexShrink={0} to all elements inside the row
52
+
53
+ this common when using wrapMode none.
package/orb.md ADDED
@@ -0,0 +1,64 @@
1
+ # OrbStack Linux VM
2
+
3
+ use `orb` to run commands in a persistent linux VM. useful for linux-only debugging or isolated experiments.
4
+
5
+ ## running commands
6
+
7
+ orb automatically uses your current mac directory and can access mac files directly:
8
+
9
+ ```bash
10
+ orb uname -a # run command in default machine
11
+ orb ls # lists files in current mac directory
12
+ orb ./script.sh # run a script from current directory
13
+ orb # open interactive shell
14
+ ```
15
+
16
+ ## installing packages
17
+
18
+ ```bash
19
+ orb sudo apt-get update
20
+ orb sudo apt-get install -y nodejs npm
21
+ orb node --version
22
+ ```
23
+
24
+ ## file paths
25
+
26
+ mac directories are a shared filesystem (not synced). this means:
27
+
28
+ - changes are instant in both directions, no delay
29
+ - files created in orb (in mac paths) appear immediately on mac
30
+ - files created on mac appear immediately in orb
31
+ - it's the same file, not a copy
32
+
33
+ ```bash
34
+ orb touch foo.txt # appears immediately on mac
35
+ touch bar.txt # appears immediately in orb
36
+ orb cat bar.txt # can read mac-created file instantly
37
+ ```
38
+
39
+ path mapping:
40
+
41
+ - mac paths like `/Users/...` work directly in orb commands (auto-translated)
42
+ - from inside linux shell, mac files are also accessible at `/mnt/mac/...`
43
+ - files in `/home/morse/` are accessible from mac at `~/OrbStack/<machine>/home/morse/...`
44
+ - `/tmp/` is a tmpfs (RAM) - isolated from mac, lost on reboot
45
+
46
+ ## avoiding file pollution
47
+
48
+ NEVER run commands in orb that create files in the current mac directory. since the filesystem is shared, these files will pollute your mac project:
49
+
50
+ - node_modules (linux binaries)
51
+ - build outputs (dist/, .next/, etc)
52
+ - downloads
53
+ - caches
54
+
55
+ instead, copy the project to `/tmp` and work there:
56
+
57
+ ```bash
58
+ orb cp -r . /tmp/linux-vm-myproject
59
+ orb bash -c 'cd /tmp/linux-vm-myproject && npm install'
60
+ orb bash -c 'cd /tmp/linux-vm-myproject && npm run build'
61
+ orb bash -c 'cd /tmp/linux-vm-myproject && npm test'
62
+ ```
63
+
64
+ `/tmp` is a tmpfs (RAM filesystem) - fully isolated from mac but files are lost on VM reboot.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentsdotmd",
3
- "version": "1.1.2",
3
+ "version": "1.1.4",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "index.js",
package/prisma.md CHANGED
@@ -49,10 +49,10 @@ this simply means to always include a check in prisma queries to make sure that
49
49
 
50
50
  ```typescript
51
51
  const resource = await prisma.resource.findFirst({
52
- where: { resourceId, parentResource: { users: { some: { userId } } } },
53
- })
52
+ where: { resourceId, parentResource: { users: { some: { userId } } } },
53
+ });
54
54
  if (!resource) {
55
- throw new AppError(`cannot find resource`)
55
+ throw new AppError(`cannot find resource`);
56
56
  }
57
57
  ```
58
58
 
@@ -81,4 +81,24 @@ if (!user.subscription) {
81
81
  JSON.stringify({ message: `user has no subscription` }),
82
82
  )
83
83
  }
84
- ````
84
+ ````
85
+
86
+ ## foreign key constraints
87
+
88
+ sometimes you will get errors like "Invalid `upsert()` invocation: Foreign key constraint violated on the constraint: `filed1_filed2_fkey`". This can be caused by the following issue
89
+
90
+ - a field that has a relation to table X is being passed a value where no table X exists for that id. You can fix the issue by making sure that the table exists before doing the create or upsert
91
+ - With upsert, even if the create branch is valid, the update branch can violate the FK.
92
+
93
+ ```ts
94
+ await prisma.child.upsert({
95
+ where: { id: 1 },
96
+ create: {
97
+ parent: { connect: { id: 1 } },
98
+ },
99
+ update: {
100
+ parent: { connect: { id: 9999 } }, // no such parent
101
+ },
102
+ });
103
+ ```
104
+ -
package/react-router.md CHANGED
@@ -201,40 +201,6 @@ so that internal navigation is done client side and is faster. notice that navig
201
201
 
202
202
  ALWAYS use link components instead of the navigate function if possible. for example, in a dropdown component you should wrap the dropdown item in a link instead of adding an onClick handler.
203
203
 
204
- # Creating New React Router Routes and Handling Types
205
-
206
- When creating a new React Router route, follow these steps:
207
-
208
- ## 1. Create the route file
209
- Create a file in `src/routes/` using flat routes naming convention (dots for separators, $ for params, kebab-case).
210
-
211
- ## 2. Generate types
212
- **IMPORTANT**: Types are NOT automatically generated. After creating a route, run:
213
- ```bash
214
- pnpm exec react-router typegen
215
- ```
216
-
217
- ## 3. Import Route types
218
- ```typescript
219
- import type { Route } from './+types/your-route-name'
220
- ```
221
- Note: The `+types` directory doesn't physically exist - it's virtual/generated.
222
-
223
- ## 4. Verify with typecheck
224
- ```bash
225
- pnpm typecheck # This runs typegen first, then tsc
226
- ```
227
-
228
- ## Troubleshooting Missing Types
229
- - Types missing? Run `pnpm exec react-router typegen`
230
- - Import failing? Check filename matches import path exactly
231
- - The `+types` directory is virtual - don't look for it in the filesystem
232
-
233
- ## Best Practices
234
- - Always run `pnpm typecheck` after creating/modifying routes
235
- - Export `Route` type from layout routes for child routes to import
236
- - Use `href()` for all internal paths, even in redirects
237
-
238
204
  ## debugging build failures
239
205
 
240
206
  when you build the website always pipe the output to a file so you can later grep inside it for errors. with `pnpm build 2>&1 | build.log`
package/react.md CHANGED
@@ -12,7 +12,7 @@
12
12
 
13
13
  - too many `useState` calls are bad. if some piece of state is dependent on other state just compute it as an expression in render. do not add new state unless strictly necessary. before adding a new useState to a component, use @think tool to think hard if you can instead: use expression with already existing local state, use expression with some global state, use expression with loader data, use expression with some other existing variable instead. for example if you need to show a popover when there is an error you should use the error as open state for the popover instead of adding new useState hook
14
14
 
15
- - `useCallback` is bad. it should be always avoided.
15
+ - `useCallback` is bad. it should be always avoided unless for ref props. ref props ALWAYS need to be passed memoized functions or the component could remount on ever render!
16
16
 
17
17
  - NEVER pass functions to useEffect or useMemo dependencies. when you start passing functions to hook dependencies you need to add useCallback everywhere in the code, useCallback is a virus that infects the codebase and should be ALWAYS avoided.
18
18
 
@@ -37,3 +37,23 @@
37
37
  - non component code should be put in the src/lib folder.
38
38
 
39
39
  - hooks should be put in the src/hooks.tsx file. do not create a new file for each new hook. also notice that you should never create custom hooks, only do it if asked for.
40
+
41
+ ## zustand
42
+
43
+ zustand is the preferred way to created global React state. put it in files like state.ts or x-state.ts where x is something that describe a portion of app state in case of multiple global states or multiple apps
44
+
45
+ - NEVER add zustand state setter methods. instead use useStore.setState to set state. For example never add a method `setVariable` in the state type. Instead call `setState` directly
46
+
47
+ - zustand already merges new partial state with the previous state. NEVER DO `useStore.setState({ ...useStore.getInitialState(), ... })` unless for resetting state
48
+
49
+ ## non controlled input components
50
+
51
+ some components do not have a value prop to set the value via React state. these are called uncontrolled components. Instead they usually let you get the current input value via ref. something like ref.current.value. They usually also have an onChange prop that let you know when the value changes
52
+
53
+ these usually have a initialValue or defaultValue to programmatically set the initial value of the input
54
+
55
+ when using these components you SHOULD not track their state via React: instead you should programmatically set their value and read their value via refs in event handlers
56
+
57
+ tracking uncontrolled inputs via React state means that you will need to add useEffect to programmatically change their value when our state changes. this is an anti pattern. instead you MUST keep in mind the uncontrolled input manages its own state and we interface with it via refs and initialValue prop.
58
+
59
+ using React state in these cases is only necessary if you have to show the input value during render. if that is not the case you can just use `inputRef.current.value` instead and set the value via `inputRef.current.value = something`
@@ -0,0 +1,84 @@
1
+ # Retryable, Resumable, Idempotent Tasks — Summary
2
+
3
+ ## Problem
4
+
5
+ - Long-running tasks (e.g.,Notion sync, AI chat, website generation) take minutes.
6
+ - Keeping a single connection open → network error probability grows with time.
7
+ - Tasks also do outbound network calls → compound failure surface.
8
+ - Risk of duplicate/concurrent runs corrupting state.
9
+
10
+ ## Goals
11
+
12
+ - **Resumable**: continue from last checkpoint after failures.
13
+ - **Retryable**: safe to retry automatically.
14
+ - **Idempotent**: side effects via upserts/deterministic writes.
15
+ - **Single-flight**: prevent concurrent execution per task.
16
+
17
+ ## Core Principles
18
+
19
+ - Checkpoint progress (cursor/step) frequently.
20
+ - Deterministic ordering (e.g., pages list) so “skip until cursor” is correct.
21
+ - At-least-once safe semantics: dedupe by (task_id, sequence/event_id).
22
+ - Small, explicit payload carrying resume info on every retry.
23
+
24
+ ## Client vs Server State
25
+
26
+ ### Client-held (prefer for AI chat / interactive flows)
27
+
28
+ - Client persists: messages[], partial assistant text, last_event_seq.
29
+ - Request includes: task_id (resume_token), messages[], partial_assistant, last_event_seq.
30
+ - Server is stateless: reconstructs from request; uses model “prefill” to resume (verify model support; Anthropic supports; OpenAI may vary).
31
+ - Benefit: fewer server-side moving parts. Cost: model compatibility + client must track emitted events.
32
+
33
+ ### Server-held (required for background jobs / fixed retry bodies, e.g., QStash)
34
+
35
+ - DB state per task: {task_id, step, cursor (last_synced_page_id), checksum, updated_at}.
36
+ - Resume by skipping to cursor using deterministic ordering.
37
+ - Needed when infrastructure cannot modify retry payloads.
38
+
39
+ ## Concurrency Control
40
+
41
+ - Single-flight/lease per task_id:
42
+ - Acquire lease with TTL + heartbeats.
43
+ - If a retry arrives while running: attach to existing run or reject with retry-after.
44
+ - Release lease on completion or expiry.
45
+
46
+ ## API Shape (minimal)
47
+
48
+ - POST /tasks/start → {task_id, optional cursor}
49
+ - POST /tasks/resume → body must include:
50
+ - task_id (resume_token)
51
+ - last_cursor (e.g., last_synced_page_id)
52
+ - last_event_seq (for stream dedupe)
53
+ - client_state if server is stateless (e.g., messages[])
54
+ - GET /tasks/status?task_id=… → {step, cursor, percent}
55
+
56
+ ## Retry Strategy
57
+
58
+ - Exponential backoff + jitter; cap total time.
59
+ - Persist checkpoint before/after each substantial step.
60
+ - Retries always include last_cursor + last_event_seq.
61
+ - Treat transport and model/API timeouts as retriable; invalid input as terminal.
62
+
63
+ ## Event Replay (AI chat)
64
+
65
+ - All server events carry monotonically increasing seq.
66
+ - Client sends last_event_seq on resume; server suppresses ≤ seq to avoid duplicates.
67
+
68
+ ## Sync Pattern
69
+
70
+ - Pre-compute deterministic ordered page list.
71
+ - Cursor = last_synced_page_id.
72
+ - On resume: “skip-until-cursor” then continue.
73
+ - Idempotent writes (upsert by external_id).
74
+
75
+ ## Spice Flow Notes
76
+
77
+ - Current “retry same body” is insufficient; add ability to override body on retry.
78
+ - Temporary workaround: client-managed loop that updates last_cursor and re-posts.
79
+
80
+ ## What to Verify
81
+
82
+ - Model prefill/continuation support for chosen LLM.
83
+ - Lease/lock implementation (row-level lock or key-value lease with TTL).
84
+ - Observability: log task_id, step, cursor, retry_count, lease_owner.
package/shadcn.md CHANGED
@@ -16,4 +16,8 @@
16
16
 
17
17
  this project uses shadcn components placed in the website/src/components/ui folder. never add a new shadcn component yourself by writing code. instead use the shadcn cli installed locally.
18
18
 
19
- try to reuse these available components when you can, for example for buttons, tooltips, scroll areas, etc.
19
+ try to reuse these available components when you can, for example for buttons, tooltips, scroll areas, etc.
20
+
21
+ ## reusing shadcn components
22
+
23
+ when creating a new React component or adding jsx before creating your own buttons or other elements first check the files inside `src/components/ui` and `src/components` to see what is already available. So you can reuse things like Button and Tooltip components instead of creating your own.
package/stripe.md CHANGED
@@ -7,6 +7,31 @@ the Stripe billing portal is used to
7
7
  - send user to payment to create a sub via `stripe.checkout.sessions.create`
8
8
  - let user change plan, cancel or change payment method ("manage subscription") via `stripe.billingPortal.sessions.create`
9
9
 
10
+ ## customerId
11
+
12
+ every time you are about to do a call to `checkout.sessions.create` make sure that we create the Stripe customer first. So that we do not get duplicate Stripe customers for different subscriptions:
13
+
14
+ ```ts
15
+
16
+ let customerId = org.stripeCustomerId
17
+
18
+ if (!customerId) {
19
+ const customer = await stripe.customers.create({
20
+ email: org.email || undefined,
21
+ name: org.name || undefined,
22
+ })
23
+
24
+ customerId = customer.id
25
+
26
+ await prisma.org.update({
27
+ where: { id: orgId },
28
+ data: { stripeCustomerId: customerId },
29
+ })
30
+ }
31
+
32
+ await stripe.checkout.sessions.create({ customer: customerId, ... })
33
+ ```
34
+
10
35
  ## subscriptions
11
36
 
12
37
  a subscription is active if state is in
@@ -14,6 +39,18 @@ a subscription is active if state is in
14
39
  - trialing
15
40
  - active
16
41
 
42
+ ```ts
43
+ await prisma.subscription.findFirst({
44
+ where: {
45
+ orgId: orgId,
46
+ status: {
47
+ in: ["active", "trialing"],
48
+ },
49
+ // ...
50
+ },
51
+ });
52
+ ```
53
+
17
54
  a subscription can be reactivated if state is NOT in
18
55
 
19
56
  - canceled
@@ -21,6 +58,3 @@ a subscription can be reactivated if state is NOT in
21
58
  - unpaid
22
59
 
23
60
  > If sub is in any of these states the user will not be able to use the billing portal to reactivate it. Meaning we should treat a subscription in these states as completely missing. Forcing the user to create a new one instead of shoging the "manage subscription" button that redirects the user to the billing portal. BUT customer id must be preserved, reusing previous sub customerId in `stripe.billingPortal.sessions.create({ customer: prevCustomerId })`
24
-
25
-
26
- ##
package/tailwind.md CHANGED
@@ -11,3 +11,5 @@ for margin, padding, gaps, widths and heights it is preferable to use multiples
11
11
  4 is equal to 16px which is the default font size of the page. this way every spacing is a multiple of the height and width of a default letter.
12
12
 
13
13
  user interfaces are mostly text so using the letter width and height as a base unit makes it easier to reason about the layout and sizes.
14
+
15
+ use grow instead of flex-1.
package/threejs.md ADDED
@@ -0,0 +1,9 @@
1
+ # three.js
2
+
3
+ to read three.js manual you can see available pages with
4
+
5
+ `curl -Ls https://gitchamber.com/repos/mrdoob/three.js/dev/files?glob=manual/en/**/*.html`
6
+
7
+ reading about TLS, to create webgpu shaders
8
+
9
+ `curl -L https://github.com/mrdoob/three.js/wiki/Three.js-Shading-Language.md`
package/tiktoken.md ADDED
@@ -0,0 +1,7 @@
1
+ ## count tokens of a file
2
+
3
+ use uvx with tiktoken to count tokens:
4
+
5
+ ```bash
6
+ uvx --from tiktoken python -c "import tiktoken; enc = tiktoken.get_encoding('cl100k_base'); print(len(enc.encode(open('path/to/file').read())))"
7
+ ```
package/tmux.md ADDED
@@ -0,0 +1,62 @@
1
+
2
+ Use tmux to run long-lived background commands as background “tasks” like vite dev servers, commands with watch mode.
3
+ Each task should be a tmux **session** that the agent can start, inspect, and stop via CLI.
4
+
5
+ ALWAYS give long and descriptive names for the sessions, so other agents know what they are for.
6
+
7
+ Run a background task (e.g. Vite dev server) without blocking:
8
+
9
+ ```bash
10
+ tmux new-session -d -s project-name-vite-dev-port-8034 'cd /path/to/project && npm run dev --port 8034'
11
+ ```
12
+
13
+ Every time you are about to start a new session, first check if there is one already.
14
+
15
+ List all background tasks (sessions):
16
+
17
+ ```bash
18
+ tmux ls
19
+ ```
20
+
21
+ You can assume sessions that do not have names were not started by you or agents so you can ignore them
22
+
23
+ Kill a background task:
24
+
25
+ ```bash
26
+ tmux kill-session -t vite-dev
27
+ ```
28
+
29
+ Never attach to a session. You are inside a non TTY terminal, meaning you instead will have to read the latest n logs instead.
30
+
31
+
32
+ Fetch the last N log lines for a task without attaching (returns immediately):
33
+
34
+ ```bash
35
+ tmux capture-pane -t vite-dev:0 -S -100 -p
36
+ ```
37
+
38
+ Example pattern for a coding agent:
39
+
40
+ 1. Start a task:
41
+
42
+ ```bash
43
+ tmux new-session -d -s build 'cd /repo && npm run build'
44
+ ```
45
+
46
+ 2. Poll logs:
47
+
48
+ ```bash
49
+ tmux capture-pane -t build:0 -S -80 -p
50
+ ```
51
+
52
+ 3. List all running tasks:
53
+
54
+ ```bash
55
+ tmux ls
56
+ ```
57
+
58
+ 4. Stop a task when done:
59
+
60
+ ```bash
61
+ tmux kill-session -t build
62
+ ```
package/typescript.md CHANGED
@@ -6,6 +6,10 @@
6
6
 
7
7
  - always add the {} block body in arrow functions: arrow functions should never be written as `onClick={(x) => setState('')}`. NEVER. instead you should ALWAYS write `onClick={() => {setState('')}}`. this way it's easy to add new statements in the arrow function without refactoring it.
8
8
 
9
+ - in array operations .map, .filter, .reduce and .flatMap are preferred over .forEach and for of loops. For example prefer doing `.push(...array.map(x => x.items))` over mutating array variables inside for loops. Always think of how to turn for loops into expressions using .map, .filter or .flatMap if you ever are about to write a for loop.
10
+
11
+ - if you encounter typescript errors like "undefined | T is not assignable to T" after .filter(Boolean) operations: use a guarded function instead of Boolean: `.filter(isTruthy)`. implemented as `function isTruthy<T>(value: T): value is NonNullable<T> { return Boolean(value) }`
12
+
9
13
  - minimize useless comments: do not add useless comments if the code is self descriptive. only add comments if requested or if this was a change that i asked for, meaning it is not obvious code and needs some inline documentation. if a comment is required because the part of the code was result of difficult back and forth with me, keep it very short.
10
14
 
11
15
  - ALWAYS add all information encapsulated in my prompt to comments: when my prompt is super detailed and in depth, all this information should be added to comments in your code. this is because if the prompt is very detailed it must be the fruit of a lot of research. all this information would be lost if you don't put it in the code. next LLM calls would misinterpret the code and miss context.
@@ -20,15 +24,13 @@
20
24
 
21
25
  - NEVER do `(x as any).field` or `'field' in x` before checking if the code compiles first without it. the code probably doesn't need any or the in check. even if it does not compile, use think tool first! before adding (x as any).something, ALWAYS read the .d.ts to understand the types
22
26
 
23
- - after any change to typescript code ALWAYS run the `pnpm typecheck` script of that package, or if there is no typecheck script run `pnpm tsc` yourself
24
-
25
27
  - do not declare uninitialized variables that are defined later in the flow. instead use an IIFE with returns. this way there is less state. also define the type of the variable before the iife. here is an example:
26
28
 
27
29
  - use || over in: avoid 'x' in obj checks. prefer doing `obj?.x || ''` over doing `'x' in obj ? obj.x : ''`. only use the in operator if that field causes problems in typescript checks because typescript thinks the field is missing, as a last resort.
28
30
 
29
31
  - when creating urls from a path and a base url, prefer using `new URL(path, baseUrl).toString()` instead of normal string interpolation. use type-safe react-router `href` or spiceflow `this.safePath` (available inside routes) if possible
30
32
 
31
- - for node built-in imports, never import singular names. instead do `import fs from 'node:fs'`, same for path, os, etc.
33
+ - for node built-in imports, never import singular exported names. instead do `import fs from 'node:fs'`, same for path, os, etc.
32
34
 
33
35
  - NEVER start the development server with pnpm dev yourself. there is no reason to do so, even with &
34
36
 
@@ -36,6 +38,7 @@
36
38
 
37
39
  - if you encounter typescript lint errors for an npm package, read the node_modules/package/\*.d.ts files to understand the typescript types of the package. if you cannot understand them, ask me to help you with it.
38
40
 
41
+ - NEVER silently suppress errors in catch {} blocks if they contain more than one function call
39
42
  ```ts
40
43
  // BAD. DO NOT DO THIS
41
44
  let favicon: string | undefined;
@@ -0,0 +1,85 @@
1
+ # Vercel Sandbox
2
+
3
+ use `sandbox` CLI to run commands in ephemeral remote Linux VMs. useful for isolated code execution, testing untrusted code, or running agent-generated scripts safely.
4
+
5
+ ## running commands
6
+
7
+ sandbox runs commands non-interactively (no TTY needed):
8
+
9
+ ```bash
10
+ sandbox run echo "hello world" # one-shot command
11
+ sandbox run node -e "console.log(2+2)" # run node code
12
+ sandbox run python -c "print('hello')" # run python (use --runtime python3.13)
13
+ sandbox run --rm ls -la # auto-cleanup after command
14
+ ```
15
+
16
+ for multiple commands, manage sandbox lifecycle manually:
17
+
18
+ ```bash
19
+ ID=$(sandbox create -q) # create sandbox, get ID
20
+ sandbox exec $ID node -e "console.log('step 1')"
21
+ sandbox exec $ID node -e "console.log('step 2')"
22
+ sandbox stop $ID # cleanup
23
+ ```
24
+
25
+ ## installing packages
26
+
27
+ ```bash
28
+ sandbox run --sudo dnf install -y golang # system packages (Amazon Linux)
29
+ sandbox run npm install express # npm packages
30
+ sandbox run pip install requests # python packages (with --runtime python3.13)
31
+ ```
32
+
33
+ available runtimes: `node22` (default), `python3.13`
34
+
35
+ ## file paths
36
+
37
+ sandbox has an isolated filesystem. the writable directory is `/vercel/sandbox`:
38
+
39
+ ```bash
40
+ sandbox exec $ID touch /vercel/sandbox/foo.txt # works
41
+ sandbox exec $ID touch /home/test.txt # permission denied
42
+ ```
43
+
44
+ ## copying files
45
+
46
+ use `sandbox cp` to transfer files between local and remote:
47
+
48
+ ```bash
49
+ # copy local file to sandbox
50
+ sandbox cp ./script.js $ID:/vercel/sandbox/
51
+
52
+ # copy from sandbox to local
53
+ sandbox cp $ID:/vercel/sandbox/output.txt ./
54
+
55
+ # copy directory
56
+ sandbox cp -r ./src $ID:/vercel/sandbox/
57
+ ```
58
+
59
+ ## reading logs
60
+
61
+ command output is returned directly from `sandbox exec` and `sandbox run`:
62
+
63
+ ```bash
64
+ # stdout is printed directly
65
+ sandbox run node -e "console.log('hello')"
66
+ # Output: hello
67
+
68
+ # capture output in a variable
69
+ OUTPUT=$(sandbox exec $ID node -e "console.log(JSON.stringify({ok:true}))")
70
+ echo $OUTPUT
71
+
72
+ # stderr is also printed
73
+ sandbox run node -e "console.error('warning')"
74
+ ```
75
+
76
+ for long-running processes or debugging:
77
+
78
+ ```bash
79
+ # write logs to file, then retrieve
80
+ sandbox exec $ID bash -c "node app.js > /vercel/sandbox/app.log 2>&1"
81
+ sandbox cp $ID:/vercel/sandbox/app.log ./
82
+
83
+ # or tail logs in real-time (requires -t for streaming)
84
+ sandbox exec -t $ID tail -f /vercel/sandbox/app.log
85
+ ```
package/vercel.md ADDED
@@ -0,0 +1,108 @@
1
+ ---
2
+ name: vercel
3
+ description: List deployments, check build status, and stream runtime logs with Vercel CLI
4
+ tags: [vercel, deployment, logs, cli]
5
+ ---
6
+
7
+ # vercel
8
+
9
+ use the vercel cli to list deployments, check build status, and read runtime logs.
10
+
11
+ ## listing deployments
12
+
13
+ ```bash
14
+ vercel list # list recent deployments
15
+ vercel list --prod # list only production deployments
16
+ vercel list --limit 5 # limit results
17
+ ```
18
+
19
+ ## deployment status and build logs
20
+
21
+ ```bash
22
+ vercel inspect <deployment-url-or-id> # get deployment info and status
23
+ vercel inspect <deployment-url-or-id> --logs # print build logs
24
+ vercel inspect <deployment-url-or-id> --logs --wait # wait for build to complete, stream logs
25
+ vercel inspect <deployment-url-or-id> --wait --timeout=5m # wait with timeout
26
+ ```
27
+
28
+ ## reading runtime logs
29
+
30
+ runtime logs only stream new logs from when you start the command. there is no way to fetch historical logs via cli.
31
+
32
+ ```bash
33
+ vercel logs <deployment-url-or-id> # stream logs for 5 minutes
34
+ vercel logs <deployment-url-or-id> --json # output as json (useful for filtering)
35
+ ```
36
+
37
+ > the `--since`, `--limit`, and `--follow` options are deprecated and ignored. use the vercel dashboard for historical logs.
38
+
39
+ ## reading logs for latest deployment
40
+
41
+ get the latest production deployment url and stream its logs:
42
+
43
+ ```bash
44
+ DEPLOY_URL=$(vercel list --prod --limit 1 | tail -n 1 | awk '{print $1}')
45
+ vercel logs "$DEPLOY_URL"
46
+ ```
47
+
48
+ for preview deployments:
49
+
50
+ ```bash
51
+ DEPLOY_URL=$(vercel list --limit 1 | tail -n 1 | awk '{print $1}')
52
+ vercel logs "$DEPLOY_URL"
53
+ ```
54
+
55
+ ## background log streaming with tmux
56
+
57
+ since `vercel logs` streams indefinitely (up to 5 minutes), use tmux to run it in background while you trigger errors. see tmux.md for more details.
58
+
59
+ 1. get latest deployment url:
60
+
61
+ ```bash
62
+ DEPLOY_URL=$(vercel list --prod --limit 1 | tail -n 1 | awk '{print $1}')
63
+ ```
64
+
65
+ 2. start log streaming in background:
66
+
67
+ ```bash
68
+ tmux new-session -d -s vercel-logs-prod "vercel logs $DEPLOY_URL --json"
69
+ ```
70
+
71
+ 3. trigger an error (e.g. hit an endpoint that fails):
72
+
73
+ ```bash
74
+ curl -s "https://$DEPLOY_URL/api/some-endpoint" || true
75
+ ```
76
+
77
+ 4. read captured logs:
78
+
79
+ ```bash
80
+ tmux capture-pane -t vercel-logs-prod:0 -S -100 -p
81
+ ```
82
+
83
+ 5. filter for errors with jq:
84
+
85
+ ```bash
86
+ tmux capture-pane -t vercel-logs-prod:0 -S -200 -p | jq -s 'map(select(.level == "error"))'
87
+ ```
88
+
89
+ 6. kill the session when done:
90
+
91
+ ```bash
92
+ tmux kill-session -t vercel-logs-prod
93
+ ```
94
+
95
+ ## timeout wrapper
96
+
97
+ if you need logs for a fixed duration without tmux:
98
+
99
+ ```bash
100
+ timeout 30s vercel logs <deployment-url> --json > logs.json
101
+ ```
102
+
103
+ ## limitations
104
+
105
+ - runtime logs stream only, no historical fetch via cli
106
+ - logs retained 1 hour (cli) or 3 days (dashboard)
107
+ - build logs stored indefinitely (truncated at 4MB)
108
+ - for long-term storage use log drains (pro/enterprise)
package/vitest.md CHANGED
@@ -1,23 +1,29 @@
1
1
  # testing
2
2
 
3
- do not write new test files unless asked. do not write tests if there is not already a test or describe block for that function or module.
3
+ .toMatchInlineSnapshot is the preferred way to write tests. leave them empty the first time, update them with -u. check git diff for the test file every time you update them with -u
4
+
5
+ never use timeouts longer than 5 seconds for expects and other statements timeouts. increase timeouts for tests if required, up to 1 minute
6
+
7
+ do not create dumb tests that test nothing. do not write tests if there is not already a test file or describe block for that function or module.
8
+
9
+ if the inputs for the tests is an array of repetitive fields and long content, generate this input data programmatically instead of hardcoding everything. only hardcode the important parts and generate other repetitive fields in a .map or .reduce
4
10
 
5
11
  tests should validate complex and non-obvious logic. if a test looks like a placeholder, do not add it.
6
12
 
7
- use vitest to run tests. tests should be run from the current package directory and not root. try using the test script instead of vitest directly. additional vitest flags can be added at the end, like --run to disable watch mode or -u to update snapshots.
13
+ use vitest or bun test to run tests. tests should be run from the current package directory and not root. try using the test script instead of vitest directly. additional vitest flags can be added at the end, like --run to disable watch mode or -u to update snapshots.
8
14
 
9
15
  to understand how the code you are writing works, you should add inline snapshots in the test files with expect().toMatchInlineSnapshot(), then run the test with `pnpm test -u --run` or `pnpm vitest -u --run` to update the snapshot in the file, then read the file again to inspect the result. if the result is not expected, update the code and repeat until the snapshot matches your expectations. never write the inline snapshots in test files yourself. just leave them empty and run `pnpm test -u --run` to update them.
10
16
 
11
17
  > always call `pnpm vitest` or `pnpm test` with `--run` or they will hang forever waiting for changes!
12
18
  > ALWAYS read back the test if you use the `-u` option to make sure the inline snapshots are as you expect.
13
19
 
14
- - NEVER writes the snapshots content yourself in `toMatchInlineSnapshot`. instead leave it empty and call `pnpm test -u` to fill in snapshots content.
20
+ - NEVER write the snapshots content yourself in `toMatchInlineSnapshot`. instead leave it as is and call `pnpm test -u` to fill in snapshots content. the first time you call `toMatchInlineSnapshot()` you can leave it empty
15
21
 
16
22
  - when updating implementation and `toMatchInlineSnapshot` should change, DO NOT remove the inline snapshots yourself, just run `pnpm test -u` instead! This will replace contents of the snapshots without wasting time doing it yourself.
17
23
 
18
24
  - for very long snapshots you should use `toMatchFileSnapshot(filename)` instead of `toMatchInlineSnapshot()`. put the snapshot files in a snapshots/ directory and use the appropriate extension for the file based on the content
19
25
 
20
- never test client react components. only server code that runs on the server.
26
+ never test client react components. only React and browser independent code.
21
27
 
22
28
  most tests should be simple calls to functions with some expect calls, no mocks. test files should be called the same as the file where the tested function is being exported from.
23
29