Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
bd92a71
docs(adr): bootstrap ADR catalogue scaffold
vilaca May 18, 2026
216c704
docs(adr): 0001 no cyclic imports anywhere under src/
vilaca May 18, 2026
b09ab2f
docs(adr): 0002 src/core/ has no dependency on src/ui/ or src/cli/
vilaca May 18, 2026
050f374
docs(adr): 0003 src/security/ and src/utils/ are primitive layers wit…
vilaca May 18, 2026
b7d0a79
docs(adr): 0004 src/providers/ has no dependency on src/ui/ or src/to…
vilaca May 18, 2026
95aeb01
docs(adr): 0005 src/providers/openai/ is an internal adapter with no …
vilaca May 18, 2026
4664634
docs(adr): 0006 src/mcp/ and src/ui/ must not import each other
vilaca May 18, 2026
45bd667
docs(adr): 0007 src/ui/headless.ts must not depend on the TUI tree
vilaca May 18, 2026
6b3abfb
docs(adr): 0008 src/ui/ is a presentation layer with no concrete prov…
vilaca May 18, 2026
4d410e3
docs(adr): 0009 provider abstraction with a shared OpenAI-compatible …
vilaca May 18, 2026
4b19b98
docs(adr): 0010 two-tier rotation per key then per provider:model tuple
vilaca May 18, 2026
62f3fbd
docs(adr): 0011 AgentEvent as the single contract between core loop a…
vilaca May 18, 2026
6cfcfb0
docs(adr): 0012 plan mode gates writes not all tool calls
vilaca May 18, 2026
e9c14a1
docs(adr): 0013 built-in security rules are additive only
vilaca May 18, 2026
5d95f2f
docs(adr): 0014 tool-call resilience stack for non-frontier models
vilaca May 18, 2026
03bbe20
docs(adr): 0015 context compaction recency window plus summary finger…
vilaca May 18, 2026
7769f3d
docs(adr): 0016 MCP servers wrapped as ToolHandlers in the shared reg…
vilaca May 18, 2026
5b40684
docs(adr): 0017 session log as JSONL in ~/.factory/sessions/
vilaca May 18, 2026
97455c7
docs(adr): 0018 hooks with sandboxed env forbidden-command guard and …
vilaca May 18, 2026
9be1903
docs(adr): 0019 multi-tab session model with one independent agent pe…
vilaca May 18, 2026
33b7e26
docs(adr): 0020 manual argv parser without commander or yargs
vilaca May 18, 2026
0db7770
docs(adr): 0021 renderer split Ink TUI vs plain-stdout headless one c…
vilaca May 18, 2026
205c202
docs(adr): 0022 subagent isolation with separate conversation and res…
vilaca May 18, 2026
f79b71a
chore: rename npm package to factory-code
vilaca May 19, 2026
a2bfb84
chore: drop unused handleProjectHookTrust alias
vilaca May 19, 2026
06892eb
docs: drop literal version from README --version example
vilaca May 19, 2026
079830b
docs: add VitePress site with GH Pages deploy
vilaca May 19, 2026
01a58a6
ci(docs): npm ci --legacy-peer-deps for VitePress install
vilaca May 19, 2026
4e70321
chore(npm): add keywords matching repo topics
vilaca May 19, 2026
048930a
ci: add GitHub Actions workflow + status badge in README
vilaca May 19, 2026
c43e998
docs: add repo social preview asset (.github/social-preview.svg)
vilaca May 19, 2026
4e90149
docs: add rendered PNG of social preview asset
vilaca May 19, 2026
71cf341
ci: upgrade npm before npm ci (Node 22 ships npm 10, lockfile needs 11)
vilaca May 19, 2026
7fd0625
ci: use 'npx npm@11.12.1 ci' instead of upgrading global npm
vilaca May 19, 2026
aa138d8
fix(retry): keep event loop alive during backoff sleep
vilaca May 19, 2026
eccde41
fix: stop unref-ing test-relevant timers + tighten system-prompt test
vilaca May 19, 2026
af2cf5e
test(e2e): bump waitForOutput timeouts from 5s to 30s
vilaca May 19, 2026
6a7f3bd
test(e2e): double waitForOutput timeouts to 60s
vilaca May 19, 2026
f606af9
test(e2e): revert timeout to 5s; skip 4 CI-flaky picker tests
vilaca May 19, 2026
eb9969f
fix(html): loop sanitizer passes to defeat splice-bypass payloads
vilaca May 20, 2026
3d31755
ci: pin workflow permissions to contents: read
vilaca May 20, 2026
cbb4bda
fix(deps): override vite to ^6.4.2 to clear path-traversal advisory
vilaca May 20, 2026
de69642
fix(deps): bump brace-expansion 5.0.5 -> 5.0.6 to clear DoS advisory
vilaca May 20, 2026
7f32e90
refactor(html): wrap each sanitizer pattern in its own fixpoint loop
vilaca May 20, 2026
50f879c
docs: align README + package.json tagline with new About text
vilaca May 20, 2026
bc78a31
docs: lead Quick start with from-source until factory-code ships on npm
vilaca May 20, 2026
c282587
refactor: parallelize startup I/O and tighten a few hot paths
vilaca May 20, 2026
1483bda
refactor(providers): extract shared formatTokenCount / normalizeBaseU…
vilaca May 20, 2026
dc5fc8a
refactor: unify tool-call pipeline + stream Read with limit
vilaca May 20, 2026
cb67208
refactor: shared helpers (parseToolArgs / errorMessage / factoryHomeP…
vilaca May 20, 2026
a620b2e
test: release-gate e2e harness covering ~80% of the manual checklist
vilaca May 21, 2026
276b57e
ci: run npm run test:release; drop unused assert imports
vilaca May 21, 2026
eec18aa
test: run e2e sequentially (--test-concurrency=1)
vilaca May 21, 2026
7ea24ed
test: skip PTY suites when CI=true
vilaca May 21, 2026
027acd0
feat(session-log): route all UI errors and warnings through SessionLo…
vilaca May 22, 2026
d610bfe
fix(swap): treat `<unknown>:<tag>` as a bare model on the current pro…
vilaca May 22, 2026
d11914d
feat(session-log): capture every outgoing LLM call as `model-request`
vilaca May 22, 2026
84e0c53
docs(adr): drop Status field, accepted-on-merge by convention
vilaca May 23, 2026
b6b325c
docs(adr): 0017 add session-start, model-request, and warning-log inv…
vilaca May 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .github/social-preview.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
69 changes: 69 additions & 0 deletions .github/social-preview.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 30 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]

