Borrowing it
Nothing to install: this file belongs to michaelwilhelmsen/humla. Take a copy, put it at the same path in your own repository, and replace the rules that are about this project with yours.
curl -O https://raw.githubusercontent.com/michaelwilhelmsen/humla/main/CLAUDE.mdgit clone --depth 1 https://github.com/michaelwilhelmsen/humlaWrote this? Show the measurements
A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.
[](https://agentmods.dev/instructions/michaelwilhelmsen/humla/claude-md)<a href="https://agentmods.dev/instructions/michaelwilhelmsen/humla/claude-md"><img src="https://agentmods.dev/badge/instructions/michaelwilhelmsen/humla/claude-md/github.svg" alt="Measured on agentmods" height="20"></a>Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.
<a href="https://agentmods.dev/instructions/michaelwilhelmsen/humla/claude-md"><img src="https://agentmods.dev/badge/instructions/michaelwilhelmsen/humla/claude-md.svg" alt="Reviewed on agentmods" width="80" height="20"></a>What it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5.1 | $0.19981 | $0.19981 |
| Opus 5 | $0.09990 | $0.09990 |
| Sonnet 5 | $0.03996 | $0.03996 |
| Haiku 4.5 | $0.01998 | $0.01998 |
Grade A, and why
humla CLAUDE.md scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 5d ago.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Nothing flagged
None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.
How it starts
The opening of the file, as written. The whole thing — 303 lines — stays where its author put it; the contents beside it link to each section on GitHub.
Humla — project notes
What this app is
Humla is a personal macOS meeting-notes app inspired by Granola. You take freeform notes during a meeting; in parallel the app records mic + system audio, transcribes it, and produces an AI summary that fuses your notes with the transcript. Personal/small-team, not SaaS — your data, your API keys, local SQLite, no backend.
The name is Norwegian for "bumblebee".
Core capabilities
- Hybrid capture (parallel streams) — mic + macOS system audio recorded simultaneously via a Swift sidecar, kept as two separate streams end-to-end (no mixdown). Each gets its own VAD-bounded chunk WAVs, its own full.wav, its own Whisper invocations with its own
prior_contexttrail. In-person meetings produce only mic chunks (system stays silent → no chunks emitted) and the diarizer runs on the mic stream so multiple humans in the same room get distinct labels. Remote calls produce both, and both get diarized — the mic is never assumed to hold a single person just because the system stream has content.Youis earned, not assigned: it survives only when the mic diarize resolves to exactly one voice. - Four STT providers — OpenAI (whisper-1 / gpt-4o-transcribe / mini / diarize), on-device Whisper via Metal, Deepgram (nova-3, nova-2, base), and Groq (whisper-large-v3-turbo). All slot into the
stt::BatchSttAdaptertrait so the dispatch path is provider-agnostic. - Per-language routing —
transcribe_config(typed JSON, single source of truth) is{ default: ProviderConfig, per_language: BTreeMap<String, ProviderConfig> }. Resolution at chunk time: per-note language → per-language override → default. E.g. Norwegian → local NB Whisper, English → Deepgram Nova-3, default → OpenAI whisper-1. - Whisper quality preset — Fast (greedy) / Balanced (beam=3) / Quality (beam=5, low no_speech threshold) for the local provider; bundles sampling strategy + confidence thresholds together so the user picks one knob.
- Per-note transcription language — global Settings → Language is the default; each note has its own language chip that overrides for that note.
- Offline diarization on stop —
speaker-diarizeSwift sidecar runs afterrecording_stop. Two engines selectable via thediarize_modelsetting: Community-1 (FluidAudio'sOfflineDiarizerManager— community-1 segmentation + VBx clustering with PLDA) and Sortformer (NVIDIA end-to-end, 4-speaker cap). Branches on which streams produced content: mic-only diarizesmic_full.wavand emitsSpeaker 1:/Speaker 2:; when both streams have content, both are diarized and numbered off one shared counter so a mic speaker and a system speaker can never collide on a number (build_hybrid_labels). The old shortcut — hard-label every mic chunkYou:and diarize onlysys_full.wav— meant a single stray system chunk (a notification chime, a few seconds of video) collapsed an entire in-person meeting onto oneYou:line, since presence of any sys chunk routed the recording into remote-call mode.You:is now applied only when the mic diarize resolves to exactly one voice. - Speaker rename + colour-coded pills — each unique speaker gets one of four design-token colours (interactive blue, success green, warning gold, accent red, cycling for 5+). A chip strip above the transcript lets the user click any speaker to rename inline; rename is a regex line-anchored rewrite of the transcript text — no separate metadata table.
- Two-source summaries — model gets
[Notater](typed notes) and[Transkripsjon](transcript) as two labelled blocks in one user message. Preset prompts are deliberately minimal (kind of summary + language only); the only source-trust signal is the parenthetical tags[Notater] (user-written)/[Transkripsjon] (auto)— the old explicit "favour notes for intent, transcript for facts" rule was dropped. An empty side is sent as(ingen)rather than omitted, so thinking models don't second-guess a missing block. - Per-note presets — Meeting / 1:1 / Lecture / Interview / Brainstorm / Voice memo, each with its own summary prompt. Custom prompts also supported (rows in
summary_promptstable, referenced ascustom:<id>). - Custom vocabulary — per-user list of names and tech terms biasing decoding. Threaded through Whisper-shaped providers as
initial_prompt, Deepgram askeyterm(Nova-3) orkeywords(other models) query params. - Trailing transcript context — every chunk's transcription receives the last ~150 committed words as
prior_context(Whisper'sinitial_promptslot for OpenAI/Local/Groq; Deepgram ignores it because itskeywordsis a per-token boost, not a continuation primer). Single biggest mitigation against silence-driven hallucinations and proper-noun drift. - VAD-bounded chunks — sidecar rotates each chunk at natural speech pauses (min 1.0 s / max 15 s / 500 ms silence trigger) instead of a fixed timer.
- Reasoning-model temperature handling — gpt-5.x / o-series reject
temperature;openai::summarizedetects viais_reasoning_model()and omits. - Local-LLM summary tuning — Ollama path goes through the native
/api/chatendpoint (not the OpenAI-compat shim at/v1) sothinkis a real toggle instead of being template-stripped.num_ctxis sized adaptively from the actual prompt length +num_predictbudget, rounded up to powers of two, bounded[8192, 65536]— a flat 65K KV cache was OOMing the model runner on tighter Macs (the cache is multi-GB on top of model weights).keep_alive: 0releases the model immediately after each summary so RAM frees up. Sampling is model-family-aware (sampling_profile(model, think)): Qwen models get the loop-breaker profile (presence_penalty=1.5,frequency_penalty=0.5,repeat_penalty=1.0) that breaks Qwen 3.5's thinking-phase loop class; every other family (e.g. the recommendedgemma4:12b-mlx) gets neutral defaults (presence/frequency=0,repeat_penalty=1.1) rather than penalties tuned for Qwen. Onlyollama_chat_stream(the summary path) carries this; the agentic tool-calling step (ollama_chat_step) uses neutraltemperature=0. Cloud OpenAI summary streams and sharespost_chatwith the chat path, which retries transientKind::Requesterrors twice (500 ms / 1.5 s backoff) — covering the case where reqwest tries to reuse a pooled HTTP/2 connection that OpenAI's edge has half-closed. Retries can't rescue a connection reaped while the model reasons, which is why the path streams at all; see theopenai.rsrow. - Your notes over MCP (#172) — Humla ships its own Model Context Protocol server, so Claude Code, Codex or any other MCP client can search and read the library from wherever the user works. Six read-only tools (
search_notes,get_note,get_transcript,list_notes,list_folders,list_clients), off until explicitly enabled in Settings → General → Integrations, which also offers a ready-to-paste config snippet per client. Read-only in this version, and no tool returns or references an audio file —keep_audiostays the single absolute gate on audio (#24) and this is not an exception above it. The workspace is resolved, never accepted as an argument, so Personal and workspace notes can't reach each other however a client asks. Search is keyword-only on purpose: an agentic client substitutes repeated queries for vector recall, which buys no API key, no per-query cost, no Keychain prompt and no network. The gap that does bite is cross-language — the index is lexical, so a query in the wrong language returns nothing, and the fix chosen is to carry each note's language as data (lang:on every hit and row,languageas a filter) rather than to name any language in a tool description. Shipping it first-party is a maintenance decision as much as a feature: Granola never did, so its users wrote nine servers against its local store, and the schema became a public API maintained by strangers. - A Note names itself (#90) — a Note whose Title Humla owns gets a short phrase derived from the head of its own content.
menubar::is_replaceable_titleis the single answer to "may this Title be replaced?": empty, aRecording 19 Aug 14:32timestamp, or theImported audioimport fallback. A real filename stem is the name the user gave the file and is never touched. Two triggers, both content-settled: the post-stop recording chain, spawned concurrently with the diarize pass rather than after it — the transcript is already final by then (recording_stopdrains every in-flight transcribe before it snapshots), and what diarization adds isSpeaker N:prefixes a title has no use for, so waiting cost minutes on a long meeting for nothing — and a debounced body-settled checkpoint in the Note view for a Note that was typed and never recorded. It goes afterrecord_detected_language, which resolvesautoto what was actually spoken, because the title's language directive reads it. Deliberately not on summary completion — summarising is a button the user presses, so that trigger would leave the motivating case (a menu-bar recorder who never opens the Note) on its timestamp forever — and deliberately not during a recording, where it would spend GPU exactly when local Whisper needs it. The call reuses the summary path'sresolve_provider, forcesthink: false, and substitutes a small non-reasoning model when the configured summary model reasons; it does not stream, so the summary panel never sees it. Failure is silent on the automatic path (a user who never asked for a Title must not be told one failed) and loud on ⋯ → Regenerate title, which bypasses eligibility because the user asked. One-shot by construction: once written, a Title is no longer replaceable, so a Note recorded in several takes keeps the first take's Title and regenerate is the escape hatch. The call is bracketed by atitle_statusevent (per-note, likesummary_status), which the open Note view answers by standing a shimmer in for the title box — the text there is about to be replaced, so dimming it would leave the wrong answer on screen while the right one loads.is_replaceable_titleis mirrored in TS asisReplaceableTitle(src/lib/noteSync.ts) — change both. - Transcribe on your terms (#146) — Transcribe manually (Settings → Recording → Audio retention) trades the live transcript for a quiet Mac: the meeting is captured and its per-source streams retained, and nothing reaches a provider until the user presses Transcribe on the note. Gated twice, deliberately.
keep_audiois the outer gate and stays so — deferring on a device that stores no audio would discard the meeting, and force-retaining behind the user's back is the exact class of exception #24 exists to remove (sessions::defer_transcriptionowns the rule; Settings shows the toggle only once retention is on, so the UI and the backend agree). And it applies only to on-device Whisper, resolved through the note's own language: what the setting buys is a Mac that isn't running Metal inference for an hour, and a cloud provider costs the machine nothing, so a per-language override routing one note to Deepgram keeps its live transcript while a Norwegian note defers. The decision is read once, atrecording_start— flipping the setting mid-meeting leaves the running capture alone, since half a transcript is worse than either regime. Each take carries a persistedtranscribedflag insessions.json(defaulting true, so every take in every existing library reads back as transcribed rather than offering to re-transcribe the world), and it is independent of the setting's current value: turning Transcribe manually off later still leaves old takes transcribable. Pressing Transcribe replays each pending take's retained audio through the same decode → VAD chunk → transcribe → diarize pipeline a file import uses, oldest first — because each take's timeline is numbered off the takes before it. Three things make it not-a-recording, each load-bearing: it never takes the single live-capture slot, so replaying an hour of audio doesn't stop the user recording their next meeting; it reports on its own per-notetranscribe_statuschannel rather thanrecording_status, so it can't blank the bar of a recording running on another note (DiarizePolicy::report_phaseis what keeps the shared diarize path quiet); and its chunks never stream intonote.transcript— the text arrives once, fromrebuild_note_transcriptover every session's timeline, so a replay that dies half-way leaves nothing behind that no timeline accounts for (ADR-0004), and a newly transcribed take lands at its own position in the note even when a later take was already transcribed (whichcombine_with_snapshot, appending to the end, could not). A diarize that can't run is not a failure here (LabelFallback::Unlabelled): the text lands withoutSpeaker N:prefixes rather than being thrown away with the labels. A take that transcribed nothing is deliberately not marked transcribed — silence and "every chunk failed" are indistinguishable from there, and the second has to stay retryable.note_sessionsanswers both halves of "would Transcribe do anything" ascanTranscribe(untranscribed and the raw streams still on disk —session_has_replayable_audio, notsession_has_audio, since a take reduced to its mixedplayback.wavstill has audio and still can't be replayed), so a take swept away by "Delete stored audio" never offers a button that can only fail.- The same machinery re-transcribes, from a
RefreshCwicon button in the Transcript panel beside Copy — mirroring the Summary panel's regenerate, because the two panels' actions shouldn't read as different kinds of control.sessions::TranscribeScopeis the difference and the whole of it (mirrored by the"pending" | "all"union onipc.transcribeNote— change both):Pendingfinishes what a deferred capture left waiting,Allre-runs every take whose raw streams survive (canRetranscribe), which is the fix for a recording that came back off the wrong language or the wrong model.takes_to_transcribeis the single answer both surfaces mirror, and it filters on replayable audio under both scopes so a run can never be offered that would silently skip every take.Allreaches the legacy flat take thatPendingcan't (it reads backtranscribed: true) — deliberately, since a note recorded before per-session storage is exactly the kind whose language needs correcting. And becauseAllreplaces text the note already had whiledb::set_transcriptkeeps no history, the command snapshots a note revision first, so the run is undoable from the note's existing revision list;Pendingneeds none, since it only adds takes that had no text. A take that fails mid-run stops the run without discarding what the takes before it committed — their timelines are written and their text is in the note, so the checkpoints and the asset push still happen, and the failure becomes the outcome only after. - A session's scalar metadata stays immutable,
duration_msincluded.cloud-sync'spush_sessionderives a session's last-write-wins key from its ownstarted_aton the stated grounds that "index / started_at / duration / streams never change", so aduration_mscorrected after the fact re-pushes under a byte-identical key and converges only because the server's hook compares<rather than<=. That is why a deferred take's length is taken from the sidecar'sfull_recordingevent at capture time (CaptureSink::captured_duration_ms→finalize_session, which prefers the timeline and falls back to this) rather than backfilled once its timeline exists.record_transcribed_taketherefore writes the flag and nothing else.
- The same machinery re-transcribes, from a
- The note views are a card grid — All notes and Folder render
NoteCardin a.nd-notegrid, with no date headings: the card carries its own full date (formatNoteDate) because there is nothing above it to say when. Each card is date, title, a four-line excerpt, then state · client · folder. The excerpt prefers the summary's opening line (noteExcerpt) — the distilled version of everything else on the note — falling back to typed body, then to the transcript with speaker labels stripped. "Opening line" is gated, not literal: horizontal rules, model preamble ("Her er …", anything ending in:) and fragments under 20 chars are stepped over — the first of them kept only when the summary holds nothing stronger — and a fragment body likewise yields to the transcript. Multi-select is unchanged from the old list row (#19): the same Cmd/Shift-click, Space, Esc and checkbox rules, with the checkbox moved to the card's top-right corner.- A borderless card needs a recessed ground.
.nd-welldarkens the scroll region a few percent, because the card's edge is entirely tone against what it sits on — and graphite declares--color-canvasand--color-surfaceboth as#ffffff, which leaves a white card on a white page with nothing but a shadow. Darkening is the one move that works in every theme and both modes; in dark the surface is already the lighter of the pair, so pushing the ground down widens the same gap. For the same reason selection cannot be a fill alone —--color-accent-softis tuned against the canvas, and graphite's#efefeflands darker than the well, so a picked card would recede. The accent ring is what reads everywhere. Everything else the card owns comes from the theme — radius from--radius-card, shadow from--shadow-card— so it is the third inset card in fact and not only in description. Underprefers-contrast: morethe card takes a real border and drops the shadow: tone-as-edge is exactly what that preference asks us to stop doing. .nd-notegrid's track floor isminmax(min(var(--card-min, 300px), 100%), 1fr). Themin()is load-bearing — a bareminmax(300px, 1fr)cannot shrink past its floor and overflows the view sideways once the body column is narrower than one card, which it is at the layout's own minimum width.
- A borderless card needs a recessed ground.
- Folders — flat folder list, per-note assignment; sidebar search matches note titles/bodies/transcripts and renders a flat result list annotated with each note's folder name.
- Chat over your notes — an agentic retrieval loop (
chat/), surfaced as the Chat tab of the Note right panel. The assistant searches and reads notes with three tools (search_notesover FTS5 keyword + semantic embeddings,get_note,list_notes), streams its answer, and cites the notes it drew from as chips that navigate to the source. Two per-conversation retrieval filters live on the conversation row and bind every turn regardless of what the model asks for: breadth (note|folder|all— what is in reach) and the authorship pin (owner_filter, a user id — whose notes are in reach, workspace-only, surfaced as the "Created by me" toggle beside the breadth picker). Multiple conversations per note, with history; a conversation can be renamed or deleted (hard, with a confirm — there is no Trash for chat) from the sidebar row's right-click menu, the/chatapp bar's ⋯, or the note pane's history popover. Runs on a chat provider configured separately from transcription and summary (Settings → Chat; OpenAI or a local server). The local provider is still stored as"ollama"but is not Ollama-only (#179): the adapter picks Ollama's native/api/chaton:11434and plain OpenAI-compat everywhere else, the same callsummarize_with_basemakes — mirrored in TS asisOllamaUrl, which decides only what advice to print. The embedder for semantic retrieval has its own address and name (embed_base_url/embed_model, both blank = the chat server andembeddinggemma), because the chat server is frequently not the one that can embed:mlx_lm.serverserves no/v1/embeddingsroute at all, llama-server wants its own process, and LM Studio names the same model differently. Settings probes it with a real one-word embedding rather than reading the chat server's model listing — a listing cannot tell you a route is missing. A reachable embedder and an embedded corpus are two facts, sincechunk_embeddingsis keyed(text_hash, model)and search filters on the model: naming a different embedder leaves every existing vector unreachable, sochat_unembedded_note_countsays how many notes that is andchat_embed_missingruns the same backfill the next launch would.localChatHintis the one readiness ladder behind both the Settings tab and the Note pane's setup prompt — the two answered the same question in two copies, and only one of them got fixed the first time. In a workspace, turns route to humla-cloud and retrieval happens server-side. Reachable inside a note, at its own library-wide/chatroute, and — scoped to one folder — at/folder/:id/chat("Chat about this folder" on the folder row's context menu, #110).- A conversation's scope is
(tenant, scope, scope_id)—note(the note id),folder(the folder id, #110) orglobal(a fixed sentinel). The three populations never leak into each other, locally or server-side. Breadth is a live filter within a thread, not its identity: a Note's pane can widen to its folder or the library, but a note-less target is pinned to its own reach (allfor/chat,folderfor a folder chat) because with no anchor the target's identity is its reach —pinned_breadth/targetPinsScopeown that rule on each side. Deleting a folder hard-deletes its conversations (they have no Trash and their whole reach was that folder); its notes only reparent, so the Sidebar confirms only when threads would actually be lost.ChatTarget::from_idstakes the note and folder ids as alternatives — both at once is an error, and an empty id is an error under either. - Opening a pane drafts or resumes, by target (
resumes_on_openin Rust,targetResumesOnOpenin TS — mirrored, change both)./chatdrafts: it opens on an unsaved conversation with the prompt cards showing, persisting nothing until the first turn, so an abandoned thread leaves no row and "+" is a local reset that costs no IPC. A note's Chat tab resumes that note's most-recent thread, deliberately — a note is an anchor, so continuing the same line of thinking is the plausible default there. A drafting pane's breadth and authorship pin live in the pane and ride in onchat_send(DraftSettings), which is what preserves the #61/#103 guarantee without the lazy row that used to be hidden from the list yet still resolved to by the next send. Conversation lists hide zero-message rows for drafting targets only (in a note, an empty thread is the draft being resumed) — in SQL for Personal so paging stays honest, and off the server'smessage_countfor a workspace, whose messages never land in the local table.
- A conversation's scope is
- Every word of the transcript has a timeline behind it (#169, ADR-0004) — the styled reader renders from the merged timelines, so text
note.transcriptcarries and no timeline accounts for is invisible there, and the first rebuild (rebuild_note_transcript, reached by cycling a speaker label, deleting a chunk, re-diarizing or unifying) deletes it outright — out of the summary, chat retrieval and embeddings with it. It arose becausecombine_with_snapshotprepends the prior take's transcript whileserialize_timelinesees the current session's chunks alone, so any recording that landed text but wrote no session assets left an orphaned prefix. Three defences, in order:- Prevention.
diarize_and_applyno longer returns early when the diarize model is missing; it serializes the chunks with an empty label — and the label alone, since word timings are orthogonal to who spoke — so the take still writes a session — which also gives a later re-diarize somewhere to attach to. - Repair on open.
note_timeline_repaircomparescomparable_wordsof the transcript against the timelines' projection;orphaned_prefixrecovers the leading lines the projection misses andsynthesize_orphan_timelinewrites them as a session at manifest index 0 (named "Earlier transcript", never "Recording 0" — it was never a take). Idempotent, and it runs after the workspace session pull so a still-arriving timeline can't be duplicated. A note with no timeline at all is left alone — it renders the textarea and hides nothing, and a synthesized session would take its free-text editing away. - Render-time guard. When
coversTranscriptcomes back false — a timeline present but short because malformed lines were skipped, an asset that never downloaded — the note falls back toTranscriptViewover the whole string. The comparison is the backend's; the client never re-derives the grouping rule (Rust groups on label alone,groupTimelineon label and session, deliberately), and comparisons normalize word sequences, never line counts. One more mirrored pair to change together:split_label(Rust) andparseTranscriptLines(Note.tsx) are the same "Label:prefix" rule, and the repair splits lines by the first while the reader draws them by the second. Separately,commit_rebuilt_transcriptrefuses to commit an empty projection over a non-empty transcript, which protects pre-sessions notes that have a transcript and no timeline at all from being blanked by one click.
- Prevention.
- Transcript editing routes through the timeline (#170) — on a note that has a timeline, the styled reader renders from it and
note.transcriptis a projection of it, so editing is per turn: a hover pencil opens that turn in place, and committing callsnote_timeline_set_chunk_textwith the whole run of chunk indices the turn spans (TimelineGroup.indices), which writes the text into the lowest index, empties the rest, and re-derives the transcript from every session's timeline — the same pathnote_timeline_set_chunk_labelandnote_timeline_delete_chunkalready take. Word timings on an edited turn are dropped (they describe words that are gone); its bounds are kept, so it still highlights during playback and only per-word karaoke is lost, on that turn. The old panel-wide textarea wrote the derived copy and touched no timeline, so the edit was invisible in the reader — permanently — while summary, chat and embeddings read the edited string. A note with no timeline keeps the whole-transcript textarea (TranscriptEditor): with no timeline there is no second copy to orphan. Both are locked while a recording is in flight.
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- 5d ago Changed · +1 lines · +561 tokens per session 4022c9cf52c4
- 9d ago First seen · 302 lines · 19,420 tokens per session scan A dc28bf518bb5
humla CLAUDE.md is an instructions file published in the GitHub repository michaelwilhelmsen/humla (276 stars, last pushed 6d ago), licensed MIT. It adds 19,981 tokens to every session, about $0.0999 per session on Opus 5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-30.
Other instructions, from other repositories
next.js AGENTS.md
AGENTS.md instructions for vercel/next.js, covering next.js development guide, codebase structure, monorepo overview, core package: packages/next and other important packages.
codex AGENTS.md
AGENTS.md instructions for openai/codex, covering rust/codex-rs, the codex-core crate, code review rules, crate api surface and model visible context.
vscode buildNext.instructions.md
Working notes and architecture documentation for the new esbuild-based build system in build/next. Use when making changes to the new build pipeline (transpile/bundle commands, NLS plugin, source-map handling, resource copying, or self-hosting watch tasks).
vscode oss-third-party-notices.instructions.md
Instructions for microsoft/vscode, covering vs code oss third-party-notices pipeline, architecture, pipeline flow in ci, applying the notice (cutover) and fallback chain (never fail the build).
langchain AGENTS.md
AGENTS.md instructions for langchain-ai/langchain, covering global development guidelines for the langchain monorepo, corridor security analysis, project architecture and context, monorepo structure and development tools & commands.
deepseek-harness AGENTS.md
AGENTS.md instructions for deepseek-ai/deepseek-harness, covering agents.md, pre-stable apis and released session data, repository layout, commands and host sandbox failures.