# RFE: public `isatty(fd: int): bool` binding

**Filer:** repoman v0.1.1 implementation
**Reef version:** 0.5.18
**Date:** 2026-05-03
**Severity:** Low — blocks one polish item; clean workaround possible by importing whole tty module if its internal C conflicts are fixed

---

## Summary

Common need: detect whether a given file descriptor (typically `STDOUT`/`STDERR`) is a terminal, to switch between interactive and non-interactive output modes. Today there is no user-callable API for this:

- `ui.backend.tty` declares `extern "C" fn reef_tty_is_tty(fd: int): int` privately and uses it internally (`if reef_tty_is_tty(STDOUT_FD) == 0`), but does not export a wrapper.
- `sys.fd` exports `STDIN()`, `STDOUT()`, `STDERR()` and various read/write/dup primitives, but no `isatty`.
- `sys.platform.libc` does not bind `isatty(3)`.

Workarounds either fail at link time (`extern "C"` declaration in user code links against an undefined symbol) or fail at compile time (importing `ui.backend.tty` pulls in conflicting `extern int write(int fd, char* buf, int count);` that clashes with the runtime's own `write` declaration).

## Use case

repoman v0.1.1 task A2 (TTY detection for rsync progress): when stdout is a terminal, repoman wants to pass `--info=stats2,progress2` to rsync (live progress); otherwise `--info=stats2` (cron-friendly). Currently hardcoded `is_tty: bool = false` for cron compatibility; missing the live-progress UX in interactive use.

This is a generic CLI need — any tool that wants to render progress bars, ANSI colors, or interactive prompts needs to detect TTY context.

## Proposed API

Either of:

```reef
// In sys.fd:
fn isatty(fd: int): bool

// Or in ui.backend.tty (publicly exported):
fn is_tty(fd: int): bool
```

Trivial wrapper:
```reef
fn isatty(fd: int): bool
    return reef_tty_is_tty(fd) == 1
end isatty
```

`sys.fd` feels more correct since `isatty(3)` is a POSIX file-descriptor primitive, but `ui.backend.tty` is also reasonable since the implementation already lives there. Either works.

## Side issue

If `ui.backend.tty` becomes the home, the existing `extern int write(int fd, char* buf, int count);` declaration inside that module needs to be removed or replaced — it conflicts with the runtime's own `write` declaration, which makes importing `ui.backend.tty` from a user program fail to compile (`error: conflicting types for 'write'`). If the goal is for user code to be able to import `ui.backend.tty` cleanly, that needs fixing regardless.

## Repoman impact

A2 in our v0.1.1 polish list is parked until this lands. Trivial to wire in once the API exists (one-line replacement in `cli.cmd_sync`).

---

*Filed by the repoman v0.1.1 build flow.*
