Repo-shipped skill previously framed CLI as primary surface with MCP
as a separate "recommended" alternative. Recipes still used CLI calls
even though MCP server has been the recommended surface since v0.3.1.
Now: MCP tool catalog (6 tools as `mcp__kebab__<name>`) leads, recipes
call MCP tools directly, CLI documented as fallback for hosts without
MCP. Generic wording preserved (no user-specific trigger keywords).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
set_draw_target switching broke cursor positioning: each hidden→stderr
restore caused indicatif to draw a fresh line instead of overwriting.
Root fix: call only set_position() in TTY AssetStarted (one draw per
file). Filename visible in non-TTY plain-line output.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
set_position() and set_message() each call update_and_draw()
independently, producing two scrollback lines per file in TTY mode.
Suppress the draw target before the two updates, restore to stderr,
then call tick() to emit exactly one frame.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
dirs::config_dir() and dirs::data_dir() both return ~/Library/Application Support
on macOS, so data_dir == config parent dir. ResetScope::DataOnly removes data_dir
and silently deletes config.toml along with it.
Fix: bypass dirs crate fallback for config/data/cache dirs; use
$HOME/.config, $HOME/.local/share, $HOME/.cache directly (XDG standard).
xdg_state_dir already used this pattern. dirs::home_dir() still used for
portability.
Migration: Config::load(None) auto-copies legacy ~/Library/Application
Support/kebab/config.toml to the new ~/.config/kebab/ on first run and
prints a migration notice to stderr.
AssetStarted now advances position (idx-1) and sets message together.
AssetFinished no longer updates the bar — Completed handles final
cleanup via finish_and_clear. Result: one bar frame per file instead
of two, eliminating the scrollback duplicate-line artifact.
- fb-26 (progress.rs): Fixed Aborted unconditional writeln (TTY duplicate output)
and Completed TTY path missing summary line. Added KEBAB_PROGRESS=plain env
override and quiet field to ProgressMode.
- fb-28 (main.rs): Added --readonly / --quiet global flags with KEBAB_READONLY env.
Readonly blocks mutating commands (ingest/ingest-file/ingest-stdin/reset) with
exit code 1; error.v1 code "readonly_mode" in --json mode. Quiet suppresses all
human progress/hint stderr while preserving errors.
- Updated task spec status for p9-fb-26 and p9-fb-28 to 'merged'.
- Updated tasks/INDEX.md and HANDOFF.md with merge status and summary entries.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add readonly/quiet fields to Cli, parse_bool_env for 1/true/yes/on support,
is_mutating guard that short-circuits with error.v1 on write-path commands,
and wire KEBAB_PROGRESS=plain through from_flags in the Ingest arm.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add `quiet: bool` to `Human` variant and expand `from_flags` to three
args (`json`, `quiet`, `plain_env`). Update `handle`/`handle_human`
accordingly; add four targeted unit tests (TDD).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- ingest_file_with_config: lowercase normalize ext (caller-side) +
early error on unsupported extension (`.docx` etc. now Err with
helpful message instead of silent skipped_by_extension counter).
New test ingest_file_errors_on_unsupported_extension.
- ingest_stdin_with_config: doc comment explaining intentional
double-call of ensure helpers (idempotent + ~ms negligible).
- external::inject_frontmatter: simplify precheck via single
trim_start binding + add CR-only line ending edge case.
- external::inject_frontmatter: doc note on yaml_quote escape
contract (agent-supplied titles with special chars are safe).
Round 1 review summary: #111 (comment)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- kebab-app: add #[doc(hidden)] to ingest_stdin_with_config (CLAUDE.md
convention — all *_with_config functions should have this attribute;
fb-31's first impl missed it on the second facade fn).
- SKILL.md: "Since v0.4.0" → "Since v0.3.1" (MCP shipped in fb-30
release v0.3.1; the wrong version claim was introduced in fb-30 doc
sync and carried forward into fb-31).
- tools_call_ingest_file: add idempotency test (second call with same
content → unchanged=1, new=0). Spec called for two tests; first impl
shipped only the happy path.
Version bump 0.3.1 → 0.3.2 deferred to separate `chore/bump-v0.3.2` PR
mirroring fb-27 + fb-30 precedent (commits 73f5d73 / 5495d96).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
fb-31 added ingest_file + ingest_stdin MCP tools (Task 9) but the
spawn-based smoke test in cli_mcp_smoke.rs still asserted the fb-30
count of 4. Bump to 6 to match the live tools/list response.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5th + 6th MCP tools — first mutation surface (fb-30 v1 was read-only).
Both wrap the new kebab-app facade fns + use spawn_blocking via the
existing spawn_tool helper. tools/list now returns 6 tools.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wraps body with YAML frontmatter (title + source_uri) via
crate::external::inject_frontmatter, writes to
_external/<hash12>.md, delegates to ingest_file_with_config. Markdown
only in v1.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three scenarios — copies external md + reports new=1, idempotent on
second call (unchanged=1), errors on missing path.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Single-file ingest entry. Copies bytes to _external/<hash12>.<ext>
via crate::external::copy_to_external, runs the per-medium pipeline on
that single asset (reuses ingest_with_config_opts via a SourceScope
{ root: _external/, include: [<filename>], exclude:
config.workspace.exclude }).
`.kebabignore` matches log a stderr warn line and proceed (explicit
ingest is bypass intent). Internal helper `check_kebabignore_match`
uses the `ignore` crate's GitignoreBuilder.
Returns the standard IngestReport (incremental ingest from fb-23
handles re-ingest as `unchanged`).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
신규 명령 `kebab ingest-file` + `kebab ingest-stdin` + MCP tool
`ingest_file` + `ingest_stdin` 도입 brainstorm 산출물. agent fetch 한
web markdown / 단일 외부 file 을 KB 에 즉시 저장.
핵심 결정:
- 외부 file 저장: copy in (`<workspace.root>/_external/<hash12>.<ext>`).
blake3 content hash 기반 deterministic 명명 → idempotent.
- CLI: 신규 subcommand 2개 (기존 `kebab ingest` 무영향).
- MCP: 4 → 6 tool. fb-30 v1 read-only 정책 변경 — 첫 mutation tool
surface (의도된 진화).
- .kebabignore: explicit ingest 가 default bypass + stderr warn.
- stdin v1: markdown 전용 + flag (--title, --source-uri) → frontmatter
자동 prepend. 이미 frontmatter 있으면 error (use ingest-file).
- `_external/` 디렉토리 첫 생성 시 .kebabignore 자동 append (walk
re-ingestion 무한 루프 방지).
- source_uri 는 frontmatter → Document.metadata 자동 흐름. wire
schema 변경 없음 (ingest_report.v1 / search_hit.v1 의 metadata
free-form map 재사용).
릴리스: 0.3.1 → 0.3.2 patch — additive only.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
agent integration MVP (fb-30 MCP server stdio) 머지 후 patch bump.
trigger:
- 신규 CLI surface `kebab mcp` (additive, 기존 명령 동작 무영향)
- new crate `kebab-mcp` (lib only, transitive 만)
- capability flag `mcp_server: false → true` (additive on schema.v1)
- design §10.2 MCP transport 절 추가 (additive subsection)
CLAUDE.md release 규약상 wire schema additive / surface 추가는
minor bump 영역이지만, pre-1.0 (0.x.y) 단계에서는 fb-26~31 group
누적 시까지 0.3.x patch 로 묶고, 큰 jump 시 0.4.0 cut 으로 운용.
fb-30 단독으로 break 없는 additive 라 0.3.1 patch 적정.
후속 fb-26 / 28 / 31 머지 시점에 추가 0.3.x patch 누적, breaking
schema 변경 시 0.4.0 minor.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>