Terminal coding agent with a PydanticAI backend and first-party Go TUI
Project description
just-another-coding-agent
read_when: you need the repo overview, scope, or setup commands
Terminal coding agent with a PydanticAI backend and a first-party Go TUI.
This repo preserves the product shape of pi's coding agent while rebuilding it as a clean Python implementation around PydanticAI. It does not inherit pi-mono's monorepo layout, extension ecosystem, or migration burden.
It is intentionally narrow: coding-agent backend first, a thin first-party terminal UI, strict contracts, no fallbacks, and no compatibility glue. PydanticAI should provide as much of the agent machinery as possible; local code exists to define and enforce the coding-agent product contract.
Scope
- Headless coding-agent runtime
- Thin first-party terminal UI built on the same runtime
- File and shell tools
- Streaming run events
- Session persistence
- JSON-over-stdio RPC for non-Python consumers
Non-goals
- General-purpose agent framework work
- Backward compatibility layers
- Legacy migration shims
Project Layout
cmd/jaca/- Go TUI entrypointinternal/jaca/- Go TUI client, rendering, config, and RPC bridgesrc/just_another_coding_agent/- canonical Python packagesrc/just_another_coding_agent/runtime/- runtime and orchestration entrypointssrc/just_another_coding_agent/tools/- coding toolssrc/just_another_coding_agent/session/- session persistencesrc/just_another_coding_agent/rpc/- RPC transportsrc/just_another_coding_agent/contracts/- public contract helpers and schemastests/- unit tests first, e2e laterdocs/- scope, architecture, contracts, ADRs, development
Install
For normal use outside a repo checkout, prefer one of these published-package paths:
uv tool install just-another-coding-agent
jaca
uvx --from just-another-coding-agent jaca
If you already use pipx, that isolated tool path works too:
pipx install just-another-coding-agent
uv tool installis the persistent daily-use pathuvxis the ephemeral no-install path- published wheels already bundle
jaca-goandjaca-read-only-worker, so normal installs do not require a local Go toolchain - installed builds update explicitly with:
uv tool upgrade just-another-coding-agent
JACA does not auto-upgrade or self-reinstall on startup.
Installed builds may show a small in-app update chooser when a newer published
version is available. The current launch uses cached version info, and JACA
refreshes that cache in the background for the next launch so startup stays
fast. You can update immediately, snooze the notice for a day, or skip that
exact version until something newer is published. /version prints the
installed version, the newer published version when one is known, and the
exact upgrade command for your install lane.
Repo Setup
uv sync --extra dev --extra test
uv run ruff check .
uv run vulture src evaluations --min-confidence 80
go run honnef.co/go/tools/cmd/staticcheck@v0.6.0 ./...
uv run pytest
Or run the combined lint pass with:
make lint
That default uv sync --extra dev --extra test path is for the Python backend,
Terminal Bench flows, and headless evaluation work. It builds the persistent
jaca-read-only-worker, but it does not build the packaged jaca-go binary.
If you want to exercise the packaged TUI binary from a repo checkout, rebuild the package explicitly with Go enabled:
JACA_BUILD_TUI=1 uv sync --reinstall-package just-another-coding-agent --extra dev --extra test
Run
Launch the long-lived stdio RPC server with explicit backend configuration:
uv run just-another-coding-agent \
--model <provider:model> \
--workspace-root /abs/path/to/workspace \
--sessions-root /abs/path/to/sessions
The process reads one JSON RPC request per stdin line and writes one or more JSON lines to stdout.
Launch the first-party terminal UI:
uv run jaca
In a repo checkout, uv run jaca is the canonical development launcher. The
interactive launcher talks to the Python backend over stdio RPC.
In a live repo checkout, uv run jaca prefers the installed jaca-go binary
when it is present, and otherwise falls back to go run ./cmd/jaca when go
is available. That keeps normal development unblocked even if the packaged TUI
binary has not been rebuilt yet.
Outside a repo checkout, the installed jaca command launches the installed
jaca-go binary.
If uv run jaca says the Go TUI binary is missing and go is not available in
the repo checkout, rebuild the environment with:
JACA_BUILD_TUI=1 uv sync --reinstall-package just-another-coding-agent --extra dev --extra test
First Run
The TUI keeps non-secret provider, model, and trace preferences in
~/.jaca/config.json.
Provider secrets are backend-owned and stored in the local OS keychain by
default. When keychain storage is unavailable, JACA stores them in
~/.jaca/auth.json instead and explains why in the auth panel.
Environment variables remain the explicit override for headless, CI, and
evaluation flows.
On Linux/WSL, interactive /login requires a supported OS keychain backend
such as Secret Service via gnome-keyring.
On first launch without a usable saved login lane, JACA opens a centered chooser panel before chat. The supported login lanes are:
- ChatGPT subscription via
/login openai-codex - OpenAI API key via
/login openai - Anthropic API key via
/login anthropic
If a saved cloud-provider selection is still missing credentials, JACA starts
masked auth immediately at startup instead of waiting for the first
/login or /model command.
When auth starts, JACA opens a centered secure setup panel: provider-specific
labeling, masked input, no transcript/history capture for the secret, and
backend-owned storage on save.
On first run, the prompt footer also tells the user to press Tab to choose a
login lane or model directly from the prompt zone.
Inside jaca:
/login openai-codexstarts ChatGPT subscription login/login openaiand/login anthropicprepare~/.jaca/auth.jsonif needed and show the exact JSON snippet to paste/login statusshows whether each login lane is ready and where the current secret came from/login clear <provider>removes the stored local secret for that provider/modelshows runnable models first, marks ready rows with a check, and uses public-style labels such asgpt-5.4 | apiandgpt-5.4 | oauth/model <provider:model>switches the active model and aligns provider state to that model/name <text>assigns a durable backend-normalized session name such asauth-store-cleanupand keeps it unique within the current workspace/sessionshows the current durable session name, opaque session id, and any direct fork parent/trace offdisables tracing/trace localstores spans locally under~/.jaca/traces//trace logfireexports spans to Logfire
To continue a named or known session later:
jaca resume auth-store-cleanup
If you omit the reference, jaca resume shows the recent sessions from the
current workspace, even when there is only one session, caps the picker to the
most recent ten, and lets you choose one by number. This picker requires an
interactive terminal. Resumed and forked sessions also hydrate a bounded
recent-history preview into the transcript instead of trying to render the
entire saved session.
To branch a current-workspace session into a new one:
jaca fork auth-store-cleanup --name auth-store-cleanup-followup
If you omit the reference, jaca fork uses the same current-workspace picker as
jaca resume. Forked sessions keep durable lineage to their direct parent and
start as a new session with copied history instead of mutating the original
thread.
Tracing is off by default. Published installs already bundle the tracing
dependencies, and repo checkouts get them from the normal uv sync setup.
When /trace logfire is not ready yet, JACA tells the user to install
Logfire, run logfire auth, run logfire projects use <project>, retry
/trace logfire, and use /trace local until Logfire is ready.
If interactive login starts on a machine without a supported OS keychain backend, JACA goes directly to the local secret file flow and explains that it is doing so because keychain storage is unavailable.
For direct Go TUI development, pass the backend command explicitly:
go run ./cmd/jaca \
--backend-command-json='["uv","run","python","-m","just_another_coding_agent"]'
Docs
docs/README.mddocs/goal.mddocs/tui.mddocs/architecture.mddocs/contracts.mddocs/grounding.mddocs/development.mddocs/adr/
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file just_another_coding_agent-0.1.16.tar.gz.
File metadata
- Download URL: just_another_coding_agent-0.1.16.tar.gz
- Upload date:
- Size: 574.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
60a886a4b96855741831e7dc0b3845b463fce3b1bb036fed392a05511d2c6f71
|
|
| MD5 |
91fd33ffdb625183bcfddf9fed1cfe0e
|
|
| BLAKE2b-256 |
3200540aba247e1908d7d58aab7c4c6ce94648469898e1c1c8fbe8d29e22350b
|
Provenance
The following attestation bundles were made for just_another_coding_agent-0.1.16.tar.gz:
Publisher:
release.yml on SahilDahiya/just-another-coding-agent
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
just_another_coding_agent-0.1.16.tar.gz -
Subject digest:
60a886a4b96855741831e7dc0b3845b463fce3b1bb036fed392a05511d2c6f71 - Sigstore transparency entry: 1283174871
- Sigstore integration time:
-
Permalink:
SahilDahiya/just-another-coding-agent@2528a5b359faa5b5bef9cccc4dc6ad26da461d3b -
Branch / Tag:
refs/tags/v0.1.16 - Owner: https://github.com/SahilDahiya
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@2528a5b359faa5b5bef9cccc4dc6ad26da461d3b -
Trigger Event:
push
-
Statement type:
File details
Details for the file just_another_coding_agent-0.1.16-py3-none-win_amd64.whl.
File metadata
- Download URL: just_another_coding_agent-0.1.16-py3-none-win_amd64.whl
- Upload date:
- Size: 5.8 MB
- Tags: Python 3, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
188ee7f1a7b024164a38090456acac0cf7391f494ede5860479d2d33ac709b40
|
|
| MD5 |
e7af966d109d50fa0932fe6dda98dacc
|
|
| BLAKE2b-256 |
ce97ae02fadf7557121ac969000165a4ce0b4feccaa58fb1188ac9db76bb14d8
|
Provenance
The following attestation bundles were made for just_another_coding_agent-0.1.16-py3-none-win_amd64.whl:
Publisher:
release.yml on SahilDahiya/just-another-coding-agent
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
just_another_coding_agent-0.1.16-py3-none-win_amd64.whl -
Subject digest:
188ee7f1a7b024164a38090456acac0cf7391f494ede5860479d2d33ac709b40 - Sigstore transparency entry: 1283174913
- Sigstore integration time:
-
Permalink:
SahilDahiya/just-another-coding-agent@2528a5b359faa5b5bef9cccc4dc6ad26da461d3b -
Branch / Tag:
refs/tags/v0.1.16 - Owner: https://github.com/SahilDahiya
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@2528a5b359faa5b5bef9cccc4dc6ad26da461d3b -
Trigger Event:
push
-
Statement type:
File details
Details for the file just_another_coding_agent-0.1.16-py3-none-manylinux_2_17_x86_64.whl.
File metadata
- Download URL: just_another_coding_agent-0.1.16-py3-none-manylinux_2_17_x86_64.whl
- Upload date:
- Size: 5.5 MB
- Tags: Python 3, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2f2d7a6ce2a6c48df27d44e7ae7f95a42d03610e1d7e87c315c4986d8ab361af
|
|
| MD5 |
804fd580a0a4bc66b7a918f5381950ed
|
|
| BLAKE2b-256 |
518c094c6841fcebbf584022df4bb097ebaf2ba08b5d65a8fa024d660c0ae863
|
Provenance
The following attestation bundles were made for just_another_coding_agent-0.1.16-py3-none-manylinux_2_17_x86_64.whl:
Publisher:
release.yml on SahilDahiya/just-another-coding-agent
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
just_another_coding_agent-0.1.16-py3-none-manylinux_2_17_x86_64.whl -
Subject digest:
2f2d7a6ce2a6c48df27d44e7ae7f95a42d03610e1d7e87c315c4986d8ab361af - Sigstore transparency entry: 1283174882
- Sigstore integration time:
-
Permalink:
SahilDahiya/just-another-coding-agent@2528a5b359faa5b5bef9cccc4dc6ad26da461d3b -
Branch / Tag:
refs/tags/v0.1.16 - Owner: https://github.com/SahilDahiya
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@2528a5b359faa5b5bef9cccc4dc6ad26da461d3b -
Trigger Event:
push
-
Statement type:
File details
Details for the file just_another_coding_agent-0.1.16-py3-none-macosx_11_0_arm64.whl.
File metadata
- Download URL: just_another_coding_agent-0.1.16-py3-none-macosx_11_0_arm64.whl
- Upload date:
- Size: 5.1 MB
- Tags: Python 3, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8a801b26e32bf426ebd631c0b37244068f3ceedb21c324afd3e6bcd0ad683c07
|
|
| MD5 |
f55db14b75d016186c73836a04f55d4b
|
|
| BLAKE2b-256 |
8dad95595258bf963f1d850f3cbf811139f656e14045b94439b74af7edabc28f
|
Provenance
The following attestation bundles were made for just_another_coding_agent-0.1.16-py3-none-macosx_11_0_arm64.whl:
Publisher:
release.yml on SahilDahiya/just-another-coding-agent
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
just_another_coding_agent-0.1.16-py3-none-macosx_11_0_arm64.whl -
Subject digest:
8a801b26e32bf426ebd631c0b37244068f3ceedb21c324afd3e6bcd0ad683c07 - Sigstore transparency entry: 1283174921
- Sigstore integration time:
-
Permalink:
SahilDahiya/just-another-coding-agent@2528a5b359faa5b5bef9cccc4dc6ad26da461d3b -
Branch / Tag:
refs/tags/v0.1.16 - Owner: https://github.com/SahilDahiya
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@2528a5b359faa5b5bef9cccc4dc6ad26da461d3b -
Trigger Event:
push
-
Statement type:
File details
Details for the file just_another_coding_agent-0.1.16-py3-none-macosx_10_12_x86_64.whl.
File metadata
- Download URL: just_another_coding_agent-0.1.16-py3-none-macosx_10_12_x86_64.whl
- Upload date:
- Size: 5.3 MB
- Tags: Python 3, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
241c203145c2fca9680075b64b20c1daac5987f7febd06edff29fd692cefa3d2
|
|
| MD5 |
75df146739825b50b41db7990be4bb55
|
|
| BLAKE2b-256 |
c7f20883babf95171efc0992b6cc1b6a91b7a629ab630e928ae60a313ef5319e
|
Provenance
The following attestation bundles were made for just_another_coding_agent-0.1.16-py3-none-macosx_10_12_x86_64.whl:
Publisher:
release.yml on SahilDahiya/just-another-coding-agent
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
just_another_coding_agent-0.1.16-py3-none-macosx_10_12_x86_64.whl -
Subject digest:
241c203145c2fca9680075b64b20c1daac5987f7febd06edff29fd692cefa3d2 - Sigstore transparency entry: 1283174891
- Sigstore integration time:
-
Permalink:
SahilDahiya/just-another-coding-agent@2528a5b359faa5b5bef9cccc4dc6ad26da461d3b -
Branch / Tag:
refs/tags/v0.1.16 - Owner: https://github.com/SahilDahiya
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@2528a5b359faa5b5bef9cccc4dc6ad26da461d3b -
Trigger Event:
push
-
Statement type: