@aurelienbbn/agentlint-plugin-core

中文文档
0.2.3发布于 2026/10/14MITTypeScriptES Module构建来源已验证近 30 天下载 2466

Custom agentlint rules for general TypeScript projects.

原始使用文档
文档目录8 节
  1. Start with 2 rules, not 25
  2. Rules
  3. Ownership: operations stay with their module
  4. 🔒 Test drift: the author doesn't accept it
  5. Declared invariants and hotspots
  6. Migration: re-review earlier acceptances
  7. Registered contract inventory
  8. Credited concepts

@aurelienbbn/agentlint-plugin-core

npm downloads CI license node

25 agentlint reviews for any TypeScript repo: a deterministic trigger finds the spot, an agent or a human settles it.

[!WARNING] Requires the engine @aurelienbbn/agentlint >=0.3.0 <0.9.0 as a peer. Evidence.

strictPreset   █████████████            13  settled rules
starterPreset  ██                        2  boundary-resilience, bounded-work
opt-in         ████████████             12  exported, in no preset: calibrate first

Start with 2 rules, not 25

agentlint init --preset "@aurelienbbn/agentlint-plugin-core#starterPreset"
agentlint rules test
agentlint rules scan --review
agentlint next --format json

init keeps an existing config and prints the install command; never installs. Calibrate bindings before requiring agentlint check --all.

import { defineConfig } from "@aurelienbbn/agentlint";
import { defineFallbackMasksFailure, fakeParity, strictPreset } from "@aurelienbbn/agentlint-plugin-core";

export default defineConfig({
  extends: [strictPreset],
  rules: [fakeParity, defineFallbackMasksFailure({ minFallbacksPerScope: 3 })],
});

Rules

RulePresetAuthorityLifecycleOptions (default)
abstraction-earns-keepstrict🔒 humanstateminForwardingMembers (3), forwardingRatio (0.8), interfacePattern, implementationFiles
boundary-resiliencestrict · starteragentstatenetworkCallPattern
bounded-data-accessstrictagentstate
bounded-workstrict · starteragentstate
comment-signalstrictagentstatenarrationPattern, minWordOverlapLength (4)
correlated-optional-statestrictagentstatediscriminantNames, minOptionalSiblings (2), skipNamePattern
expected-value-recomputedstrictagentstatematcherPattern, derivationCallees, maxFindingsPerFile (3)
integration-test-owns-its-boundarystrictagentstateintegrationPattern, doublePattern
operations-stay-with-ownerstrictagentstateminOperations (4), entryPattern (api.* files), packages
temporal-couplingstrictagentstateguardMessagePattern, initMethodPattern
test-behavior-coveragestrictagentstatemockPattern, outcomePattern, minInteractionShare (0.5), maxInlineSnapshotLines (12)
test-exercises-project-codestrictagentstateprojectImportPattern, workspacePackages, blackBoxModules
test-expectation-driftstrict🔒 humanchangeauthority, testFilePattern, assertionPattern, maxEvidenceLines
change-scatter-review🧪🔒 humanchangeminFiles (3), maxFindings (3), tokenPattern
fake-parity🧪agentstatefakeNamePattern, portTypePattern
fallback-masks-failure🧪agentstateminFallbacksPerScope (2), sensitiveNames
flag-forked-function🧪🔒 humanstateminFlags (2), minSitesForSingleFlag (3), includeJsx (false)
hotspot-change-review🧪🔒 humanchangehotspots (empty: silent)
isomorphic-mapping🧪🔒 humanstateminProperties (5), identityRatio (0.9)
pinned-suspect-output🧪agentstatesuspectPattern
precision-boundary-review🧪🔒 humanstateconversionCalleePattern
property-test-opportunity🧪agentstatepairPatterns, idempotentPattern, propertyApiPattern
protected-invariant-change🧪🔒 humanchangeinvariants (empty: silent)
single-use-extraction-review🧪🔒 humanstateminParameters (2), minStatements (3)
validation-discards-proof🧪agentstatenamePattern

