# knitr: a literate programming engine that guesses its settings and sed-parses its own name

> yihui/knitr mixes R code with prose and hands chunk level control to the user. Its front page is mostly a list of complaints about Sweave, and the build is a Makefile that recovers the package name and version by running sed over DESCRIPTION.

**yihui/knitr** — A general-purpose tool for dynamic report generation in R

- Repository: https://github.com/yihui/knitr
- Website: https://yihui.org/knitr/
- Stars: 2,468 · Forks: 877
- Language: R
- License: not declared
- Published: 2026-09-28 · Updated: 2026-09-28 · Language: en
- Canonical page: https://hysenlabs.com/projects/yihui-knitr

## When you leave an option out, knitr guesses

The only sentence the front page offers about settings says that if options are not explicitly specified, knitr will try to guess reasonable default settings. Nothing follows it. There is no table of guessed values, no statement about which directory counts as the project root when you hand a file to knit, and no error path for a guess that turns out to be wrong. Set against the rest of the pitch, which is about lightweight APIs giving users full control of the output without heavy coding work, the gap is worth naming plainly: control is promised at the level of an individual chunk, and the settings that would tie a chunk to a location on disk are the ones left to inference. The main manual, the graphics manual and the FAQ pages on the package homepage are where that behaviour belongs. The front page promises a guess and stops talking.

## A motivation section written as nine complaints about Sweave

Rather than list what it does, the project explains itself through what the author wanted from Sweave and its add-on packages. Reading down the list: chunk level control of figure width, the thing that needed `[width=.8\textwidth]` between `\includegraphics` and `{my-plot.pdf}`, because `\setkeys{Gin}` sets one global width and figures often differ. Graphics devices other than PDF and postscript, wanted as something as plain as `dev = 'png'` or `dev = 'CairoJPEG'`. Every plot in a chunk recorded, not only the last one. Numbers inside `\Sexpr{}` rounded without writing `round(x, 3)` at every single site. Plots that do not need a `print()` call, so that ggplot2 objects and `qplot(x, y)` just work. No instructions for `Sweave.sty`, which LaTeX sometimes cannot find. Cached chunks that still print their results. Graphics in brew, syntax highlighting in R2HTML. Then an ellipsis, and an Amazon link to the book dropped in the middle of the list with no sentence attached.

## One entry point, and the style file it wants you to stop needing

The usage section is three lines long, and it is the whole documented interface:

```r
library(knitr)
?knit
knit(input)
```

No step in that sequence invokes a typesetter. There is no PDF command, no LaTeX call, and no note about which output formats `knit(input)` produces, only a pointer to the package homepage for details and examples. The one LaTeX package named anywhere on the page is `Sweave.sty`, and it appears as a grievance: the author wished users would never need instructions for it, or run into trouble because LaTeX cannot find it. The same paragraph of history worries that cacheSweave and pgfSweave carry large amounts of code copied from official R, which turns into an obligation to track new R releases. So the package positions itself as the replacement for those engines, while the downstream typesetting stays somebody else's problem.

## The Makefile recovers the package name with sed

Three variable definitions decide what every other target builds:

```
PKGNAME := $(shell sed -n "s/Package: *\([^ ]*\)/\1/p" DESCRIPTION)
PKGVERS := $(shell sed -n "s/Version: *\([^ ]*\)/\1/p" DESCRIPTION)
PKGSRC  := $(shell basename `pwd`)
```

The first two run at parse time and take the value straight out of DESCRIPTION, stopping at the first space or tab. The third takes the name of whatever directory make happens to be running in, which is then used as the argument to `R CMD build` after a `cd ..`. The install target needs both recovered values to spell the archive:

`R CMD INSTALL $(PKGNAME)_$(PKGVERS).tar.gz`

If DESCRIPTION ever puts a tab between the colon and the value, the capture finds nothing, both variables expand empty, and make raises no error while the tarball name loses its package prefix and its version. Nothing in the file checks that the recovered values look like a package. `PKGSRC` has a related weakness: it is the checkout directory name at parse time, so a build started from anywhere else than the package root resolves to a different source directory.

## make deps installs its helpers from a plain HTTP mirror

The documentation and package tooling arrive through one target:

```
deps:
	tlmgr install pgf preview xcolor;\
	Rscript -e 'if (!require("Rd2roxygen")) install.packages("Rd2roxygen", repos="http://cran.rstudio.com")'
```

Three TeX packages, pgf, preview and xcolor, come through tlmgr, the TeX package manager rather than the R one. Rd2roxygen is fetched conditionally, only when it is not already loadable, and the repository it is fetched from is named with an `http://` URL and no transport security, while the install snippet on the front page points at `https://cloud.r-project.org`. So the build recipe and the installation instructions name two different hosts for the same package index. The `docs` target then hands the package root to rab with building switched off. The default target is `all: check clean`, which runs a full CRAN style check and then deletes the check directory it just produced, so a plain `make` leaves nothing behind to inspect.

## A target named travis, and integration checks in a sibling repository