permissions:
contents: read

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'
# Node 22 ships npm 10; the lockfile is generated by npm 11+ which
# handles transitive peer ranges (e.g. @types/react@18 pulled through
# dev deps) differently — npm 10 rejects with "package.json and
# package-lock.json not in sync." Avoid the global self-upgrade race
# ("Cannot find module 'promise-retry'") by shelling out to a pinned
# npm via npx.
- run: npx -y npm@11.12.1 ci
- run: npm run lint
- run: npx tsc --noEmit
- run: npm run test:release
75 changes: 75 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
name: Deploy docs site

# Builds the VitePress site under .vitepress/ and publishes it to the
# repo's GitHub Pages environment. Triggered on pushes to main that
# touch docs sources (README, ARCHITECTURE, CONTRIBUTING, SECURITY,
# docs/**, or the VitePress config itself), plus a manual dispatch for
# republishing without a content change.
#
# Pages must be enabled on the repo with the "GitHub Actions" source
# (Settings → Pages → Source: GitHub Actions) for the deploy step to
# succeed. The published URL is https://vilaca.github.io/factory/.

on:
push:
branches: [main]
paths:
- 'README.md'
- 'ARCHITECTURE.md'
- 'CONTRIBUTING.md'
- 'SECURITY.md'
- 'docs/**'
- '.vitepress/**'
- '.github/workflows/docs.yml'
- 'package.json'
- 'package-lock.json'
workflow_dispatch:

# One in-flight deploy at a time; newer pushes preempt older ones so
# the site reflects HEAD without queueing redundant builds.
concurrency:
group: pages
cancel-in-progress: true

permissions:
contents: read
pages: write
id-token: write

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'
- name: Install dependencies
# --legacy-peer-deps: VitePress transitively depends on
# @docsearch/react, whose peer declares react < 19. The main
# project pins react@19 (used by Ink), which npm 10 (the version
# shipped with the setup-node@v4 / Node 22 combo) treats as a
# hard conflict and refuses to install. The peer is bogus in
# practice — VitePress doesn't actually mount @docsearch/react
# at runtime when `search.provider: 'local'` is configured (see
# .vitepress/config.ts) — so the legacy resolver is both safe
# and necessary here.
run: npm ci --legacy-peer-deps
- name: Build VitePress site
run: npm run docs:build
- name: Upload Pages artifact
uses: actions/upload-pages-artifact@v3
with:
path: .vitepress/dist

deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,8 @@ coverage/

# Local-only scratch
IDEAS.md

# VitePress docs site build output + deps
.vitepress/dist/
.vitepress/cache/
.vitepress/node_modules/
107 changes: 107 additions & 0 deletions .vitepress/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import { defineConfig } from 'vitepress';