🧪 opt-in: exported, register it yourself · 🔒 only a human can accept a finding. Presets ignore **/*.d.ts.

Promote an opt-in rule only when most of its agentlint rules scan --review findings lead to a change. Each prescribes a fix that is expensive or of unknown volume.

fetch(url);                                                          // ❌ boundary-resilience: no signal/timeout
fetch(url, { signal: AbortSignal.timeout(2_000) });                  // ✅
try { await fetch(url, { signal }); } catch (error) { logger.warn('failed', error); }  // ❌ failure discarded (logging still discards)

expect(applyDiscount(price, pct)).toBe(price - (price * pct) / 100); // ❌ expected-value-recomputed
expect(applyDiscount(200, 15)).toBe(170);                            // ✅ states it

const email = form.get("email") || "";                               // ❌ fallback-masks-failure
<span title={user.email ?? ""}>{user.id ?? ""}</span>               // ✅ JSX display default

A network try/catch returning an empty literal is reported by both fallback-masks-failure and boundary-resilience.

Boundaries: boundary-resilience, bounded-work, bounded-data-access
RuleFires onStays silent
boundary-resiliencefetch( / axios / got / ky call whose argument list has no signal, timeout, timeoutMs, deadline or AbortSignalchained fetch(url).then(...) reports once, on the call owning the args; strings and comments are blanked (fetch("/api/signal?timeout=1") fires)
catch of a try around an outbound call, or .catch(cb) on one, that discards the failure (handing it only to console.* / logger.* still discards)rethrow, branching on the error, passing it to another function, a REASON: comment of ≥ 3 words; catches around anything else
bounded-work≥ 3 sequential awaits with I/O, looped I/O, Promise.all(...map(...)) fan-out, timeoutMs/durationMs/cpuMs > 60 000a pure items.map(item => item.id)
bounded-data-accessfindMany/findAll/getMany/list/search/query/select on a repo/store/dao/client/model/collectiona non-zero first/take/limit/pageSize/perPage/maxResults or .limit(n)/.take(n)

Limits: bounded-work separates enclosing operations; a cursor alone is not a cardinality bound; cancellation is not a deadline.

Tests: behaviour coverage, recomputed expectations, integration boundaries, project imports
RuleFires onStays silent
test-behavior-coverage3 triggers, distinct keys (below)value, error, property, snapshot matchers count as outcomes
expected-value-recomputedexpect(subject(...)).toBe…(expected) where expected is computed from the subject's inputs60 * 60 * 1000, URLs from unrelated constants, expect.*, fc.property / it.prop bodies
integration-test-owns-its-boundaryan integration / e2e test that constructs doublesprint.test.ts, contract suites (int, contract are not markers)
test-exercises-project-codea test file with an it/test that imports nothing from the projectblack-box drivers; *.test-d.ts
test-behavior-coverage triggers
file-density      ≥ 3 mock constructions, no assertion pins returned state or output
interaction-only  ≥ 2 tests, or ≥ minInteractionShare of a file's tests, assert interactions only
                  (skipped when file-density already fires; lists the doubles per test)
snapshot-only     ≥ 2 tests whose only oracle is a whole-value snapshot,
                  or an inline snapshot > maxInlineSnapshotLines

toHaveBeenCalled*, toHaveBeenNthCalledWith, toHaveReturned* and the toBeCalled* aliases never count as outcomes, even through a custom outcomePattern. The judge asks, per double, whether the mocked collaborator is an unmanaged process boundary. Choosing the double and oracle stays in the testing skill. Limit: measures mock/assertion density per file, not per-test coverage.

expected-value-recomputed. Test files only. Matchers: toBe, toEqual, toStrictEqual, toBeCloseTo, toContain, toMatchObject. expected (or the local const it names, inside the same test callback) is computed when it is arithmetic with a non-literal operand, a map/filter/reduce/join/replace/toLowerCase/toFixed/round… call, or a template with ≥ 2 substitutions. Reports only when the expected expression shares an identifier with the subject call's arguments, or calls something imported from the subject's own module.

integration-test-owns-its-boundary. Path has an integration or e2e segment or name part (orders.integration.test.ts, tests/integration/..., e2e/...), or the first describe title contains "integration". Doubles: vi.fn(, createMock(, mockX(, fakeX(, or an InMemoryX/FakeX/StubX name. Strings and comments are ignored; the doubles are the evidence. One finding per file. A contract suite legitimately runs the fake next to the real thing.

test-exercises-project-code. Project-reaching specifiers: relative, @/, ~/, #..., or a name in workspacePackages, through import, export ... from, import(), require() or vi.importActual(). Black-box drivers that keep it silent: node:child_process, execa, node:fs, node:fs/promises, @playwright/test, supertest, undici, or a bare fetch( call. A monorepo importing itself by package name lists those names in workspacePackages.

Ownership: operations stay with their module

operations-stay-with-owner reports a file that calls minOperations (4) or more operations of one other module through its public entry. A module's entry is a relative import resolving to api.ts (entryPattern), or a bare specifier listed in packages (@acme/* for a scope). Operations are the value names starting lowercase; schemas, classes, constants in PascalCase and every type import are vocabulary and never count. Counted per file and per owner, so a read model calling two operations of each of three modules stays silent.

// src/qa/story.ts: ❌ replays takedown's own state moves, so the seed belongs to takedown
import { requestComposed, requestSent, requestBounced, requestReplied } from "../takedown/api.ts";

// src/ops/act.ts: ✅ one outcome the owner offers, plus its vocabulary
import { merchantsStart, type TakedownSource } from "../takedown/api.ts";

The fix is ownership, not a wider entry: move the code into the owner, or let the owner contribute it through a declaration the composition collects (a seed, a handler, a migration). Exclude the composition root (registry/, workers/) in the binding when it legitimately assembles every module. Calibrated on one modular monolith (515 files): 1 finding, the seed that replayed another feature's moves.

🔒 Test drift: the author doesn't accept it

test-expectation-drift authority defaults to "human": the change author is the party tempted to accept a finding about it. defineTestExpectationDrift({ authority: "agent" }) restores the usual default. Don't narrow include to test files: the engine filters the change by the binding before detection, and two kinds depend on source edits.

The 6 drift kinds (one finding per test or *.snap file)
KindFires when
assertion-removedmore assertion lines deleted than added; a line reappearing verbatim anywhere in the change is a move and leaves both sides first
test-removedmore it(/test( lines deleted than added, or a test file deleted while no source file with the same stem is deleted or renamed
matcher-downgradedsame expect(subject) steps down toStrictEqual › toEqual/toBe › toMatchObject › toHaveProperty/toContain/toBeDefined/toBeTruthy, toBe › toBeCloseTo, or gains expect.any/expect.anything/expect.objectContaining/expect.arrayContaining
expectation-revaluedsame subject, same matcher, different argument, and a non-test source file changed
disabled.skip, .todo, .fails or xit/xtest/xdescribe added
snapshot-rewrittenlines deleted from a .snap file or a multi-line toMatchInlineSnapshot body while source changed

Silent: added test files, additions-only hunks, stronger matchers, a test deleted with its source. The only change-lifecycle rule in the settled set.

Design: abstraction-earns-keep, correlated-optional-state, temporal-coupling, comment-signal
RuleFires onStays silent
abstraction-earns-keepbehaviour-only interface/type equal to its only recognized implementer (class, satisfies, annotated object); Impl/Default/Base/Concrete/Standard/Real affix on an implementation of a relatively imported interface; a class forwarding verbatim to one collaborator; a module whose exports all forward (replaces its per-export findings); an export passing its parameters unchanged to one callname-based matching unless interfacePattern is set; name matches when the file shows ≥ 2 implementers
correlated-optional-statenon-test interface/object type with a required status/state/kind/type/phase/step/mode/variant string-literal union + ≥ 2 optional or | null/| undefined fields*Props, *Options, *Config, *Params, *Args, *Input, *Query, *Filter, *Patch, *Update; members of a union or intersection
temporal-couplinga non-test class usable before setup, one finding per class (signals below)decorated framework fields (@property() name!: string), ! fields the constructor assigns, "User not found"
comment-signala // comment starting with create/get/set/return/initialize/loop/check/call/update/send/add/remove that shares a word with the next line; docblocks restating the signatureunits, invariants, useful public-interface docs, even short; JS type-only JSDoc tags
temporal-coupling signals
guard-throw          throw message says "not initialized/connected/started/configured/ready/loaded/opened",
                     "call x() first/before" or "must call/be initialized"
definite-assignment  undecorated `name!: T` assigned in a method, never in the constructor
nullable-init        `| null`/`| undefined` field set by exactly one init/initialize/setup/connect/open/
                     start/load/configure/bootstrap method, null-checked in ≥ 2 other methods

Factory closures aren't inspected yet. Bags of lifecycle booleans belong to no-impossible-state-bag in the type-evidence oxlint plugin.

abstraction-earns-keep counts implementers instead of reading names. Recommended interfacePattern: /^I[A-Z][a-z]|Interface$/, which keeps IPAddress silent. Factories returning fresh object literals (directly or through a local const), interface inheritance and direct/intersection type aliases count as implementation evidence. Reusing an existing instance, object spreads, abstract classes and ambient declarations do not prove another concrete implementation.

For cross-file evidence, pass exact repository-relative source paths with defineAbstractionEarnsKeep({ implementationFiles: ["src/clock.ts", "src/manual-clock.ts"] }). The engine captures these declared dependencies; the detector resolves relative named/namespace imports and re-exports against those snapshots. Same-named unrelated interfaces and comments cannot supply implementation evidence. This mode scans the repository and dependency changes invalidate decisions. It performs no filesystem reads, package-alias resolution or full TypeScript type inference; uncaptured implementations still require human review.

Exports are checked structurally, including expression arrows and async/await. Calls with transformed, reordered or defaulted arguments, and accessors over module-owned private collaborators stay silent. Factories supply evidence of an additional implementation; their own return interfaces do not become new header candidates. An abstraction that makes today's change easier passes even with one implementer.

comment-signal docblock bar, from conventions observed in upstream effect-ts/effect sources (Array.ts, Option.ts, Duration.ts):

KeepDrop
@since, @category, @example, @see@param / @returns: types live in the signature, never restated
structured prose: "When to use", "Details"a parameter list restated in ≤ 3 words per entry (review candidate)
edge cases: NaN treated as 0, clamping to [0, length]
units and precision: rounding to the nearest nanosecond
invariants: inclusive bounds, singleton instances; gotchas

JavaScript type-only JSDoc tags stay valid: they carry compile-time type information.

fallback-masks-failure 🧪: triggers and "required data"

Measure its volume on your code before enforcing. One finding per function at most; default binding excludes test files.

Fires onDetail
?? / || with an empty literal on the right"", ``, 0, [], {}, "unknown", "N/A", when the left side names required data
≥ minFallbacksPerScope (2) fallbacks on ordinary names in one function
parameter or destructuring default with an empty literalrequired-looking names only
catch / .catch(cb) whose every return is empty, null or undefined and that discards the errorsame definition as boundary-resilience, REASON: escape included

"Required data" = the trailing property, string key (form.get("email"), headers["x-api-token"]) or callee, split into segments and matched against sensitiveNames (default: id, key, token, secret, price, amount, total, cost, fee, tax, balance, quantity, count, currency, url, email, sku, …). width does not match id. Fallbacks the type checker proves useless belong to typescript/no-unnecessary-condition.

Other opt-in rules: what the catalog line doesn't say
RuleExtra
validation-discards-proofcomplements fallback-masks-failure: that one reports the default papering over absence, this one where the proof should have been produced
precision-boundary-reviewnamed conversion calls stay silent
single-use-extraction-reviewasks whether the helper names a concept or fragments one operation
change-scatter-reviewfind one invariant owner, or justify independent boundary translations
hotspot-change-reviewpaths backed by concrete correction, rollback, incident or co-change history; generic complexity scores are not hotspots

Declared invariants and hotspots

protected-invariant-change and hotspot-change-review ship empty and stay silent: they fire only on what your repo declares.

FactoryEach entry
defineProtectedInvariantChangeinvariants[]: id, statement (falsifiable against the change), protectedPaths: RegExp[], evidencePaths?: RegExp[]
defineHotspotChangeReviewhotspots[]: id, pathPattern: RegExp (backed by real history), evidence (the concrete reason)

Migration: re-review earlier acceptances

Review prompts, not correctness proofs.

RuleRevDetectorChange
boundary-resilience ⚠️22reports discarding handlers around outbound calls; resilience words outside the argument list no longer count
test-behavior-coverage ⚠️33reports interaction-matcher-only files, interaction-only tests, snapshot-only tests
abstraction-earns-keep ⚠️22counts implementers and forwarding members; IName / ...Interface names only with interfacePattern
abstraction-earns-keep, flag-forked-function, isomorphic-mappingarchitectural tradeoffs: now 🔒 human authority
flag-forked-functionskips JSX files unless includeJsx

⚠️ existing acceptances need a fresh review.

Agentlint rule contract
FactDetail
rule shapelifecycle, standard (revision), detector (version), binding (id, authority, scope, material options)
composingdefineConfig({ extends: [preset] }) or defineConfig({ rules: [configuredRule] }); repeated uses need distinct binding ids
authorityrepository owners choose scope and authority; mechanically evidenced rules may permit agent acceptance; architectural, invariant and irreversible tradeoffs require a human
accepting a findingrequires matching current evidence and matching authority
fixtures@aurelienbbn/agentlint/testing runs the embedded activation/silence fixtures with the real parser

Registered contract inventory

Generated from package exports by pnpm catalog. Rule-specific options and limitations are described above and in the source tests.

Rule/checkTrigger or review scope
abstraction-earns-keepFlags interfaces that mirror their only implementer, classes and modules that forward verbatim to one collaborator, and exports that only delegate to a single call.
boundary-resilienceFlags outbound network calls that show no timeout or AbortSignal, and handlers around them that discard the failure.
bounded-data-accessFlags repository-like list/search/query calls without obvious boundedness markers.
bounded-workFlags execution paths with unbounded I/O, fan-out, or runtime budgets.
change-scatter-reviewFlags a decision token added across several production files so a reader checks whether the change is legitimately cross-cutting or duplicates ownership.
comment-signalFlags comments that narrate the next line or docblocks that restate the signature.
correlated-optional-stateFlags object types that pair a literal-union status field with two or more optional fields, where a discriminated union would make illegal combinations unrepresentable.
expected-value-recomputedFlags assertions whose expected value is computed from the same inputs as the call under test instead of being stated.
fake-parityFlags hand-written stateful fakes of a port so a shared behaviour suite or contract test proves they still behave like the real implementation.
fallback-masks-failureFlags empty-literal fallbacks on required-looking values, fallback-dense functions, and error handlers that return an empty literal.
flag-forked-functionFlags functions whose boolean or literal-union parameters are used only to choose between code paths, to check whether they are two functions sharing a name.
hotspot-change-reviewFlags changes to paths a repository has identified from real corrective history instead of treating generic complexity scores as defects.
integration-test-owns-its-boundaryFlags test files named or titled as integration tests that also construct test doubles, so the claimed boundary is checked to be real.
isomorphic-mappingFlags functions that copy an object field by field into a same-shaped object, to check that a real boundary separates the two types.
operations-stay-with-ownerFlags a file that calls several operations of another module through its public entry, so a reviewer decides whether that code belongs to the owner or the owner's entry exposes its internals.
pinned-suspect-outputFlags expected strings and inline snapshots that contain undefined, NaN, [object Object], Invalid Date or an embedded null, which usually certify a bug the test recorded.
precision-boundary-reviewFlags raw arithmetic across different unit-bearing identifiers so a reader checks units, tolerances, rounding and independent test evidence.
property-test-opportunityFlags test files that cover an encode/decode-style inverse pair or an idempotent normaliser with examples only, where one property would cover the open input domain.
protected-invariant-changeFlags changes to repository-declared invariant surfaces and their supporting evidence so architectural guarantees cannot change silently.
single-use-extraction-reviewFlags substantial file-local helpers with one caller and several forwarded values so a reader decides whether the extraction names a real concept or fragments one operation.
temporal-couplingFlags classes that can exist in an unusable state: 'not initialized' guards, definite-assignment fields set outside the constructor, and nullable fields filled by an init method.
test-behavior-coverageFlags mock-dense test files without an outcome assertion, tests that assert mock interactions only, and tests whose only oracle is a snapshot of a whole value.
test-exercises-project-codeFlags test files that import nothing from the project, so the code they exercise is a copy or a third-party library.
test-expectation-driftFlags test files whose existing expectations were deleted, loosened, skipped or re-valued in the same change, so the behaviour change is declared rather than absorbed.
validation-discards-proofFlags validate/check/ensure functions that return void or boolean without a type predicate, so what they proved is lost to the type system.

Credited concepts

  • "Characterization Testing" by Michael Feathers (concept)
  • "Choosing properties for property-based testing" by Scott Wlaschin (concept: inverse and idempotence families)
  • "ContractTest" by Martin Fowler (concept)
  • "Design Smell: Temporal Coupling" by Mark Seemann (concept)
  • "Designing with types: Making illegal states unrepresentable" by Scott Wlaschin (concept)
  • "Don't Put Logic in Tests" (Google Testing Blog) (concept)
  • "Feature Envy" from Martin Fowler's Refactoring (concept, lifted from classes to modules)
  • "FlagArgument" by Martin Fowler (concept)
  • "Getting Started with Contract Tests" by J. B. Rainsberger (concept)
  • "IntegrationTest" by Martin Fowler (concept: narrow integration tests double the remote, not the adapter)
  • "Interfaces are not abstractions" by Mark Seemann (concept: header interfaces, Reused Abstractions Principle)
  • "Parse, don't validate" by Alexis King (concept)
  • "Parse, don't validate" by Alexis King (concept: absence is rejected once, at the boundary)
  • "The Wrong Abstraction" by Sandi Metz (concept)
  • "When to Mock" by Vladimir Khorikov (concept: interaction assertions belong to unmanaged process boundaries)
  • ImpossibleBench (arXiv 2510.20270) (concept: passing by editing the oracle)
  • code-slop by asyrafhussin (MIT) + thermos by Cursor (MIT), concepts re-implemented
  • code-slop by asyrafhussin (MIT, concept re-implemented)
  • code-slop by asyrafhussin (MIT, concept re-implemented; real-defenses checklist)
  • https://alexn.org/blog/2026/09/22/ai-has-no-wisdom-and-neither-will-you/ (inspiration; independently implemented)
  • https://alexn.org/blog/2026/09/22/ai-has-no-wisdom-and-neither-will-you/#isso-thread (inspiration; independently implemented)
Credits, per rule

Concepts only; every rule is independently implemented.

RuleConcept
fallback-masks-failure"Parse, don't validate", Alexis King: absence is rejected once, at the boundary
validation-discards-proof"Parse, don't validate", Alexis King
test-behavior-coverage"When to Mock", Vladimir Khorikov: interaction assertions belong to unmanaged out-of-process dependencies
test-expectation-driftImpossibleBench (arXiv 2510.20270): passing by editing the oracle; "Characterization Testing", Michael Feathers
expected-value-recomputed"Don't Put Logic in Tests", Google Testing Blog
integration-test-owns-its-boundary"IntegrationTest", Martin Fowler: narrow integration tests double the remote, not the adapter
correlated-optional-state"Designing with types: Making illegal states unrepresentable", Scott Wlaschin
abstraction-earns-keep"Interfaces are not abstractions", Mark Seemann: header interfaces with one implementer
operations-stay-with-owner"Feature Envy" and "Move Function", Martin Fowler (Refactoring), lifted from classes to modules
temporal-coupling"Design Smell: Temporal Coupling", Mark Seemann
flag-forked-function"The Wrong Abstraction", Sandi Metz; "FlagArgument", Martin Fowler
property-test-opportunity"Choosing properties for property-based testing", Scott Wlaschin: inverse and idempotence families
fake-parity"ContractTest", Martin Fowler; "Getting Started with Contract Tests", J. B. Rainsberger
single-use-extraction-review, change-scatter-review, precision-boundary-review, protected-invariant-change, hotspot-change-review"AI Has No Wisdom and Neither Will You", Alexandru Nedelcu: delayed maintainability feedback, fragmented single-use helpers, explicit design invariants
comment-signal docblock barconventions observed in upstream effect-ts/effect sources
starterPreset onboardingdesloppify by Peter O'Malley: gradual onboarding; no code or guidance copied

版本与发布记录

@aurelienbbn/agentlint-plugin-core 共发布 7 个版本,首次发布于 2026/09/25;过去 12 个月发布了 7 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.2.3latest2026/10/1424 天前
0.2.22026/10/1325 天前
0.2.02026/10/0929 天前
0.1.32026/09/301 个月前
0.1.22026/09/301 个月前
0.1.12026/09/251 个月前

关于 @aurelienbbn/agentlint-plugin-core 的常见问题

@aurelienbbn/agentlint-plugin-core 是什么?

Custom agentlint rules for general TypeScript projects.

如何安装 @aurelienbbn/agentlint-plugin-core?

在项目目录运行 npm install @aurelienbbn/agentlint-plugin-core,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@aurelienbbn/agentlint(>=0.3.0 <0.9.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@aurelienbbn/agentlint-plugin-core 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@aurelienbbn/agentlint-plugin-core 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@aurelienbbn/agentlint-plugin-core 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js ^22.19.0 || ^24.11.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@aurelienbbn/agentlint-plugin-core 可以商用吗?

@aurelienbbn/agentlint-plugin-core 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@aurelienbbn/agentlint-plugin-core 的下载量有多少?

根据 npm 官方下载统计,@aurelienbbn/agentlint-plugin-core 在 2026/10/07 – 2026/11/05 这 30 天内被下载 2,466 次,日均约 82 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@aurelienbbn/agentlint-plugin-core 还在维护吗?

最新版本 0.2.3 发布于 2026/10/14(24 天前);至今共发布 7 个版本,其中过去 12 个月发布了 7 个;首次发布于 2026/09/25。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。