Core behavioral rules and skills for NanoClaw personal assistant agents. Always-on rules for communication, verification, memory, and formatting.
77
97%
Does it follow best practices?
Impact
—
No eval scenarios have been run
Risky
Do not use without reviewing
jbaruch/nanoclaw-core is a tessl tile — a publishable package of behavioral rules and skills for NanoClaw personal assistant agents. It is installed into NanoClaw agent environments via tessl install jbaruch/nanoclaw-core. The tile provides always-on conversational rules and reusable skill scripts.
Current version: see tile.json → version field.
tile.json # Tile manifest: name, version, rules/skills registry
README.md # Human-readable overview + rules/skills tables
CHANGELOG.md # Version history; un-headed `### ` blocks at the top
# are stamped with the version heading at publish
pyproject.toml # pytest config + ruff lint (scoped to tests/ only)
pyrightconfig.json # pyright module resolution for the skill-bundle layout
requirements-dev.txt # Dev dependencies: pyright, pytest, ruff (pinned)
rules/ # 12 behavioral rule files (11 always-on, 1 conditional)
core-behavior.md
telegram-protocol.md
default-silence.md
ground-truth.md
context-recovery.md
post-compaction-trust.md
tone-matching.md
language-matching.md
temporal-awareness.md
read-full-content.md
query-size-limits.md
progress-updates.md
skills/
query-history/
SKILL.md # Skill definition consumed by the tessl runtime
scripts/
query-message-history.py # Keyword/sender search over messages.db
now-vs-deadline/
SKILL.md
scripts/
now-vs-deadline.py # Deterministic past/future comparison vs the current instant
tests/
conftest.py # Shared fixtures; loads kebab-case scripts via importlib
test_query_message_history.py
test_now_vs_deadline.py
.github/
workflows/
test.yml # CI: ruff + pyright + pytest on every PR; callable
# (workflow_call) as the publish workflow's gate job
publish-tile.yml # On push to main: test-suite gate, skill review,
# tile lint, CHANGELOG stamp, publish to tessl registry
review-openai.md # AI-assisted PR review (OpenAI; compiled .lock.yml)
review-anthropic.md # AI-assisted PR review (Anthropic; compiled .lock.yml)Install dev dependencies first (Python 3.11+):
pip install -r requirements-dev.txtLint (scoped to tests/ only — tile scripts under skills/*/scripts/ predate the lint config):
python -m ruff check tests/
python -m ruff format --check tests/Type check (zero-findings gate; --warnings fails on warnings too; module resolution via pyrightconfig.json):
python -m pyright --warnings skills/ tests/Run tests:
python -m pytestCI runs these in order: ruff check → ruff format → pyright → pytest. All four must pass on every PR.
There is no build step. This is a pure Python + Markdown tile; nothing needs compiling.
rules/*.md)---
alwaysApply: true
---alwaysApply: false plus an applyTo: glob+prose scope (see rules/progress-updates.md for the live example). Both forms are valid tessl frontmatter; pick by whether the rule's prescription fires on every turn or only in a specific context.core-behavior.md).skills/*/SKILL.md)name: and description: fields (no alwaysApply).skills/<skill-name>/scripts/ and use kebab-case filenames (e.g., query-message-history.py)./home/node/.claude/skills/tessl__<skill-name>/scripts/<script>.py.tile.json and README.md must stay in synctile.json (the rules object) and the rules table in README.md.tile.json (the skills object) and the skills table in README.md.version field in tile.json follows semver. The publish workflow bumps the patch version automatically on every merge to main; edit it by hand only for an intentional minor or major release (see gotcha 6).tests/ and are standard pytest.import query-message-history is a syntax error). All test fixtures load them via importlib.util.spec_from_file_location. The conftest.py _load() helper handles this — use the existing query_message_history fixture as the template rather than reimplementing the loading pattern.test_now_vs_deadline.py for the pattern).tests/ in pyproject.toml; do not apply ruff rules to files under skills/*/scripts/ unless that is the explicit scope of a PR.error field uses three states: null (clean success), "env-warning: ..." prefix (non-fatal config hint, script still produced useful output), or any other string (hard failure, exits non-zero).| Workflow | Trigger | Purpose |
|---|---|---|
test.yml | PR + workflow_call | Lint (ruff) + type check (pyright) + pytest |
publish-tile.yml | push to main, workflow_dispatch | gate (calls test.yml) → tessl skill review (quality gate ≥85) → tile lint → CHANGELOG stamp → publish |
review-openai.md / review-anthropic.md | PR events | AI-assisted code review |
The publish workflow first runs the full test suite as a read-only gate job (calling test.yml via workflow_call — main-push coverage comes from this call, not a separate push: trigger on test.yml), then tessl skill review --threshold 85 on each changed skill. A red suite or failing quality score blocks the publish.
tile.json + README.md drift — if you add/remove a rule or skill in one place, update both. The table and the JSON registry must match.tests/. Do not widen it to skills/*/scripts/ without an explicit decision in the PR.alwaysApply: true or alwaysApply: false + applyTo: (conditional).conftest.py following the _load() pattern. Do not try to import the script directly.tesslio/patch-version-publish on every merge to main. Only edit tile.json's version by hand for a minor or major bump.## Unreleased heading. Add un-headed ### entry blocks at the top; the publish workflow's stamp step writes the ## <version> — <date> heading at publish time. Every merge publishes a version, so every PR should carry an entry block.rules
skills
now-vs-deadline
scripts
query-history