Last Updated: 2026-01-19
# Install
bun install
# Build all packages
bun run build
# Lint
bun run lint
bun run lint:fix
# Test (package-specific)
cd packages/<package> && bun run test
# Run UI dev server
cd packages/ui && bun run dev
# Create changeset
bun run changeset
# Version packages
bun run version
# Publish all (automated CI)
bun run release
# Manual release (when CI fails)
export NPM_TOKEN=<token>
export GITHUB_TOKEN=<token>
bun scripts/release-all.tsgit clone <repo>
cd root
bun installRequirements:
- Bun v1.3.4+ (bun.sh)
- Git
- Modern browser (Chrome 86+, Edge 86+)
Critical Rules (from AGENTS.md):
⚠️ NEVER auto-commit - always ask user approval first⚠️ ALWAYS fetch/pull main before creating new branch⚠️ NEVER suppress issues - ask user what to do
Workflow:
- Fetch latest:
git fetch origin && git pull origin main - Create branch:
git checkout -b <branch-name> - Make changes
- Test locally
- Create changeset:
bun run changeset - Commit with approval
- Push:
git push -u origin <branch-name> - Create PR via
gh pr create
Default: NO testing during development
- Test AFTER feature completion
- Only run tests if you modified source files
- Test files in
tests/directories, never insrc/
Per-Package:
# kql-lezer (currently failing - dep issues)
cd packages/kql-lezer && bun run test
# kql-to-duckdb (113 tests)
cd packages/kql-to-duckdb && bun run test tests
# ui (manual testing)
cd packages/ui && bun run devAfter ANY feature:
- Update feature checklists (mark [x] for completed)
- Add patterns/gotchas to dev guides
- Update status docs
Why: AI agents have no memory between sessions. Without updates, knowledge is lost.
When to Modify:
- Adding new KQL operator support
- Fixing parsing edge cases
- Improving AST structure
Process:
- Update
src/kql.grammar(Lezer grammar) - Run
bun run build:grammar(regenerates parser.ts) - Update
src/parser/cst-to-ast/mappers if needed - Update types in
src/types.ts - Run tests (when dep issue fixed)
- Update docs
Key Files:
src/kql.grammar- Hand-written grammar (THIS is the source of truth)src/parser.ts- Generated (DO NOT EDIT manually)src/parser/cst-to-ast/index.ts- Main mapper
Grammar Debugging:
See packages/kql-lezer/docs/howto-grammar-debug.md
When to Modify:
- Adding support for new operators
- Adding function mappings
- Fixing SQL generation bugs
Process:
- Import types from kql-lezer if needed
- Update
src/translator.ts - Add function mapping if needed
- Add test cases in
tests/ - Run
bun run test tests - Update status docs
Key Patterns:
// Adding new operator
function translateOperator(op: OperatorType): string {
const column = translateExpression(op.column)
return `SELECT ${column} FROM ...`
}
// Adding new function
const functionMap = {
kqlName: 'SQL_NAME',
// ...
}When to Modify:
- UI/UX improvements
- Adding query features
- Fixing layout issues
Process:
- Start dev server:
bun run dev - Make changes in
src/ - Test in browser
- Update styles in
src/styles/theme.css - Document gotchas in
docs/ui-dev.md
Hot Module Replacement: Vite auto-reloads on changes
- kql-lezer: Add grammar rule in
src/kql.grammar - kql-lezer: Add CST→AST mapper in
src/parser/cst-to-ast/operators/ - kql-lezer: Add type definition
- kql-to-duckdb: Add translator in
src/translator.ts - kql-to-duckdb: Add tests
- Both: Update status docs
- Check TypeScript errors:
bun run build - Check lint errors:
bun run lint - Fix issues
- Verify:
bun run build && bun run lint
Required by AGENTS.md:
- Run git status, git diff, git log in parallel
- Analyze all changes (NOT just latest commit)
- Draft PR summary covering ALL commits
- Push with
-uflag if new branch - Use
gh pr createwith HEREDOC for body:
gh pr create --title "Title" --body "$(cat <<'EOF'
## Summary
- Bullet points of changes
## Test plan
- Checklist for testing
EOF
)"- MUST include disclaimer:
_This PR was created by an AI agent on behalf of @<username>._
- Use Bun, not npm: All scripts use
bun run, notnpm run - Workspace dependencies: Use
workspace:*for internal packages - ESM only: All packages use
"type": "module" - Read before edit: Always read files before modifying
- Minimize output: Use
head,tail,grepto limit bash output
- Generated files: parser.ts is auto-generated, don't edit directly
- Grammar syntax: Lezer uses
{ }for alternation, not tree-sitter'schoice() - CST nodes: Lezer CST uses
.nodeproperty, not.children - Test deps: @lezer/lr resolution issue - tests currently failing
- CTE naming: Use
cte_0,cte_1, etc. for deterministic output - Expression parentheses: Always parenthesize sub-expressions to maintain precedence
- Function mapping: Case-sensitive -
count()≠COUNT() - Let variables: Substitute before translation, not during
- No hooks: SolidJS uses
createSignal, notuseState - Reactivity: Wrap derived data in
createMemo, not regular functions - Grid truncation: MUST use
min-width: 0on grid children - Theme switching: Update DOM classes, not just CSS
- DuckDB files: Must be in
public/, not bundled by Vite - File handles: Lost on page reload without user permission
kql-lezer:
- Issue: Cannot find @lezer/lr
- Workaround: None currently - known issue
kql-to-duckdb:
- Issue: "0 test files matching pattern"
- Fix: Ensure test files have
.test.tsor.spec.tssuffix - Run:
bun test tests(not justbun test)
TypeScript errors:
- Check imports from workspace packages
- Verify
tsconfig.jsonreferences - Run
bun run buildfrom root to build in order
Lezer grammar errors:
- Check grammar syntax in
kql.grammar - Run
bun run build:grammarto see parser generation errors - See
docs/howto-grammar-debug.md
DuckDB errors:
- Check
public/duckdb-eh.wasmexists - Check browser console for WASM errors
- Verify DuckDB WASM version compatibility
CodeMirror errors:
- Check kql-lezer build output
- Verify @codemirror packages installed
- Check browser console for module errors
- Feature:
feat/<description> - Fix:
fix/<description> - Agent work:
claude/<description>-<session-id>
feat(package): short description
Longer description if needed.
Explains why, not what.
Examples:
feat(kql-lezer): add support for between operatorfix(ui): prevent grid column overflow with long textdocs: update kql-to-duckdb status with test count
Always use gh for GitHub operations:
# Create issue
gh issue create --title "Title" --body "Body" --label "bug,agent"
# Create PR
gh pr create --title "Title" --body "$(cat <<'EOF'
Body here
EOF
)"
# View workflow
gh run view <run-id>
# Check logs
gh run view --log-failed --job=<job-id>MUST include disclaimer on ALL GitHub content:
---
_This {issue|PR|comment} was created by an AI agent on behalf of @<username>._Build order: Automatically handled by turbo
Caching: Turbo caches build outputs
Filtering: Use --filter to target specific packages
# Build only ui and its dependencies
bun run build --filter=./packages/uiCreating a changeset:
bun run changeset
# Follow prompts:
# 1. Select packages that changed
# 2. Choose version bump (patch/minor/major)
# 3. Write summaryVersioning:
# Update package versions
bun run version
# Publish to npm
bun run releaseFixed mode: All packages version together (currently all at 1.2.0)
The automated changesets workflow may not always work. Use these manual scripts when needed:
Prerequisites:
# Set required tokens
export NPM_TOKEN=<your-npm-token>
export GITHUB_TOKEN=<your-github-token>
# Version packages first
bun run versionIndividual steps:
# 1. Publish to npm only
bun scripts/publish-npm.ts
# 2. Publish to GitHub Package Registry only
bun scripts/publish-github.ts
# 3. Create GitHub release only
bun scripts/create-release.ts
# 4. Deploy UI only
bun scripts/deploy-ui.tsComplete release (all steps):
# Runs: build → npm publish → GitHub publish → create release → deploy UI
bun scripts/release-all.tsScripts location: /scripts/
publish-npm.ts- Publish all packages to npmpublish-github.ts- Publish all packages to GitHub registrycreate-release.ts- Create GitHub release from versiondeploy-ui.ts- Deploy UI to fossiq.github.iorelease-all.ts- Run complete release workflow
Notes:
- UI deployment requires either SSH key or GITHUB_TOKEN
- All packages must be built before publishing
- Versions should be bumped via changesets before running scripts
- Functions: Small, focused, single responsibility
- Naming: Descriptive (no single letters except loop indices)
- Files: Under ~100-150 lines
- Errors: Handle with descriptive messages
- Pure functions: Prefer over classes
// External first
import { something } from 'external-package'
// Internal workspace
import { Type } from '@fossiq/kql-ast'
// Relative
import { helper } from './helpers'- Only where logic isn't self-evident
- Explain WHY, not WHAT
- Update when code changes
Workflows:
ci.yml- Main workflow that orchestrates all jobs on push/PRlint.yml- Code lintingbuild.yml- Build all packagestest.yml- Run testspublish-npm.yml- Publish packages to npm (decoupled from UI)deploy-ui.yml- Deploy UI to fossiq.github.io (decoupled from npm)
Workflow Triggers:
ci.yml- Runs on push to main and all PRs- Runs lint → build → test
- On main branch only: publish-npm + deploy-ui (parallel)
deploy-ui.yml- Also runs independently on push to main when UI-related files change- Triggers: changes in
packages/ui/,packages/kql-lezer/,packages/kql-to-duckdb/,packages/kql-ast/
- Triggers: changes in
Secrets Required:
NPM_TOKEN- npm authentication for publishing packagesDEPLOY_KEY_GITHUB_IO- SSH deploy key for fossiq.github.io repositoryGITHUB_TOKEN- Automatically provided by GitHub Actions
Debugging CI:
gh run view <run-id>- See job statusgh run view --log-failed --job=<job-id>- See failed logs- Check workflow definitions in
.github/workflows/ - Inspect scripts in
.github/scripts/
Common CI Failures:
- Dependency installation (check lock file)
- Cache issues (update cache keys)
- Build order (check turbo.json)
- Missing secrets (check repository settings → Secrets)
- Deploy key permissions (check fossiq.github.io deploy keys)
The publishing and deployment workflows are intentionally decoupled:
Why Decoupled:
- npm package releases and UI deployments have different cadences
- UI can be deployed independently when fixing visual bugs
- npm packages can be published without re-deploying UI
- Failures in one pipeline don't block the other
- Both can run in parallel for faster releases
Workflow:
Push to main
↓
CI Workflow
├─→ Lint
├─→ Build
└─→ Test
├─→ Publish npm (if on main)
│ ├─→ Publish packages to npm
│ └─→ Create GitHub release
│
└─→ Deploy UI (if on main)
└─→ Deploy to fossiq.github.io
UI changes detected
↓
Deploy UI Workflow (independent)
└─→ Deploy to fossiq.github.io
Manual Triggers:
# Trigger npm publish only (via GitHub UI)
gh workflow run publish-npm.yml
# Trigger UI deploy only (via GitHub UI)
gh workflow run deploy-ui.yml- Use
bun run devin ui for hot reload - Use
--filterto build only changed packages - Use lint fix:
bun run lint:fixvs manual fixes
- All packages pre-built for npm
- UI uses Vite's optimized build
- DuckDB WASM lazy-loaded
- Table virtualization for large results
- Bun: https://bun.sh/docs
- Lezer: https://lezer.codemirror.net/
- SolidJS: https://www.solidjs.com/docs
- DuckDB WASM: https://duckdb.org/docs/api/wasm
- CodeMirror 6: https://codemirror.net/docs/
- Changesets: https://github.com/changesets/changesets