// VitePress site for factory. Reuses the existing repo markdown
// (README.md, ARCHITECTURE.md, CONTRIBUTING.md, SECURITY.md, docs/*)
// as the source of truth — this config only adds nav/sidebar wiring.
//
// Build: `npm --prefix .vitepress run build` produces .vitepress/dist/,
// which the GH Action publishes to GitHub Pages at
// https://vilaca.github.io/factory/.
export default defineConfig({
// GH Pages serves the site under /factory/. Both the dev server and
// the built site must know this so internal links resolve correctly.
base: '/factory/',
title: 'factory',
description:
'A terminal-first coding agent. Self-hosted, provider-agnostic, configurable.',
cleanUrls: true,
lastUpdated: true,
// README links to relative paths like ./docs/providers.md and
// ./ARCHITECTURE.md. VitePress follows those at build time. The few
// exceptions — links to LICENSE (not markdown, served as a GitHub
// file), localhost, and similar — get ignored here rather than
// rewritten in the source README.
ignoreDeadLinks: [
// LICENSE is a plain-text file, not a markdown page. README's
// "see LICENSE" link is valid on GitHub but VitePress can't render
// it as a page. Users land on the GitHub copy either way.
/^\.?\/LICENSE$/i,
/^https?:\/\/localhost/,
],
// README is the landing page; the rest hangs off the sidebar.
rewrites: {
'README.md': 'index.md',
},
// Skip files VitePress shouldn't try to render as pages.
srcExclude: [
'node_modules/**',
'dist/**',
'dist-test/**',
'coverage/**',
'src/**',
'test/**',
'scripts/**',
'CHANGELOG.md',
'IDEAS.md',
],
themeConfig: {
nav: [
{ text: 'Home', link: '/' },
{ text: 'Quick start', link: '/#quick-start' },
{ text: 'Docs', link: '/docs/configuration' },
{ text: 'Architecture', link: '/ARCHITECTURE' },
{ text: 'GitHub', link: 'https://github.com/vilaca/factory' },
],
sidebar: [
{
text: 'Getting started',
items: [
{ text: 'Overview', link: '/' },
{ text: 'Configuration', link: '/docs/configuration' },
{ text: 'Providers', link: '/docs/providers' },
{ text: 'Troubleshooting', link: '/docs/troubleshooting' },
],
},
{
text: 'Usage',
items: [
{ text: 'Slash commands', link: '/docs/slash-commands' },
{ text: 'Hotkeys', link: '/docs/hotkeys' },
{ text: 'Headless mode', link: '/docs/headless' },
{ text: 'WebFetch tool', link: '/docs/web-fetch' },
{ text: 'Sampling params', link: '/docs/sampling-params' },
],
},
{
text: 'Operations',
items: [
{ text: 'Security', link: '/docs/security' },
{ text: 'Observability', link: '/docs/observability' },
{ text: 'Picker internals', link: '/docs/picker-internals' },
],
},
{
text: 'Project',
items: [
{ text: 'Architecture', link: '/ARCHITECTURE' },
{ text: 'Contributing', link: '/CONTRIBUTING' },
{ text: 'Security policy', link: '/SECURITY' },
],
},
],
socialLinks: [
{ icon: 'github', link: 'https://github.com/vilaca/factory' },
],
editLink: {
pattern: 'https://github.com/vilaca/factory/edit/main/:path',
text: 'Edit this page on GitHub',
},
search: {
provider: 'local',
},
footer: {
message: 'Released under the Apache-2.0 License.',
copyright: 'Copyright © vilaca',
},
},
});
4 changes: 4 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,7 @@ The project follows [Semantic Versioning](https://semver.org/). Pre-1.0, breakin
## Architecture overview

See [ARCHITECTURE.md](ARCHITECTURE.md) for a full module map and data-flow walkthrough.

## Architecture Decision Records

Decisions that change an invariant in [ARCHITECTURE.md](ARCHITECTURE.md), `src/security/`, or the `core/agent/` loop require an ADR — see [docs/adr/README.md](docs/adr/README.md) for the catalogue, conventions, and template. Reference the ADR number in the PR description.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# 🏭 factory

[![CI](https://github.com/vilaca/factory/actions/workflows/ci.yml/badge.svg)](https://github.com/vilaca/factory/actions/workflows/ci.yml)
![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)
![Node](https://img.shields.io/badge/node-%3E%3D22-brightgreen.svg)

**A coding agent that runs anywhere — local or cloud, frontier or 7B — with the resilience to make smaller models actually useful.**
**A coding agent CLI engineered to make any LLM — local or cloud, frontier or 7B — actually useful.**

## Why factory

Expand Down Expand Up @@ -33,6 +34,8 @@ That's it. `factory` opens a picker for provider, model, and API key the first t

> **`npm link` permission errors?** It writes a symlink into your npm global prefix; if that's a system path it needs sudo. Either set a user-writable prefix once (`npm config set prefix "$HOME/.npm-global"` and add `$HOME/.npm-global/bin` to your `PATH`), skip linking and run `npx factory` from the repo, or invoke directly with `node /path/to/factory/dist/index.js`.

> **npm install coming soon.** A `factory-code` package will land on npm once the first tagged release ships; until then, build from source.

## Documentation

- [docs/providers.md](./docs/providers.md) — full provider matrix, env vars, auth specifics
Expand All @@ -50,7 +53,7 @@ That's it. `factory` opens a picker for provider, model, and API key the first t
## Quick reference

```bash
factory --version # 0.1.0
factory --version # print version
factory --help # full flag list
factory # interactive picker
factory -p anthropic -m claude-sonnet-4-6 # one-shot
Expand Down
Loading