Contributing
Contributing to Signet
Section titled “Contributing to Signet”This guide is for developers contributing to the signetai/ monorepo,
the reference implementation of the Signet open standard.
New to git or GitHub? Start with Your First PR, a step-by-step walkthrough of making your first contribution.
This guide is for contributing from source. If you just want to use
Signet as a product, follow Quickstart and
install the global signet CLI instead of cloning the repo.
Development Setup
Section titled “Development Setup”Contributor workflow, from source:
git clone https://github.com/Signet-AI/signetai.gitcd signetaibun installbun run buildbun testBefore submitting changes, run the full check suite:
bun run typecheck # TypeScript strict mode checkbun run lint # Biome static analysisbun run format # Biome auto-formatbun test # All testsCommon local loops:
# Full workspace buildbun run build
# Daemon local devcd platform/daemon && bun run dev
# Website local devcd web/marketing && bun run devProject Structure
Section titled “Project Structure”This is a Bun workspace monorepo organized by intent:
platform/ # engine/runtime: core, daemon, nativesurfaces/ # human-facing surfaces: CLI, dashboard, desktop, tray, browser extensionintegrations/ # external harness integrations grouped by toollibs/ # reusable developer libraries: SDK, connector-baseplugins/ # Signet-native plugins loaded by Signetdist/ # assembled shipping artifacts, including signetaiweb/ # marketing site and Cloudflare workersmemorybench/ # benchmark harness, datasets, reports, and local UIKey packages:
platform/core/ # @signet/core — types, database, search, identityplatform/daemon/ # @signet/daemon — HTTP API, file watcher, pipelinesurfaces/cli/ # @signet/cli — setup wizard and daemon managementsurfaces/dashboard/ # signet-dashboard — Svelte dashboardsurfaces/desktop/ # @signet/desktop — Electron desktop applicationsurfaces/browser-extension/ # @signet/extension — browser extensionlibs/sdk/ # @signet/sdk — integration SDK for third-party appslibs/connector-base/ # @signet/connector-base — shared connector primitivesintegrations/<tool>/connector/ # install-time harness connectorsintegrations/<tool>/plugin/ # plugins loaded by external toolsintegrations/openclaw/memory-adapter/ # @signetai/signet-memory-openclawplugins/core/secrets/ # core Signet-native secrets plugindist/signetai/ # signetai — installable distribution packageweb/marketing/ # @signet/web — marketing site (Cloudflare Pages)web/workers/reviews/ # Cloudflare Worker for review automationmemorybench/ # benchmark harness and benchmark UIKey Modules
Section titled “Key Modules”These are the areas most likely to be touched in non-trivial contributions. Familiarize yourself with them before diving in.
platform/daemon/src/pipeline/ is the LLM-based memory extraction
pipeline. It runs in stages: extraction (extraction.ts, shared JSON
recovery/parsing helpers) → decision (decision.ts, write/update/skip) →
optional graph operations → retention decay. The entrypoint is worker.ts;
provider.ts wires up the stages. Config modes like shadowMode and
mutationsFrozen are respected here. For live prompt checks against local
Ollama models, see platform/daemon/src/pipeline/README.md.
platform/daemon/src/auth/ handles token-based auth for the
HTTP API. Key files: middleware.ts (Hono middleware), tokens.ts (token
lifecycle), policy.ts (access rules), rate-limiter.ts.
platform/daemon/src/connectors/ is the connector framework used by
the daemon. registry.ts manages connector registration; filesystem.ts
handles connector-driven file operations.
platform/daemon/src/analytics.ts, timeline.ts, and
diagnostics.ts provide observability. Analytics tracks pipeline
events; timeline records structured agent history; diagnostics exposes
health and repair tooling. Tests live alongside each file.
platform/core/src/database.ts owns the SQLite schema and migrations.
Any schema change must go through here. The wrapper supports both
bun:sqlite (under Bun) and better-sqlite3 (under Node.js) via runtime
detection.
Development Workflow
Section titled “Development Workflow”Make changes, rebuild the affected package, then test:
# Rebuild a single packagecd platform/daemon && bun run build
# Run a single test filebun test platform/daemon/src/pipeline/worker.test.ts
# Full rebuildbun run buildFor daemon changes specifically:
cd platform/daemonbun run dev # watch modebun run start # run directly without watchThe daemon serves its HTTP API on port 3850 by default. You can override
with SIGNET_PORT, SIGNET_HOST, and SIGNET_PATH environment variables.
Conventions
Section titled “Conventions”Package manager: Bun everywhere. Do not use npm or pnpm.
Linting and formatting: Biome. Run bun run lint and
bun run format before committing. CI will enforce this.
TypeScript: Strict mode is enforced by convention. Specifically:
no any (use unknown with narrowing), no as casts (fix the types),
no non-null assertions (!), explicit return types on all exported
functions, readonly where mutation is not intended, as const unions
over enum.
Commit messages: Conventional commits with a 50-character subject
line and 72-character body width. Use imperative mood. Types: feat,
fix, docs, style, refactor, perf, test, build, ci,
chore, revert. Scope the subject to the package or area changed,
e.g. feat(daemon): add rate limiting to auth middleware.
File size: Aim to keep files under ~700 LOC. Split or refactor when a file grows unwieldy, especially if it improves testability.
Comments: Explain why, not what. Self-explanatory code needs no inline narration; non-obvious logic or workarounds deserve a brief note.
Naming
Section titled “Naming”Use single word names by default. Multi-word names only when a single word would be ambiguous. Reduce variable count by inlining values used once.
// Goodconst foo = 1function journal(dir: string) {}const journal = await Bun.file(path.join(dir, "journal.json")).json()
// Badconst fooBar = 1function prepareJournal(dir: string) {}const journalPath = path.join(dir, "journal.json")const journal = await Bun.file(journalPath).json()Destructuring
Section titled “Destructuring”Avoid unnecessary destructuring. Use dot notation to preserve context.
// Goodobj.aobj.b
// Badconst { a, b } = objVariables
Section titled “Variables”Prefer const over let. Use ternaries or early returns instead of reassignment.
// Goodconst foo = condition ? 1 : 2
// Badlet fooif (condition) foo = 1else foo = 2Control Flow
Section titled “Control Flow”Avoid else statements. Prefer early returns.
// Goodfunction foo() { if (condition) return 1 return 2}
// Badfunction foo() { if (condition) return 1 else return 2}Pull Requests
Section titled “Pull Requests”Keep PRs focused. A PR that touches the pipeline, auth, and CLI in unrelated ways is harder to review and more likely to introduce regressions. If you are unsure whether an architectural change fits, open an issue first.
Before contributing a connector or adapter, look at how
connector-claude-code or connector-openclaw are structured. Connectors
are designed to be idempotent — safe to install multiple times. Follow
that pattern.
PRs with UI changes (dashboard, web, extension) must include screenshots. No screenshots, no merge.
Be transparent about AI assistance in PRs where applicable. See the AI Policy for disclosure requirements and expectations.
Conventional Commits and Versioning
Section titled “Conventional Commits and Versioning”Commit types drive automated version bumps:
feat:orfeat(scope):→ minor version bump (user-facing features only)fix:,refactor:,chore:,perf:,docs:, etc. → patch bumpBREAKING CHANGE:in subject or!after type (e.g.feat!:) → major bump
Use feat: only for genuinely new user-facing functionality. Internal
improvements, helpers, and plumbing should use fix:, refactor:,
chore:, or perf: to avoid unnecessary minor bumps.
Release Workflow
Section titled “Release Workflow”Releases are fully automated via GitHub Actions (.github/workflows/release.yml).
Do not publish packages manually. Push to main and CI handles the rest.
What triggers a release
Section titled “What triggers a release”Every push to main triggers the workflow, unless the commit message
contains chore: release (prevents infinite loops from release commits)
or the push only changes non-code files (markdown, images, etc.).
Automated steps
Section titled “Automated steps”- Build —
bun install && bun run buildon all packages - Version bump — Reads the current version from
dist/signetai/package.json, compares with remote, computes bump level from commit messages, and increments accordingly. Allpackage.jsonfiles (exceptsurfaces/dashboard/package.json) are updated to the new version. - Changelog —
bun scripts/changelog.ts --bump-onlycomputes the bump level from conventional commit subjects since the last tag, thenbun scripts/changelog.ts --version <new-version>writes the matchingCHANGELOG.mdentry for the actual release version. - npm publish — Publishes
signetaiand@signetai/signet-memory-openclawto npm with thenexttag, then promotes tolatest(unless it’s a major bump). - Commit and tag — Commits the version bump and changelog as
chore: release <version>, creates av<version>git tag, and pushes both. - GitHub Release — Creates a GitHub release with the changelog section as notes.
Published packages
Section titled “Published packages”signetai(meta-package bundling CLI + daemon)@signetai/signet-memory-openclaw(OpenClaw runtime adapter)
Adding a new package to the publish step
Section titled “Adding a new package to the publish step”Append an additional cd ../path && npm publish --tag next --access public
line to the “Publish to npm” step in .github/workflows/release.yml, and
add a corresponding npm dist-tag add in the “Promote to latest” step.
Scripts
Section titled “Scripts”All scripts live in scripts/ and are written in TypeScript (run via
bun) or bash.
| Script | Description |
|---|---|
changelog.ts |
Computes the semver bump from conventional commits since the last git tag, can prepend a CHANGELOG.md entry for an explicit release version, and can rebuild the full changelog from git tags. Generated entries include a short release summary, optional tag range, and grouped sections (feat, fix, perf, refactor, docs). Writes a .bump-level file used by CI to determine the semver bump. Called automatically during the release workflow. |
bump-level.ts |
Exports computeBumpLevel() — scans commit subjects for BREAKING CHANGE: (→ major), feat: (→ minor), or defaults to patch. Used by changelog.ts. |
version-sync.ts |
Aligns the version field in versioned Signet runtime/package workspaces to match the reference version in dist/signetai/package.json. Web manifests are intentionally excluded. Run manually with bun run version:sync or pass --to <version> to set an explicit version. |
extract-changelog-section.ts |
Extracts a single version’s section from CHANGELOG.md. Used by CI to populate GitHub release notes. |
check-install-guide.ts |
Validates that the install guide (web/marketing/public/skill.md), README, and landing page components contain the expected install prompt and don’t reference deprecated commands. |
post-push-sync.sh |
Watches for the release workflow to complete after a push to main, then pulls the resulting release commit locally. Useful for staying in sync after pushing. |
Identity Files
Section titled “Identity Files”Signet recognizes these standard identity files at $SIGNET_WORKSPACE/:
| File | Required | Description |
|---|---|---|
| AGENTS.md | yes | Operational rules and behavioral settings |
| SOUL.md | yes | Persona, character, and security settings |
| IDENTITY.md | yes | Agent name, creature type, and vibe |
| USER.md | yes | User profile and preferences |
| HEARTBEAT.md | no | Current working state, focus, and blockers |
| MEMORY.md | no | Memory index and summary |
| TOOLS.md | no | Tool preferences and notes |
| BOOTSTRAP.md | no | Setup ritual (typically deleted after first run) |
The detectExistingSetup() function in platform/core/src/identity.ts
detects existing setups from OpenClaw, Claude Code, and OpenCode.
Reference Repos
Section titled “Reference Repos”Use these as implementation references when designing protocol handling, integrations, and operational safeguards.
- lossless-claw — lossless context handling
- openclaw — agent runtime reference
- acpx — agent communication protocol
- arscontexta — agentic notetaking
- ACAN — LLM-enhanced memory retrieval
- cli — CLI patterns
- codex/cli
- opencode
To run any script manually:
bun scripts/changelog.ts --bump-onlybun scripts/changelog.ts --version 1.2.3bun scripts/changelog.ts --rebuildbun scripts/version-sync.ts --to 1.2.3bun scripts/extract-changelog-section.ts 0.14.5bun scripts/check-install-guide.ts./scripts/post-push-sync.shTest Discovery
Section titled “Test Discovery”Test discovery runs through workspace package scripts. Prefer targeted
package tests or bun run --filter ... test over bare root bun test, since
references/ contains third-party codebases with their own tests.
To run tests for a specific package:
# Run all tests in a packagebun test platform/daemon/
# Run a single test filebun test platform/daemon/src/pipeline/worker.test.ts
# Run all tests across all workspacesbun run test