App-karr
view release on metacpan or search on metacpan
with the note on STDERR. The defaults keep their honest use â "what would
a board created here start with?" is a real question â but have to be
asked for: `karr config show --defaults` (and `get KEY --defaults`) reads
no board, needs no repository, and answers the same everywhere, so the
difference between the board's value and karr's is carried by the exit
code rather than by an unmarked payload. Which key it is does not decide
anything: in a fresh clone every key can be overridden on the remote, and
`board.name` is only the one that almost always is. `--defaults` renders
identically to a board read, so `diff <(karr config show) <(karr config
show --defaults)` is exactly the set of keys a board overrides. It is
rejected on `set`, with exit 2.
- The read-only commands no longer render an empty board where there is no
board (ticket #135). `board`, `list`, `show`, `log`, `context` and the
bare `karr` summary never asked whether a board was there; they rendered
the code defaults over an empty task list, so a repository holding no
board printed exactly what a board holding no cards prints â down to the
byte, once the board is called "Kanban Board". `git clone` does not fetch
`refs/karr/*`, which makes that the normal state of every fresh clone,
where the tickets are all still on the remote: a user who trusts `0 tasks`
there concludes they are gone. The reads stay offline â a pull in front of
every `karr show` is not worth it, and a stale read is recoverable where a
stale write is not â but they now report what they actually read. Nothing
under `refs/karr/` is refused with exit 1 and a message that names the
namespace, denies the empty-board reading, and, where the repository has a
remote, leads with `karr sync` rather than `karr init`: the board is
unfetched rather than absent, and `init` would answer that by starting a
second, empty one. A half-board (#133) is read rather than refused â its
tasks are demonstrably there â with the note that `refs/karr/config` is
missing on STDERR, so `--json` stays parsable. An initialized board with
no tasks answers exactly as before, which is the distinction that was
missing. `--json` consumers tell the two apart the way they tell every
other karr failure apart: exit 1 and an empty stdout, rather than a
payload full of zeros. The agent skill says so too, in its Sync section:
a fresh clone has no `refs/karr/*`, the read commands refuse until
`karr sync` has run, and `karr init` is the wrong answer there. That is
the loop this came out of â an agent read an empty board, believed it,
and reached for `init`.
- The runtime images can reach an `ssh://` remote (ticket #134). They
shipped without an ssh binary â `runtime-base` installed `git gosu passwd`
and the shared libraries, and nothing else â so git's CLI fallback died
with `error: cannot run ssh: No such file or directory` and a board on an
ssh remote was unreachable from the published images. That fallback is not
decoration: it is there for the ssh-config and `ProxyCommand` setups
libgit2 cannot do, and it could never take a single one of them.
`openssh-client` is now installed with the rest. The other half was the
README's recommended alias, which mounted `.gitconfig`, `.claude`,
`.codex` and `.cursor` but not `.ssh`, while setting `HOME=/home/karr` â
so libgit2 looked for `known_hosts` in a directory that did not exist and
reported every host as unknown, and the fix it printed
(`ssh-keyscan ⦠>> ~/.ssh/known_hosts`) was carried out on the host, where
the container never saw it. The alias now mounts `~/.ssh` read-only, and
an agent-forwarding variant is documented as a shell function, since
`docker run` rejects the socket mount outright when no agent is running.
Neither half helps alone: an ssh binary with no keys cannot authenticate,
and mounted keys with no ssh binary cannot fall back. A third piece only
turned up when the finished image was pointed at a real ssh remote: the
root image drops to whoever owns F</work>, and that host uid has no
C</etc/passwd> entry, so C<ssh> â which looks itself up with
C<getpwuid()> â refused to start with `No user exists for uid 1000`. The
entrypoint now writes an entry for the uid before dropping to it. The
fixed-user image never had this problem, since C<useradd> wrote one at
build time; the default image, the one the README recommends, had it for
every ssh remote.
- `karr init` no longer stamps the encoding marker on a board it is
completing rather than creating (ticket #132). `init` accepts a
half-board â task refs present, `refs/karr/config` missing â and finishes
it (#62), but it used to write `refs/karr/meta/encoding` on the way out
either way. On a board from 0.402 or earlier that marker asserts the
opposite of what the adopted task refs carry: the read path stopped
undoing their double-encoded UTF-8, every old card turned to mojibake
(`⦠Transport prüfen â` became `⦠Transport prüfen â`), and `karr
repair` then reported the board as already up to date and declined to
migrate it, leaving hand-deleting a ref as the only way back. Not one
byte in the refs changes in that failure, which is why it was invisible.
The marker is now written only by an `init` that found nothing at all
under `refs/karr/`, so a completed half-board keeps both the repair on
read and `karr repair --yes`. `karr import --yes` had the same defect and
the same fix: it rewrites the task refs from the file view but never the
activity log under `refs/karr/log/` (nor the config, when the view
carries no `config.yml`), so on a pre-0.403 board it stamped a claim it
could not make and turned every old log entry into mojibake. It now
stamps only a board that import itself created. `karr repair --yes` is
unchanged and remains the one command that may stamp an existing board,
because it is the one that rewrites every ref.
- "No karr board found. Run 'karr init' to create one." no longer speaks
for two different repositories (ticket #133). Write commands raised it
whenever `refs/karr/config` was absent, including on a repository whose
tasks, counter and log were all there â so a board missing exactly one
ref reported itself as never having existed. An agent hit that on a
repository holding 21 tickets, believed them gone, and ran `karr init`,
which at the time also broke how they were read (#132 above). A
repository with nothing under `refs/karr/` still gets the old sentence,
the one `backup`, `destroy`, `materialize` and `repair` raise for the
same state. A half-board now gets its own: it is named as one, the number
of task refs at stake is stated, and `karr init` is described as
completing the board while keeping what is already there. `karr init`
likewise reports which of the two things it did.
- `karr config get statuses` and `karr config get classes` are readable
again (ticket #130). Both lists allow an entry to be either a bare name or
a mapping â `{ name: in-progress, require_claim: true }`,
`{ name: expedite, wip_limit: 1 }` â and the renderer joined the raw list,
so every mapping printed as `HASH(0x558580cd1688)`. The default board hits
it twice in `statuses` and, because all four of its classes are mappings,
four times out of four in `classes`, where the answer carried no name at
all. An entry now renders as its name followed by its per-entry settings
in parentheses â `in-progress (require_claim: 1)`, `expedite
(bypass_column_wip: 1, wip_limit: 1)` â and `karr config show` renders the
two lists the same way instead of dropping the settings, so the overview
and the single-key lookup cannot disagree about what the board's columns
are. `--json` is unchanged: it already carried the entries as configured,
and still does. This was not cosmetic â that output is what a reader
consults to learn which columns a board has, and the unreadable entries
led an agent to describe an "extended status set" with a `closed` status
that no board in the tree configures.
- The `runtime-user` image build no longer warns about `/home/karr`. The
shared `runtime-base` stage used to create that directory, so
`runtime-user`'s `useradd -m` was asking for a home that already existed
and printed `useradd: warning: the home directory /home/karr already
( run in 1.460 second using v1.01-cache-2.11-cpan-f0ff5d10edf )