# LESSONS
This file is a shared memory for implementation tasks. It should capture stable decisions, preferences, sharp edges, and project structure notes that future work should reuse.
## Current decisions
- The tool name is `hy`.
- The project is a Rust CLI, starting as a single binary crate.
- The crate should stay dependency-free unless a later task proves a strong need for external crates.
- Logs must remain plain text so they are still usable with `grep` and similar tools.
- The preferred on-disk format is escaped TSV, not JSON and not a database.
- Daily files should live under `~/.logs/` with names like `bash-history-YYYY-MM-DD.log`.
- `hy` should replace custom logging logic in shell snippets, but it cannot eliminate shell integration entirely.
## Shell integration gotcha
- Bash and zsh know what command just ran; a standalone binary does not.
- Because of that, `hy` can centralize the logic, but it still needs either:
- a minimal shell hook that calls `hy record`, or
- an instrumented shell mode such as `hy shell` later
- Generated shell hooks should call `${HY_BIN:-hy}` so users can override the binary path without editing the managed block.
- `hy install` should manage a clearly marked block inside the rc file and update it in place so reinstalling stays idempotent.
## Parsing gotcha
- The original space-delimited format is ambiguous when paths or commands contain spaces.
- Exact folder matching depends on adopting the structured escaped-TSV format.
- Legacy logs should be treated as migration input with best-effort parsing only.
- The legacy parser currently looks for the shell history number boundary after an absolute-looking `pwd` path, which is good enough for migration but not exact.
- Structured lines should fail fast on malformed field counts or broken escape sequences instead of guessing.
## Record contract
- The searchable log line stores exactly three escaped-TSV fields: timestamp, cwd, and command.
- `history_id` is useful for duplicate suppression, but it should not be written into the searchable log line.
- Duplicate suppression state can live in a separate hidden text file inside the log directory.
- `hy record` should reject missing `--cwd` and empty `--command` values before touching the filesystem.
- If the duplicate-suppression state file is missing or corrupt, recording should continue and the state should be refreshed instead of failing.
- The current timestamp is produced inside `hy` via the system `date` command so the shell hook does not need to supply it.
- `HY_LOG_DIR` should override the log directory for both recording and searching.
- Relative `HY_LOG_DIR` values should resolve from the user's home directory so behavior stays stable across working directories.
## Search semantics
- `hy <query>` should search command text by substring in v1.
- `hy --folder <path>` should resolve relative paths from the caller's current working directory.
- Path-like folder filters should expand from the caller's current directory, but plain values such as `src` should work as substring matches against the logged cwd.
- `hy --folder .` should mean "current directory and descendants".
- Search currently skips malformed log lines instead of failing the whole command.
- Search results should come back newest first by file date and then reverse line order within each file.
- Default rendered output should stay one escaped-TSV line per match so it remains easy to pipe or grep.
- Folder resolution should be lexical normalization only; do not canonicalize against the filesystem because the logged shell path may intentionally preserve symlinks.
- `--today` and `--since` should filter by the daily log filename date first, not by re-parsing every entry timestamp.
- `--json` output can be rendered without dependencies as a compact array of objects including source file and line metadata.
- Search should fail fast when the user provides neither a query nor a folder filter.
- Case-insensitive search should apply to both command text and folder filters.
- `HY_IGNORE_CASE` should accept `1/0`, `true/false`, `yes/no`, and `on/off`.
## Scope guardrails
- No database in v1.
- Directly scan daily log files first; optimize only if real usage demands it.
- Keep output human-readable by default.
- Move logic into Rust and keep shell snippets as thin as possible.
## Testing notes
- End-to-end CLI tests should prefer spawning the built `hy` binary with a temporary `HOME` instead of mutating process-global environment variables inside the test process.
- Record/search flow tests should cover duplicate suppression, folder-only searches, and machine-readable JSON output.
## Repository notes
- `tasks.md` is intentionally local-only and must not be committed.
- `README.md` should describe shipped behavior and setup, not stale planning notes.
- `LESSONS.md` should record decisions that future tasks should not rediscover.
- Keep the crate split into `lib.rs` plus a thin `main.rs` so command parsing and behavior remain easy to unit test.
- GitHub Actions should keep CI simple on push and treat `v*.*.*` tags as release triggers.
- The release workflow should update the checked-out Cargo version to match the tag before building assets, without relying on the committed manifest version already being bumped.