{"_id":"@alejandrocantero/kanbamd","_rev":"8-42d97d6a69277bbdac46a06010613b40","name":"@alejandrocantero/kanbamd","dist-tags":{"latest":"1.8.0"},"versions":{"1.0.0":{"name":"@alejandrocantero/kanbamd","version":"1.0.0","keywords":["kanban","markdown","frontmatter","typescript"],"license":"MIT","_id":"@alejandrocantero/kanbamd@1.0.0","maintainers":[{"name":"alejandrocanterouser","email":"alejandrotrust2@pm.me"}],"dist":{"shasum":"b8b6943a1bbed2c41fa54aba03312e0996a4f24e","tarball":"https://registry.npmjs.org/@alejandrocantero/kanbamd/-/kanbamd-1.0.0.tgz","fileCount":26,"integrity":"sha512-nVJ1cO33DFTknEPi1m2Jd5Zkrt6aRi3cPmyt0hzbMZPPEDsgxTWx7A6ASG2D0PTZgKEUxBHgwnMys3nd7UltTg==","signatures":[{"sig":"MEYCIQDHNPUaPQ2W0Mh1a8V77MmwVI473jXneHvWN28JNnBEbgIhAKf0ob4hWXkPVYdpvPZqYBcykKjWLpS8vpazoXIYgmFn","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":56383},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"f002ecaf3b2a6dce7520d48242216a6faeb1a815","scripts":{"lint":"biome check .","test":"vitest run","build":"tsc -p tsconfig.json","format":"biome format . --write","release":"bun run scripts/release.ts","lint:fix":"biome check . --write","typecheck":"tsc -p tsconfig.typecheck.json"},"_npmUser":{"name":"alejandrocanterouser","email":"alejandrotrust2@pm.me"},"_npmVersion":"10.9.7","description":"Manage Kanban boards backed by Markdown files, frontmatter, and column folders.","directories":{},"_nodeVersion":"22.22.2","dependencies":{"fuse.js":"^7.1.0","slugify":"^1.6.6","gray-matter":"^4.0.3"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^1.6.0","typescript":"^5.4.5","@types/node":"^20.12.12","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/kanbamd_1.0.0_1777648730654_0.43029634374147663","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@alejandrocantero/kanbamd","version":"1.2.0","keywords":["kanban","markdown","frontmatter","typescript"],"license":"MIT","_id":"@alejandrocantero/kanbamd@1.2.0","maintainers":[{"name":"alejandrocanterouser","email":"alejandrotrust2@pm.me"}],"dist":{"shasum":"fc2efd3310a775fa70fac4c60c320505cad4aa5f","tarball":"https://registry.npmjs.org/@alejandrocantero/kanbamd/-/kanbamd-1.2.0.tgz","fileCount":26,"integrity":"sha512-2h3JF2GRcMx38fLr0iod/53vl0uxeyX0HBVr8h7iS/9Lb1K5lpwJyKAVIna6eZ7Cb3S/WhcQWhrlSUyp2hyIuQ==","signatures":[{"sig":"MEQCIEuIt37avJJSz2JyKIsylYDbuuOZL/GHC+Gqlg6ZDyI5AiBo/dhBeN8A+ut62c5qZnxcv9dAM9GkSX14msdIfUeTrg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":56889},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"65dc6f136f7fd63931f3de1ad843ff49b314500a","imports":{"#src/*":{"types":"./dist/*.d.ts","default":"./dist/*.js"}},"scripts":{"lint":"biome check .","test":"vitest run","build":"tsc -p tsconfig.json","format":"biome format . --write","release":"bun run scripts/release.ts","lint:fix":"biome check . --write","typecheck":"tsc -p tsconfig.typecheck.json"},"_npmUser":{"name":"alejandrocanterouser","email":"alejandrotrust2@pm.me"},"_npmVersion":"10.8.2","description":"Manage Kanban boards backed by Markdown files, frontmatter, and column folders.","directories":{},"_nodeVersion":"20.20.2","dependencies":{"fuse.js":"^7.1.0","slugify":"^1.6.6","gray-matter":"^4.0.3"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^1.6.0","typescript":"^5.4.5","@types/node":"^20.12.12","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/kanbamd_1.2.0_1777657086109_0.12572638538507164","host":"s3://npm-registry-packages-npm-production"}},"1.3.0":{"name":"@alejandrocantero/kanbamd","version":"1.3.0","keywords":["kanban","markdown","frontmatter","typescript"],"license":"MIT","_id":"@alejandrocantero/kanbamd@1.3.0","maintainers":[{"name":"alejandrocanterouser","email":"alejandrotrust2@pm.me"}],"dist":{"shasum":"2f206b85b9ba328e1ff7501345d8cecd0aa31b54","tarball":"https://registry.npmjs.org/@alejandrocantero/kanbamd/-/kanbamd-1.3.0.tgz","fileCount":26,"integrity":"sha512-PWVq7JsaK4Rix14C86i9fnlS9C0zp5l7+9KpQGrO/J66TW14mFEQ/Da6bVBz2hPE0J6L/f9YH2wnH8F5ImPSlg==","signatures":[{"sig":"MEUCIGbrprcIX8LFfRj3DlDWK9pbKW68zNyrhNWQ5eCXg2XmAiEAkCPdNup5i3AtjWkRp/O9IcBNiJTf3bI+Tvik0LftJZg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":56160},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"87cd8050eb6f9af400fe853ed2b256966a1de907","imports":{"#src/*":{"types":"./dist/*.d.ts","default":"./dist/*.js"}},"scripts":{"lint":"biome check .","test":"vitest run","build":"tsc -p tsconfig.json","format":"biome format . --write","release":"bun run scripts/release.ts","lint:fix":"biome check . --write","typecheck":"tsc -p tsconfig.typecheck.json"},"_npmUser":{"name":"alejandrocanterouser","email":"alejandrotrust2@pm.me"},"_npmVersion":"10.8.2","description":"Manage Kanban boards backed by Markdown files, frontmatter, and column folders.","directories":{},"_nodeVersion":"20.20.2","dependencies":{"fuse.js":"^7.1.0","slugify":"^1.6.6","gray-matter":"^4.0.3"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^1.6.0","typescript":"^5.4.5","@types/node":"^20.12.12","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/kanbamd_1.3.0_1777657184229_0.7224967619453755","host":"s3://npm-registry-packages-npm-production"}},"1.4.3":{"name":"@alejandrocantero/kanbamd","version":"1.4.3","keywords":["kanban","markdown","frontmatter","typescript"],"license":"MIT","_id":"@alejandrocantero/kanbamd@1.4.3","maintainers":[{"name":"alejandrocanterouser","email":"alejandrotrust2@pm.me"}],"dist":{"shasum":"09bd297bffcff5750594559c5848ddd0ede5bdfb","tarball":"https://registry.npmjs.org/@alejandrocantero/kanbamd/-/kanbamd-1.4.3.tgz","fileCount":26,"integrity":"sha512-wlFPCDdez18c9jxcTVZalGJg9GMJLHl6EcAAc/3icKuHBeaqq1QUxtfBAbdR/AUK0bmOqa4YQMoNWhTV8gbYYA==","signatures":[{"sig":"MEUCIQCtb1Csp2Y0hRrdtXIBCtqt25ay8F41/Mg99t/q5T5gawIgYoyfexxch0i18QdgUfJ1hcmTRpdrTOTsBf2smCOg6+0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":56053},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"bf61816650c7b7e62f2f42ded3d0f257a99f8001","scripts":{"lint":"biome check .","test":"vitest run","build":"tsc -p tsconfig.json","format":"biome format . --write","release":"node scripts/release.mjs","lint:fix":"biome check . --write","typecheck":"tsc -p tsconfig.typecheck.json"},"_npmUser":{"name":"alejandrocanterouser","email":"alejandrotrust2@pm.me"},"_npmVersion":"10.8.2","description":"Manage Kanban boards backed by Markdown files, frontmatter, and column folders.","directories":{},"_nodeVersion":"20.20.2","dependencies":{"fuse.js":"^7.1.0","slugify":"^1.6.6","gray-matter":"^4.0.3"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^1.6.0","typescript":"^5.4.5","@types/node":"^20.12.12","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/kanbamd_1.4.3_1777751828010_0.651179248560585","host":"s3://npm-registry-packages-npm-production"}},"1.5.0":{"name":"@alejandrocantero/kanbamd","version":"1.5.0","keywords":["kanban","markdown","frontmatter","typescript"],"license":"MIT","_id":"@alejandrocantero/kanbamd@1.5.0","maintainers":[{"name":"alejandrocanterouser","email":"alejandrotrust2@pm.me"}],"bin":{"kanbamd":"dist/cli.js"},"dist":{"shasum":"1ad4bde7476d46ade1b564f9c5a22b936dd9e68b","tarball":"https://registry.npmjs.org/@alejandrocantero/kanbamd/-/kanbamd-1.5.0.tgz","fileCount":30,"integrity":"sha512-v5s5tIgb8ptOMh17ipqWTasp9GoaZgjOTmOHTrj4tpnwztGY7nodOEqOlU0jL2A8e61PT611eGEm1Snsy3uUww==","signatures":[{"sig":"MEYCIQDl5twpA4YcEezbV69TxVGLMgeOGXxQOTPUD4L2s2QJtwIhAIS5ysWiAE+9+dhT5d9CPm4D7/UvFWN74VKSVs09xFpQ","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":94560},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"d0e26e562a3c3c15e138fbc5781380c93e225da4","scripts":{"lint":"biome check .","test":"vitest run","build":"tsc -p tsconfig.json","format":"biome format . --write","release":"node scripts/release.mjs","lint:fix":"biome check . --write","typecheck":"tsc -p tsconfig.typecheck.json"},"_npmUser":{"name":"alejandrocanterouser","email":"alejandrotrust2@pm.me"},"_npmVersion":"10.8.2","description":"Manage Kanban boards backed by Markdown files, frontmatter, and column folders.","directories":{},"_nodeVersion":"20.20.2","dependencies":{"chalk":"^5.6.2","fuse.js":"^7.1.0","slugify":"^1.6.6","commander":"^12.1.0","gray-matter":"^4.0.3","@inquirer/prompts":"^7.10.1"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^1.6.0","typescript":"^5.4.5","@types/node":"^20.12.12","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/kanbamd_1.5.0_1777878836638_0.982659698988082","host":"s3://npm-registry-packages-npm-production"}},"1.6.0":{"name":"@alejandrocantero/kanbamd","version":"1.6.0","keywords":["kanban","markdown","frontmatter","typescript"],"license":"MIT","_id":"@alejandrocantero/kanbamd@1.6.0","maintainers":[{"name":"alejandrocanterouser","email":"alejandrotrust2@pm.me"}],"bin":{"kanbamd":"dist/cli.js"},"dist":{"shasum":"fe65e98cb8a89463817f20ffd7bfe65d12474f72","tarball":"https://registry.npmjs.org/@alejandrocantero/kanbamd/-/kanbamd-1.6.0.tgz","fileCount":30,"integrity":"sha512-sDf/dzfQ1CduvF5LpVH3UmaVBe2Q9LNy1DaPxo62jWOr0au0cpPuu1mXe2lcJv89COOtwkggabHL4Xr3xhk1Pw==","signatures":[{"sig":"MEUCIQCDYQCtbTUtzvUUqAERHDC4fmFpBBUS+DajROG0Lg1t1wIgTmxuTREzEOJkoCD5ykKQlMFJW6rBzZWSgrgLvKCrPs4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":94560},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"a9382bbc260c4aaf17cdb01f44c5da05760253a5","scripts":{"lint":"biome check .","test":"vitest run","build":"tsc -p tsconfig.json","format":"biome format . --write","release":"node scripts/release.mjs","lint:fix":"biome check . --write","typecheck":"tsc -p tsconfig.typecheck.json"},"_npmUser":{"name":"alejandrocanterouser","email":"alejandrotrust2@pm.me"},"_npmVersion":"10.8.2","description":"Manage Kanban boards backed by Markdown files, frontmatter, and column folders.","directories":{},"_nodeVersion":"20.20.2","dependencies":{"chalk":"^5.6.2","fuse.js":"^7.1.0","slugify":"^1.6.6","commander":"^12.1.0","gray-matter":"^4.0.3","@inquirer/prompts":"^7.10.1"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^1.6.0","typescript":"^5.4.5","@types/node":"^20.12.12","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/kanbamd_1.6.0_1777878874871_0.2124174800742571","host":"s3://npm-registry-packages-npm-production"}},"1.7.0":{"name":"@alejandrocantero/kanbamd","version":"1.7.0","keywords":["kanban","markdown","frontmatter","typescript"],"license":"MIT","_id":"@alejandrocantero/kanbamd@1.7.0","maintainers":[{"name":"alejandrocanterouser","email":"alejandrotrust2@pm.me"}],"bin":{"kanbamd":"dist/cli.js"},"dist":{"shasum":"11482c96c70fe1bd420be63ea7c953714c517656","tarball":"https://registry.npmjs.org/@alejandrocantero/kanbamd/-/kanbamd-1.7.0.tgz","fileCount":30,"integrity":"sha512-ciI6/cNxsZ390FoYLM42PsGA8+It6tz975i8CbBpoyIlBENYwiO5aYO5P3U0Q2eFyWdqYeUq1/qYy8bAy3SI5Q==","signatures":[{"sig":"MEYCIQC4aG3J436GxTr8W4SC8Yp5FIE0K8RMRmSQzsFfqeGTOwIhAMeODNgut/e7hJrHI+FYrDJhi2myyDPoHpukVnjYoCxH","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":94764},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"4bca078f8dcf0043d964899d127dfc8345ec3b59","scripts":{"lint":"biome check .","test":"vitest run","build":"tsc -p tsconfig.json","format":"biome format . --write","release":"node scripts/release.mjs","lint:fix":"biome check . --write","typecheck":"tsc -p tsconfig.typecheck.json"},"_npmUser":{"name":"alejandrocanterouser","email":"alejandrotrust2@pm.me"},"_npmVersion":"10.8.2","description":"Manage Kanban boards backed by Markdown files, frontmatter, and column folders.","directories":{},"_nodeVersion":"20.20.2","dependencies":{"chalk":"^5.6.2","fuse.js":"^7.1.0","slugify":"^1.6.6","commander":"^12.1.0","gray-matter":"^4.0.3","@inquirer/prompts":"^7.10.1"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^1.6.0","typescript":"^5.4.5","@types/node":"^20.12.12","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/kanbamd_1.7.0_1777889877052_0.3768984185518769","host":"s3://npm-registry-packages-npm-production"}},"1.8.0":{"name":"@alejandrocantero/kanbamd","version":"1.8.0","description":"Manage Kanban boards backed by Markdown files, frontmatter, and column folders.","type":"module","main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"bin":{"kanbamd":"dist/cli.js"},"scripts":{"build":"tsc -p tsconfig.json && cp -R skills dist/skills","format":"biome format . --write","lint":"biome check .","lint:fix":"biome check . --write","release":"node scripts/release.mjs","test":"vitest run","typecheck":"tsc -p tsconfig.typecheck.json"},"keywords":["kanban","markdown","frontmatter","typescript"],"license":"MIT","dependencies":{"@inquirer/prompts":"^7.10.1","chalk":"^5.6.2","commander":"^12.1.0","fuse.js":"^7.1.0","gray-matter":"^4.0.3","slugify":"^1.6.6"},"devDependencies":{"@biomejs/biome":"^1.9.4","@types/node":"^20.12.12","typescript":"^5.4.5","vitest":"^1.6.0"},"engines":{"node":">=20"},"_id":"@alejandrocantero/kanbamd@1.8.0","gitHead":"7182426671c6fc1d1aa36d40481317227840a77c","_nodeVersion":"20.20.2","_npmVersion":"10.8.2","dist":{"integrity":"sha512-sqzphFjiI5D4I13UTjKemPOzwpQNw3ExRstsP5Vvjl2fNkPotVIgz8fNwrxJI6hOYYrJU98rcKZFXq/BVZp06w==","shasum":"3e37922337dba123985979184690d2c639c98a60","tarball":"https://registry.npmjs.org/@alejandrocantero/kanbamd/-/kanbamd-1.8.0.tgz","fileCount":31,"unpackedSize":128491,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIGPUMqOd+21t9MJf22XnCF56K11m3KTLLB6bqjACMRfEAiEAxjx8VhWVBRU9plXuzYCdopTe3S1JYVXID73SQ9qGf5E="}]},"_npmUser":{"name":"alejandrocanterouser","email":"alejandrotrust2@pm.me"},"directories":{},"maintainers":[{"name":"alejandrocanterouser","email":"alejandrotrust2@pm.me"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/kanbamd_1.8.0_1777899220733_0.2227516526614648"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-01T15:18:50.552Z","modified":"2026-05-04T12:53:41.041Z","1.0.0":"2026-05-01T15:18:50.864Z","1.2.0":"2026-05-01T17:38:06.288Z","1.3.0":"2026-05-01T17:39:44.387Z","1.4.3":"2026-05-02T19:57:08.180Z","1.5.0":"2026-05-04T07:13:56.779Z","1.6.0":"2026-05-04T07:14:34.999Z","1.7.0":"2026-05-04T10:17:57.204Z","1.8.0":"2026-05-04T12:53:40.896Z"},"license":"MIT","keywords":["kanban","markdown","frontmatter","typescript"],"description":"Manage Kanban boards backed by Markdown files, frontmatter, and column folders.","maintainers":[{"name":"alejandrocanterouser","email":"alejandrotrust2@pm.me"}],"readme":"# @alejandrocantero/kanbamd\n\nTypeScript library and CLI for managing Kanban boards stored as Markdown files with YAML frontmatter in column directories.\n\n## Install\n\n```sh\nnpm install @alejandrocantero/kanbamd\n```\n\n### Global CLI install\n\n```sh\nnpm install -g @alejandrocantero/kanbamd\n```\n\n## Board Layout\n\nEach column is a directory. Each card is a `.md` file:\n\n```\nboard/\n├── todo/\n│   └── fix-login.md\n├── doing/\n│   └── refactor-auth.md\n└── done/\n```\n\nA card file:\n\n```markdown\n---\ntitle: Fix login\ntags: [bug]\norder: 1\npriority: high\nassignee: alice\n---\nOAuth callback fails when redirect_uri has a trailing slash.\n```\n\n**Reserved frontmatter fields** (managed by kanbamd, cannot be used as custom fields):\n\n| Field | Type | Description |\n|---|---|---|\n| `title` | `string` | Card title (required) |\n| `tags` | `string[]` | List of tags |\n| `order` | `integer` | 1-based position within column |\n\nFilesystem metadata is exposed as `createdAt` (birthtime) and `updatedAt` (mtime).\n\n## SDK\n\n### Setup\n\n```ts\nimport { Kanbamd } from \"@alejandrocantero/kanbamd\";\n\nconst board = new Kanbamd({\n  root: \"./board\",\n  columns: [\"todo\", \"doing\", \"done\"],\n  createRoot: false,       // default: false — create root dir if missing\n  createColumns: true,     // default: true  — create column dirs inside root\n});\n\nawait board.init();\n```\n\n#### Memory storage\n\nIn-memory storage for testing or programmatic use (no filesystem required):\n\n```ts\nconst board = new Kanbamd({\n  storage: \"memory\",\n  columns: [\"todo\", \"doing\", \"done\"],\n});\n\nawait board.init();\n```\n\n### Typed custom fields\n\nPass a type parameter to constrain custom frontmatter fields:\n\n```ts\ntype CustomFields = {\n  priority?: \"low\" | \"medium\" | \"high\";\n  assignee?: string;\n  estimate?: number;\n};\n\nconst board = new Kanbamd<CustomFields>({\n  root: \"./board\",\n  columns: [\"todo\", \"doing\", \"done\"],\n});\n```\n\n### API\n\n#### `listColumns()`\n\n```ts\nconst columns: string[] = await board.listColumns();\n```\n\n#### `listCards(options?)`\n\n```ts\nconst allCards = await board.listCards();\nconst todoCards = await board.listCards({ column: \"todo\" });\n```\n\nReturns `Card<T>[]` sorted by column then order.\n\n#### `getCard(locator)`\n\n```ts\nconst card = await board.getCard({ column: \"todo\", id: \"fix-login\" });\n```\n\n`Card<T>` shape:\n\n| Field | Type | Description |\n|---|---|---|\n| `id` | `string` | Slug derived from title |\n| `fileName` | `string` | `\"<id>.md\"` |\n| `column` | `string` | Column the card belongs to |\n| `frontmatter` | `CardFrontmatter<T>` | Parsed YAML frontmatter |\n| `body` | `string` | Markdown body |\n| `createdAt` | `Date` | Filesystem birthtime |\n| `updatedAt` | `Date` | Filesystem mtime |\n\n#### `createCard(column, input)`\n\n```ts\nconst card = await board.createCard(\"todo\", {\n  title: \"Fix login\",\n  tags: [\"bug\"],\n  body: \"OAuth callback fails.\",\n  frontmatter: {\n    priority: \"high\",\n    assignee: \"alice\",\n  },\n});\n```\n\n`CreateCardInput<T>`:\n\n| Field | Type | Default | Description |\n|---|---|---|---|\n| `title` | `string` | _required_ | Card title |\n| `tags` | `string[]` | `[]` | Tags |\n| `body` | `string` | `\"\"` | Markdown body |\n| `frontmatter` | `NoReservedFrontmatter<T>` | — | Custom fields |\n\nDuplicate IDs get a numeric suffix: `fix-login`, `fix-login-2`, `fix-login-3`, etc.\n\n#### `updateCard(locator, input)`\n\n```ts\nconst updated = await board.updateCard(\n  { column: \"todo\", id: \"fix-login\" },\n  {\n    title: \"Fix OAuth redirect\",\n    tags: [\"bug\", \"auth\"],\n    body: \"Updated description.\",\n    frontmatter: { priority: \"medium\" },\n  }\n);\n```\n\nAll fields in `UpdateCardInput<T>` are optional. Omitted fields keep their current value.\n\n#### `moveCard(locator, target)`\n\n```ts\nawait board.moveCard(\n  { column: \"todo\", id: \"fix-login\" },\n  { column: \"doing\" }\n);\n```\n\nThe source column's order is normalized (1, 2, 3, ...). The moved card is placed last in the target column. Throws `DuplicateCardError` if a card with the same ID already exists in the target column.\n\n#### `reorderCard(locator, index)`\n\n```ts\nconst reordered = await board.reorderCard(\n  { column: \"todo\", id: \"fix-login\" },\n  0   // 0-based new position\n);\n```\n\nReturns the entire column's cards in their new order. Out-of-range indices are clamped.\n\n#### `deleteCard(locator)`\n\n```ts\nawait board.deleteCard({ column: \"todo\", id: \"fix-login\" });\n```\n\nThe column's remaining cards are normalized.\n\n#### `searchCards(options)`\n\n```ts\nconst results = await board.searchCards({\n  query: \"oauth redirect\",\n  columns: [\"todo\", \"doing\"],\n  tags: [\"bug\"],\n  limit: 10,\n});\n```\n\nFuzzy search (Fuse.js, threshold: 0.35, ignoreLocation: true) across `id`, `frontmatter.title`, `frontmatter.tags`, and `body`. Tag filtering is AND-based.\n\n### Error classes\n\n| Error | When |\n|---|---|\n| `BoardRootNotFoundError` | Root dir missing or not a directory |\n| `ColumnNotFoundError` | Column not in the defined list |\n| `CardNotFoundError` | Card file or ID not found |\n| `DuplicateCardError` | ID collision during move |\n| `InvalidFrontmatterError` | Invalid/reserved key in frontmatter |\n| `InvalidStorageConfigurationError` | Misconfigured storage options |\n\nAll extend `KanbamdError`.\n\n## CLI\n\nThe `kanbamd` binary ships with the package.\n\n### `kanbamd init`\n\nInitialize a board. Creates column directories and a `.kanbamd.json` config.\n\n```sh\nkanbamd init\nkanbamd init --no-fields                         # skip custom field prompts\nkanbamd init --root ./board --columns todo,doing,done\n```\n\nBy default, `init` prompts interactively to define custom frontmatter fields. Four field types are supported:\n\n| Type | Input | Example |\n|---|---|---|\n| `text` | Free text | `assignee`, `branch` |\n| `select` | Single choice | `priority` (low/medium/high) |\n| `multiselect` | Checkboxes | `labels` (frontend, backend, devops) |\n| `number` | Integer with min/max | `estimate`, `story-points` |\n\nEach can be marked required and have a default value.\n\n### `kanbamd columns`\n\n```sh\nkanbamd columns\n```\n\nLists columns with card counts.\n\n### `kanbamd list`\n\n```sh\nkanbamd list\nkanbamd list --column todo\nkanbamd list -c todo\n```\n\nCards shown as: `<order>. [<column>] <title> #<id> #<tag1> #<tag2>`\n\n### `kanbamd add`\n\nFully interactive. Prompts for: column (skipped if only one exists), title (required), body, tags (comma-separated), custom fields (if defined in config), and order (defaults to last).\n\n```sh\nkanbamd add\n```\n\n### `kanbamd view`\n\n```sh\nkanbamd view fix-login                            # by ID\nkanbamd view fix-login --column todo              # disambiguate\nkanbamd view                                      # interactive picker\n```\n\nDisplays: title, ID, column, order, tags, all custom fields, `createdAt`, `updatedAt`, and body.\n\n### `kanbamd move`\n\n```sh\nkanbamd move fix-login --to done                  # non-interactive\nkanbamd move                                      # interactive picker\n```\n\nThe target is auto-selected if only one other column exists.\n\n### `kanbamd delete`\n\n```sh\nkanbamd delete fix-login                          # by ID\nkanbamd delete                                    # interactive picker\n```\n\nAlways prompts for confirmation.\n\n### `kanbamd search`\n\n```sh\nkanbamd search \"oauth bug\"\nkanbamd search \"oauth\" --tags bug,auth            # must have ALL tags\nkanbamd search \"oauth\" --column todo,doing        # filter columns\nkanbamd search \"oauth\" --limit 5                  # max results (default: 10)\nkanbamd search \"fix\" -t bug -c todo,doing -l 20\n```\n\n### Global options\n\nThese apply before any subcommand and override config:\n\n```sh\nkanbamd --root ./board --columns todo,doing,done list\n```\n\nIf omitted, kanbamd walks up the directory tree looking for `.kanbamd.json`. Falls back to the current directory, auto-detecting columns from subdirectories.\n\n### Interactive fallback\n\nCommands accepting an optional `<id>` (`view`, `move`, `delete`) show a select list when called without one. Ctrl+C exits cleanly.\n\n## Configuration\n\n`kanbamd init` writes a `.kanbamd.json` file:\n\n```json\n{\n  \"root\": \"./board\",\n  \"columns\": [\"todo\", \"doing\", \"done\"],\n  \"fields\": [\n    { \"name\": \"priority\", \"type\": \"select\", \"options\": [\"low\", \"medium\", \"high\"], \"required\": true },\n    { \"name\": \"assignee\", \"type\": \"text\", \"default\": \"unassigned\" },\n    { \"name\": \"estimate\", \"type\": \"number\", \"min\": 1, \"max\": 100 },\n    { \"name\": \"labels\", \"type\": \"multiselect\", \"options\": [\"frontend\", \"backend\", \"devops\"] }\n  ]\n}\n```\n\n| Key | Type | Description |\n|---|---|---|\n| `root` | `string` | Path to board root, relative to this file |\n| `columns` | `string[]` | Ordered column names |\n| `fields` | `FieldConfig[]` | Custom field definitions (optional) |\n\nConfig is discovered by walking up from the working directory, so commands work from any subdirectory.\n","readmeFilename":"README.md"}