There is a `travis:` target, and it does not touch Travis. It builds the tarball and runs `R CMD check --no-manual`, which is the same work as `check` without `--as-cran`:

```
check: build-cran
	cd ..;\
	R CMD check $(PKGNAME)_$(PKGVERS).tar.gz --as-cran
```

The name is a leftover. What runs now is the pair of GitHub Actions workflows the badges point at, R-CMD-check.yaml and knitr-examples.yaml. The integration path is stranger, because it leaves the repository entirely:

```
integration-run:
	xvfb-run make deps knit -C knitr-examples

integration-verify:
	GIT_PAGER=cat make diff -C knitr-examples
```

Both step into a knitr-examples directory beside the checkout with `make -C`, and no such directory appears among the top-level entries here. Verification is not a test result at all; it is a git diff in that other repository, with the pager replaced by cat. A fresh clone cannot run either target without that sibling directory, and xvfb-run asks for a virtual X display on top of it. The `examples:` target stays inside the package, running knit-all.R from inst/examples.

## Two ways in: CRAN, or an hourly build on a personal mirror

Installation is offered twice. The stable path is a single call:

```r
install.packages('knitr')
```

The development path is described as an hourly build served from a personal universe, and it works by remapping the repository names before the same call:

```r
options(repos = c(
  yihui = 'https://yihui.r-universe.dev',
  CRAN = 'https://cloud.r-project.org'
))

install.packages('knitr')
```

Two details are worth reading twice. The mapping key is the word yihui, and the ordinary CRAN entry is kept alongside it under its own name, so dependencies still resolve from the main index rather than from the personal mirror. And the word hourly is doing real work in that sentence: nothing in this repository pins a snapshot, so two people installing the development version minutes apart can get different code with the same version number. The Makefile offers no matching target for either path, since install there means building the tarball from the checkout and installing it with R CMD INSTALL.

## Nine months between releases, three days between pushes

Three release dates are on record: v1.50 on 2025-03-16, v1.51 on 2025-12-20, and v1.52 on 2026-09-06. Each gap runs to roughly nine months. The master branch, meanwhile, took a push on 2026-10-01 and the repository is not archived, so the gap is not a sign of abandonment. It does mean the version on CRAN trails the committed code by months, and that a bug fixed on master stays unfixed for anyone on the stable install until the next tag. Separately, the licence is stated in one sentence at the end of the front page: the package is free and open source software licensed under GPL. No version of GPL is named, and no LICENSE file appears among the top-level entries. What does appear beside the English front page is README-ES.md and README-PT.md, plus a separate FAQ.md, NEWS.md, and directories for docs, inst, man, tests and vignettes.

## Conclusion

knitr suits R users who want to set each chunk instead of one global option, and it hands that control over at the price of making you find out what it guessed on your behalf. Before you depend on it, pin down which version you actually have, since releases sit months behind the master branch, work out the working directory behaviour yourself because the front page promises a guess and nothing more, and do not expect the engine to hand you a finished document, because no step in its own instructions runs a typesetter. Its build tooling is best read as the maintainers' private scaffolding: it reaches into a sibling examples checkout and a plain HTTP mirror.

## FAQ

### How do you use the knit function in R?

Three lines cover the whole entry point: load the package with library(knitr), open its help with ?knit, then pass your document to knit(input). Anything you leave unset is guessed rather than fixed, and the front page sends further reading to the main manual, the graphics manual and the FAQ pages on the package homepage.

### What is knitr used for?

It is an R package for literate programming, a general purpose engine that mixes R code with prose and gives per chunk control over the output instead of a single global setting. Its own account of its purpose is written almost entirely as a list of things the author wanted from Sweave: per chunk figure widths, graphics devices other than PDF and postscript, and not having to print() plots.

### What does the Makefile need before it can rebuild the documentation?

The deps target installs the TeX packages pgf, preview and xcolor through tlmgr, then installs Rd2roxygen from http://cran.rstudio.com, written as a plain http URL. The docs target then calls rab on the package root with building switched off. The installation instructions on the front page name a different host, https://cloud.r-project.org.

### Can the integration targets run from a fresh clone?

Not as written. integration-run runs xvfb-run make deps knit -C knitr-examples, and integration-verify runs GIT_PAGER=cat make diff -C knitr-examples, so both step into a knitr-examples directory that has to sit beside the checkout and does not appear among the top-level entries here. Verification is a git diff in that sibling repository rather than a test result, and xvfb-run wants a virtual X display.

### Which license does knitr use?

The front page closes by calling the package free and open source software licensed under GPL, without naming a version of it. No LICENSE file appears among the top-level entries of the repository, so the exact terms are not settled by anything in the root listing.

## Sources

- [Issues](https://github.com/yihui/knitr/issues)
- [Project website](https://yihui.org/knitr/)
- [README](https://github.com/yihui/knitr/blob/master/README.md)
- [Releases](https://github.com/yihui/knitr/releases)
- [yihui/knitr on GitHub](https://github.com/yihui/knitr)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/yihui-knitr
